以南非為例,談談落後指標、先行指標等

https://www.storm.mg/investreview2020/article/2907252

我們先用落後指標來檢視 , 南非的狀況

落後指標:失業率 

為什麼一開場先用落後指標,無非是告訴大家,這指標落後於基本面,是一個很好的檢視方式!

如果過去政府有對經濟做出貢獻與努力,最終失業率就會下降

但是很遺憾的,這個南非政府似乎無能改善!

下圖為失業率:數據是29%,截至 2020 年的資料,是近十年最高了


落後的指標看過去是否能夠改善,先行的指標看未來是否有機會改善

先行指標:製造業PMI 

目前的數據是45.7,這是全球前幾名的低!

PMI 低於50就是進入衰退的前兆,45.7這個數字也預告南非未來也不太樂觀!


南非製造業PMI 低於50。

什麼樣的環境造成南非這麼慘呢?

看一個國家就至少也要看他的基礎建設是否完善,

南非的罩門在哪?在於電力不足?因此百業蕭條。


如果一個國家缺電,您想能投資什麼產業?

半導體?不可能。生產線一停電要損失多少?

製造業?產品做一半停電怎麼辦?


所以最後南非可以依賴的就是礦業,一直都是礦業。


也因為南非電力不穩定,甚至導致國家信評可能被降低到更低的垃圾等級,簡稱垃圾中的垃圾 ......


再看看影響南非幣的主要外部因素:美元

美元強,南非幣弱;反之...


南非幣的經常帳:自從2008年以來沒有正數

因此國家缺錢怎麼辦?只好借外債了。以債養債這個國家很慘!

債務占國家 GDP 比重也隨著外債的增加持續高漲!





結論:

1. 南非從基本面來看,離好轉還有很長遠的距離。

2. 如果基本面要轉好,至少南非的電力問題要搞定,而南非電力如果政府不救,就是快要破產的公司了,一個國家搞成這樣不容易!

3. 南非幣可以投資嗎?如果您很喜歡投機的話可以考慮(但是光換匯成本就超過 3%)

4. 南非的展望:南非是新興市場中前五名脆弱的,只要美元轉強,那麼南非可能就是受害最嚴重的國家之一。








開發 iOS,PCH 檔案的配置及使用

https://www.itread01.com/p/398294.html

在 Xcode 6 之前,建立一個新工程時 Xcode 會在 Supporting files 資料夾下面自動建立一個「工程名-Prefix.pch」檔案,這也是一個頭檔案,pch 標頭檔案的內容能被專案中的其他所有原始檔共享和訪問。是一個預編譯檔案。

PCH 檔案的作用

1. 用來包含一些使用頻率較高的標頭檔案

2. 存放一些全域性的巨集

3. 因為是預編譯檔案,會增加編譯時間,所以在 Xcode 6 以後,蘋果為了避免濫用 pch 檔案,不再自動生成。


在 PCH 中定義的巨集會自動新增到所有的檔案中,所以新增的時候要特別注意,一定要區分 C 檔案和 OC 檔案,如果不區分,把 OC 巨集用的內碼表新增到 C 檔案中,C 檔案無法識別 OC 中的框架就會報錯。

詳見課程影片:

https://www.youtube.com/watch?v=PI3hbyaYT2s&list=PLzKtnppOmiXAlARyp-aRjP0e-RsWiS4UW&index=12

還有如何區分 Debug 和 Release 等細節




iOS 開發常用巨集

https://codertw.com/ios/327901/

Objective-C


//字串是否為空
#define kStringIsEmpty(str) ([str isKindOfClass:[NSNull class]] || str == nil || [str length] < 1 ? YES : NO )
//陣列是否為空
#define kArrayIsEmpty(array) (array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0)
//字典是否為空
#define kDictIsEmpty(dic) (dic == nil || [dic isKindOfClass:[NSNull class]] || dic.allKeys == 0)
//是否是空物件
#define kObjectIsEmpty(_object) (_object == nil \
|| [_object isKindOfClass:[NSNull class]] \
|| ([_object respondsToSelector:@selector(length)] && [(NSData *)_object length] == 0) \
|| ([_object respondsToSelector:@selector(count)] && [(NSArray *)_object count] == 0))
//獲取螢幕寬度與高度
#define kScreenWidth \
([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)] ? [UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale : [UIScreen mainScreen].bounds.size.width)
#define kScreenHeight \
([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)] ? [UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale : [UIScreen mainScreen].bounds.size.height)
#define kScreenSize \
([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)] ? CGSizeMake([UIScreen mainScreen].nativeBounds.size.width/[UIScreen mainScreen].nativeScale,[UIScreen mainScreen].nativeBounds.size.height/[UIScreen mainScreen].nativeScale) : [UIScreen mainScreen].bounds.size)
//一些縮寫
#define kApplication  [UIApplication sharedApplication]
#define kKeyWindow   [UIApplication sharedApplication].keyWindow
#define kAppDelegate  [UIApplication sharedApplication].delegate
#define kUserDefaults  [NSUserDefaults standardUserDefaults]
#define kNotificationCenter [NSNotificationCenter defaultCenter]
//APP版本號
#define kAppVersion [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]
//系統版本號
#define kSystemVersion [[UIDevice currentDevice] systemVersion]
//獲取當前語言
#define kCurrentLanguage ([[NSLocale preferredLanguages] objectAtIndex:0])
//判斷是否為iPhone
#define kISiPhone (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
//判斷是否為iPad
#define kISiPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
//獲取沙盒Document路徑
#define kDocumentPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
//獲取沙盒temp路徑
#define kTempPath NSTemporaryDirectory()
//獲取沙盒Cache路徑
#define kCachePath [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]
//判斷是真機還是模擬器
#if TARGET_OS_IPHONE
//真機
#endif
#if TARGET_IPHONE_SIMULATOR
//模擬器
#endif
//開發的時候列印,但是釋出的時候不列印的NSLog
#ifdef DEBUG
#define NSLog(...) NSLog(@"%s 第%d行 \n %@\n\n",__func__,__LINE__,[NSString stringWithFormat:__VA_ARGS__])
#else
#define NSLog(...)
#endif
//顏色
#define kRGBColor(r, g, b)  [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
#define kRGBAColor(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(r)/255.0 blue:(r)/255.0 alpha:a]
#define kRandomColor KRGBColor(arc4random_uniform(256)/255.0,arc4random_uniform(256)/255.0,arc4random_uniform(256)/255.0)
#define kColorWithHex(rgbValue) \
[UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16)) / 255.0 \
green:((float)((rgbValue & 0xFF00) >> 8)) / 255.0 \
blue:((float)(rgbValue & 0xFF)) / 255.0 alpha:1.0]
//弱引用/強引用
#define kWeakSelf(type) __weak typeof(type) weak##type = type;
#define kStrongSelf(type) __strong typeof(type) type = weak##type;
//由角度轉換弧度
#define kDegreesToRadian(x)  (M_PI * (x) / 180.0)
//由弧度轉換角度
#define kRadianToDegrees(radian) (radian * 180.0) / (M_PI)
//獲取一段時間間隔
#define kStartTime CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
#define kEndTime NSLog(@"Time: %f", CFAbsoluteTimeGetCurrent() - start)

1.定義尺寸類的巨集


DimensMacros.h
//狀態列高度
#define STATUS_BAR_HEIGHT 20
//NavBar高度
#define NAVIGATION_BAR_HEIGHT 44
//狀態列 + 導航欄 高度
#define STATUS_AND_NAVIGATION_HEIGHT ((STATUS_BAR_HEIGHT)   (NAVIGATION_BAR_HEIGHT))
//螢幕 rect
#define SCREEN_RECT ([UIScreen mainScreen].bounds)
#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
#define CONTENT_HEIGHT (SCREEN_HEIGHT - NAVIGATION_BAR_HEIGHT - STATUS_BAR_HEIGHT)
//螢幕解析度
#define SCREEN_RESOLUTION (SCREEN_WIDTH * SCREEN_HEIGHT * ([UIScreen mainScreen].scale))
//廣告欄高度
#define BANNER_HEIGHT 215
#define STYLEPAGE_HEIGHT 21
#define SMALLTV_HEIGHT 77
#define SMALLTV_WIDTH 110
#define FOLLOW_HEIGHT 220
#define SUBCHANNEL_HEIGHT 62

2.定義沙盒目錄檔案的巨集


PathMacros.h
//檔案目錄
#define kPathTemp          NSTemporaryDirectory()
#define kPathDocument        [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]
#define kPathCache         [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
#define kPathSearch         [kPathDocument stringByAppendingPathComponent:@"Search.plist"]
#define kPathMagazine        [kPathDocument stringByAppendingPathComponent:@"Magazine"]
#define kPathDownloadedMgzs     [kPathMagazine stringByAppendingPathComponent:@"DownloadedMgz.plist"]
#define kPathDownloadURLs      [kPathMagazine stringByAppendingPathComponent:@"DownloadURLs.plist"]
#define kPathOperation       [kPathMagazine stringByAppendingPathComponent:@"Operation.plist"]
#define kPathSplashScreen      [kPathCache stringByAppendingPathComponent:@"splashScreen"]
#endif

3.工具類的巨集


UtilsMacros.h
//Log utils marco
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#ifdef DEBUG
#define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define DLog(...)
#endif
#ifdef DEBUG
#define ULog(...)
//#define ULog(fmt, ...) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"%s\n [Line %d] ", __PRETTY_FUNCTION__, __LINE__] message:[NSString stringWithFormat:fmt, ##__VA_ARGS__] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; }
#else
#define ULog(...)
#endif
//System version utils
#define SYSTEM_VERSION_EQUAL_TO(v)         ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)       ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)         ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)   ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
// 獲取RGB顏色
#define RGBA(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]
#define RGB(r,g,b) RGBA(r,g,b,1.0f)
#define IsPortrait ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait || [UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortraitUpsideDown)
#define IsNilOrNull(_ref)  (((_ref) == nil) || ([(_ref) isEqual:[NSNull null]]))
//角度轉弧度
#define DEGREES_TO_RADIANS(d) (d * M_PI / 180)
//大於等於7.0的ios版本
#define iOS7_OR_LATER SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")
//大於等於8.0的ios版本
#define iOS8_OR_LATER SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")
//iOS6時,導航VC中view的起始高度
#define YH_HEIGHT (iOS7_OR_LATER ? 64:0)
//獲取系統時間戳
#define getCurentTime [NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]]

4.通知Notification相關的巨集


NotificationMacros.h
//系統Notification定義
#define TNCancelFavoriteProductNotification   @"TNCancelFavoriteProductNotification"   //取消收藏時
#define TNMarkFavoriteProductNotification    @"TNMarkFavoriteProductNotification"    //標記收藏時
#define kNotficationDownloadProgressChanged   @"kNotficationDownloadProgressChanged"   //下載進度變化
#define kNotificationPauseDownload       @"kNotificationPauseDownload"        //暫停下載
#define kNotificationStartDownload       @"kNotificationStartDownload"        //開始下載
#define kNotificationDownloadSuccess      @"kNotificationDownloadSuccess"       //下載成功
#define kNotificationDownloadFailed       @"kNotificationDownloadFailed"       //下載失敗
#define kNotificationDownloadNewMagazine    @"kNotificationDownloadNewMagazine"
服務端API介面的巨集
APIStringMacros.h
//////////////////////////////////////////////////////////////////////////////////////////////////
//介面名稱相關
#ifdef DEBUG
//Debug狀態下的測試API
#define API_BASE_URL_STRING   @"http://boys.test.companydomain.com/api/"
#else
//Release狀態下的線上API
#define API_BASE_URL_STRING   @"http://www.companydomain.com/api/"
#endif
//介面
#define GET_CONTENT_DETAIL   @"channel/getContentDetail" //獲取內容詳情(含上一個和下一個)
#define GET_COMMENT_LIST    @"comment/getCommentList"  //獲取評論列表
#define COMMENT_LOGIN      @"comment/login"      //獲取評論列表
#define COMMENT_PUBLISH     @"comment/publish"     //釋出評論
#define COMMENT_DELETE     @"comment/delComment"    //刪除評論
#define LOGINOUT        @"common/logout"      //登出
還有很多其他型別的巨集,此處不一一列舉
建立一個import所有巨集相關的檔案Macros.h
Macros.h
#import "UtilsMacros.h"
#import "APIStringMacros.h"
#import "DimensMacros.h"
#import "NotificationMacros.h"
#import "SharePlatformMacros.h"
#import "StringMacros.h"
#import "UserBehaviorMacros.h"
#import "PathMacros.h"
在xcode專案的pch檔案中,匯入Macros.h檔案
XcodeProjectName-Prefix.pch
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "Macros.h"
#endif



Xcode 多版本共存

https://nickyuu.github.io/2017/09/20/14/


1. 手動下載 Xcode

https://developer.apple.com/download/more/


2. Xcode 多版共存

將舊的 Xcode 重新命名加上版本號


下載好新的 Xcode 後,解壓縮,解壓後再把新的 Xcode 拉到應用程式內重新命名


3. 切換預設 Xcode 版本

打開 terminal,使用 xcode-select 指令切換預設 Xcode 版本,後面參數為路徑:

1
2
3
4
# Xcode 8
sudo xcode-select -s /Applications/Xcode8.app
# Xcode 9
sudo xcode-select -s /Applications/Xcode9.app


查看版本:

在終端中使用下列指令

xcodebuild -version



未來聯準會不會輕易升息,宣告長期低利率時代的來臨

聯準會 (Fed) 主席鮑爾 (Jerome Powell) 週四 (2020/8/27) 全球央行年會上宣布 Fed 重大政策的改變。Fed 將採取平均通膨目標架構,來支持勞動力市場和更廣泛的經濟,這意味「長期零利率」時代即將來臨。

聯準會主席鮑爾週四發表演說時宣布,Fed 正式同意一項「平均通膨目標」政策,認為這是對貨幣政策的穩健更新。

鮑爾稱,Fed 尋求實現平均 2% 通膨率,因此判斷通膨率持續低於 2% 時期之後,適當的貨幣政策可能會在一段時間內將通膨目標鎖定在略高於 2% 的水準。

鮑爾還提到另一政策變化,即調整利率政策將根據就業率相對於最高水平的「缺口 (shortfalls)」來決定」,而不是根據「偏差」來決定。

鮑爾說,儘管此一政策轉變似乎只是小事,但 (實際上) 意義重大。這一變化反映 Fed 對強勁勞動力市場帶來好處的理解,特別是對中、低所得的社群。

鮑爾解釋,這項重大政策變化是反映 Fed 近來學到的教訓,即便失業率降至歷史低點,通膨率也沒有如預期上升,顯示強勁的就業市場可以在不引發通膨的情況下得到維持。

換言之,未來當失業率下降、通膨率不同時攀升時,Fed 就不太會傾向於升息。

鮑爾說,Fed 不會為失業率設定具體目標,但允許決定充分就業的條件,並認為 2% 仍是合理的通膨目標。

鮑爾進一步提醒,許多人認為 Fed 想要推高通膨率,這有違常規,然而,持續過低的通膨率可能對經濟構成重大風險。

鮑爾最終並未提到希望 (允許) 通膨天花板升高到何種程度,達拉斯聯準銀行總裁卡普蘭 (Robert Kaplan) 週四受訪時透露,大約 2.25%-2.5% 區間。

各方看法

未來聯準會不會輕易升息,宣告長期低利率時代的來臨。

嘉信理財固定收益部門負責人 Kathy Jones 說:「目前,美國的失業率遠高於 10%。短期內出現大幅通膨調升的可能性相當渺茫。無論政策是否改變,聯準會都將在未來幾年保持零利率。」

《CNBC》財經節目主持人 Jim Cramer 稱,鮑爾站在多頭這一邊。

在經濟下滑的時候刺激通膨率上升看似很怪,但聯準會、經濟學家更怕的是落入像日本一樣的狀況:通貨緊縮下,經濟成長遲緩,不管怎麼刺激經濟都沒有用。聯準會認為,疫情導致高失業率,高風險會出現通縮。除此之外,目前的低利率讓政策制定者的轉圜空間很小,進一步寬鬆政策是必要的。

更不用提,自從2009年中以來,除了其中兩年,其他時間通膨率都低於2%目標。諮詢公司Capital Economics經濟學家艾希沃夫(Paul Ashworth)指出,最要緊的是,貨幣政策已經接近極限,雖然聯準會並不會公開承認,但從他們鼓吹國會採取更多的財政刺激措施,就可以略知一二。

策略轉向的附帶條件是長期的低利率。加拿大蒙特婁銀行(BMO)資深固定收益策略師希爾(Jon Hill)指出:「我們將會停留在零利率更長時間,央行將採取更多積極措施來達成通膨指令。在過去他們習慣搶先升息以避免來自通膨的壓力,現在他們將轉變為等到持續通膨後才行動。

這是一種結果導向的策略,聯準會達到穩定通膨率和失業率的目標前,將不會升息。零利率下限(Zero lower bound)過去被視為反常,現在則成為標準措施。前白宮經濟學家弗曼(Jason Furman)更直指:「如果5年後利率仍為零,我也不會感到驚訝。」

德意志銀行(Deutsche Bank)全球經濟研究部門主管霍普(Peter Hooper)預測,如果疫苗研發和施打順利,美國GDP 2022年上半可能就會回到2020年第一季水準,比以前經濟衰退時復甦更快。

聯準會的政策對股市是利多,但也可能催生泡沫化。摩根士丹利(Morgan Stanley)股票策略師威爾遜(Michael Wilson)表示:「接下來股市可能會有一波成長恐慌,接下來是長達幾週或幾個月的利率恐慌,這最終可能使我們對美國股票指數進行首次可交易的修正。」


iOS 開發的重點知識

https://chars.tech/blog/ios-interview/

笔试面试是程序员应聘绕不过的坎,想进大厂就一定要有知识储备量,而这个却是最佳的考察方式。笔者分享一些收集的iOS面试题,答案仅供参考,如有错误,还请指正。


第一部分

1.Objective-C语言的基本特点?


Objective-C语言是C语言的一个超集,只是在C的基础之上添加了面向对象(OO)的特性;Objective-C与Java语言相同都是单继承,这一点与C++语言不同(多重继承),这一点可以参看之前有关讲解继承的文章;Objective-C不支持命名空间,取而代之的是在类名之前添加前缀,以此来区分。


2.#include与#import的区别,#import与@class的区别?


1)#include和#import效果相同,只是后者不会引起交叉编译,确保头文件只会被导入一次。


2)#import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你。使用#import编译效率高,防止相互包含的编译错误。


3.简述类目优缺点,如果覆盖本类或者父类的方法会出现什么问题?


优点:不需要通过增加子类而增加现有类的行为(方法),且类目中的方法与原始类方法基本没有区别。


缺点:无法向类目添加实例变量。覆盖原始类方法后,原始类的方法没办法调用。


4.简述内存管理基本原则?


如果使用alloc、copy(mutableCopy)或者retain一个对象时,你就有义务向它发送一条release或autorelease消息。其他方法创建的对象,不需要由你来管理内存。


5.什么是ARC技术?与GC是否相同?


ARC是Automatic Reference Counting的简称,我们称之为自动引用计数,是iOS5.0之后推出的内存管理的新特性。本质上还是使用引用计数来管理对象,只是我们在编写代码时,不需要向对象发送release或autorelease方法,也不可以调用dealloc方法,编译器会在合适的位置自动给用户生成release(autorelease)消息。GC是Garbage Collection,内存垃圾回收机制,ARC比GC性能好。


6.iOS中是否支持垃圾回收机制?


iOS开发只支持MRC与ARC,Mac开发支持GC垃圾回收机制,10.8之后弃用了GC,推荐使用ARC。


7.深、浅复制的基本概念以及区别?


浅复制:只复制对象本身,不对里面的属性复制。


深复制:不仅复制对象本身,对象持有的属性对象也做复制。


8.内存中的堆区和栈区的差别?


栈区(stack)由编译器自动分配释放,存放方法(函数)的参数值,局部变量的值等。


堆区(heap)一般由程序员分配与释放,若程序员不释放,则会内存溢出。


9.用户自定义了一个对象,如何实现拷贝(可变和不可变拷贝)?


必须实现copying和mutableCopying协议,表示返回一个不可变和可变的对象。否则,程序将会出现异常。


-(id)copyWithZone:(NSZone *)zone {

Person *person = [[self Class] allocWithZone:zone];

person->age = self.age;

person->name = self.name;

return person;

}

-(id)mutableCopyWithZone:(NSZone *)zone;

10.定义属性时,什么时候用assign、retain、copy和nonatomic?


assign:普通赋值,一般常用于基本数据类型,常见委托设计模式,以此来防止循环引用。


retain:保留计数,获得了对象的所有权。引用计数在原有基础上加1。


copy:用来复制对象,一般字符串使用,Foundation中的不可变对象使用,效果相当于retain,只是引用计数加1。


nonatomic:非原子性访问,不加同步,多线程并发访问会提高性能。


11.strong和weak,_unsafe_unretained与weak的区别?


strong:强引用,在ARC中告诉编译器帮助我们自动插入retain。


weak:弱引用,是普通赋值,相当于手动管理内存的assign。


_unsafe_unretained:与weak功能一致,区别在于当指向的对象销毁后,weak会将变量置为nil,防止调用野指针。


12.ARC存在内存泄露吗?


ARC中如果内存管理不当的话,同样会存在内存泄露。例如,ARC中也会循环引用导致内存泄露;Objective-C对象与CoreFoundation类之间桥接时,管理不当也会产生内存泄露。


13.当我们释放对象时,为什么需要调用[super dealloc]方法?


子类是继承自父类,那么子类中有一些实例变量(对象),是继承自父类的,因此,我们需要调用父类方法,将父类所拥有的实例进行释放。


14.自动释放池是什么,如何工作?


自动释放池是NSAutorelease类的一个实例,当向一个对象发送autorelease消息时,该对象会自动入池,待池销毁时,将会向池中所有对象发送一条release消息,释放对象。


15.为什么delegate(代理)属性都是assign而不是retain的?


防止循环引用,以至对象无法得到正确的释放。


16.delegate使用weak还是strong?为什么?苹果有delegate使用strong的类吗?为什么?


delegate一般使用weak,主要是为了避免出现循环引用。苹果官方NSURLSession类中的delegate使用strong引用。因为苹果要求所有的网络请求都用同一个对象去发送,那么这个对象就封装为一个单例对象。


第二部分

1.iOS开发中数据持久性有哪几种?


plist文件写入,对象归档,sqlite3数据库,CoreData。


2.什么是KVC和KVO?它们之间的关系是什么?


KVC:键值编码,是一种间接访问对象实例变量的机制,该机制可以不通过存取方法就可以访问对象的实例变量。


KVO:键值观察,是一种能使得对象获取到其他对象属性变化的通知机制。 实现KVO键值观察模式,被观察的对象必须使用KVC键值编码来修改它的实例变量,这样才能被观察者观察到。因此,KVC是KVO的基础或者说KVO的实现是建立在KVC的基础之上的。


3.简述常见的设计模式?


单例模式、代理设计、观察者(通知)、工厂方法、模板方法。


4.内存管理在dealloc方法中用release方法与self.xx=nil哪个好?


使用self.xx=nil更好,因为先调用了release方法,而且还将变量设置为nil,这样就更安全的释放对象,防止野指针调用。


5.线程与进程的区别和联系?


一般的应用程序是单个进程,也有多进程(Chrome),进程是个静态的容器,里面容纳了很多个线程,线程是一系列方法的线性执行路径。


6.Objective-C语言的优缺点?


优点:类目、动态识别、支持C语言、Objective-C与C++可以混编。


缺点:不支持命名空间、不支持运算符重载、不支持多重继承。


7.代理delegate、通知Notification与block的使用区别?


delegate和block一般是用于两个对象一对一之间的通信交互,delegate需要定义协议方法,代理对象实现协议方法,并且需要建立代理关系才可以实现通信。block更加简洁,不需要定义繁琐的协议方法,但是如果通信事件比较多的话,建议使用delegate。 Notification主要用于一对多情况下通信,而且,通信对象之间不需要建立关系,但是使用通知,代码可读性差。


8.控制器ViewController的loadView、viewDidLoad、viewWillApear和viewDidUnload分别是在什么时候调用?


loadView:当控制器的根视图view为空,且此view被访问时调用。


viewDidLoad:loadView调用之后被调用。


viewWillApear:当控制器根视图view被添加到父视图上时调用。


viewDidUnload:iOS6.0之前,当内存警告时,先卸载视图,再调用 viewDidUnload来释放内存。


9.@synthesize和@dynamic的区别?


@synthesize:系统自动生成getter和setter属性声明。


@dynamic:告诉编译器,属性的获取与赋值方法由用户自己实现,不自动生成。


10.事件响应者链的概念?


响应者链表示一系列的响应者对象。事件被交由第一响应者对象处理,如果第一响应者不处理,事件被沿着响应者链向上传递,交给下一个响应者。一般来说,第一响应者是个视图对象或者其子类对象,当其被触摸后事件交由它处理,如果它不处理,事件会被传递给它的视图控制器对象(如果存在),然后是它的父视图对象(如果存在),以此类推,直到顶层视图。接下来会沿着顶层视图到窗口(UIWindow对象),再到程序(UIApplication对象)。如果整个过程都没有响应这个事件,该事件被丢弃。一般情况下,在响应者链中只要有对象处理事件,事件就停止传递。但有时候可以在视图的响应方法中根据一些条件判断来决定是否需要继续传递事件。


11.C语言中的static变量和static函数有什么作用?


1)表示变量是静态存储变量,表示变量存放在静态存储区。


2)加在函数前面的时候表示该函数是内部连接,只在本文件中有效,别的文件中不能使用该函数。


12.指针题


1)int a; //一个数值。

2)int *a; //一个指向数值的指针。

3)int **a; //一个指向指针的指针。

4)int a[10]; //一个有10个指针的数组,该指针是指向一个整型数的。

5)int *a[10]; //一个有10个指针的数组,该指针是指向一个整型数的。

6)int (*a)[10]; //一个指向有10个整型数数组的指针。

7)int (*a)(int); //一个指向函数的指针,该函数有一个整型参数并返回一个整型数。

8)int (*a[10])(int); //一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数。

13.写一个NSString类的实现?


+(id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding {

NSString *obj;

obj = [self allocWithZone:NSDefaultMallocZone()];

obj = [obj initWithCString:nullTerminatedCString encoding:encoding];

return autorelease(obj);

}

14.Objective-C与C如何混用?Objective-C与C++如何混用?


实现文件的扩展名.m改成.mm即可,但cpp文件必须只能使用C/C++代码,而且cpp文件include的头文件中,也不能出现Objective-C的代码,因为cpp只能写C++的代码。


15.Objective-C中有私有方法和私有变量吗?


使用private修饰的全局变量是私有的变量。


Objective-C在语法上没有设计私有的方法,不过可以通过延展在实现文件里定义方法作为私有的方法。但不是真正意义上的私有方法,也是可以调用的,只是外部不可见而已。


第三部分

1.下面关键字const有什么含义?


const int a;

int const a;

const int *a;

int * const a;

前两个的作用是一样的,a是一个常整型数。


第三个意味着a是一个指向常整型数的指针(即整型数是不可修改的,但指针可以)。


第四个意味着a是一个指向整型数的常指针(即指针指向的整型数是可以修改的,但指针是不可修改的)。


2.C语言中extern的作用,extern “C”的作用?


1)extern可以置于变量或者函数前,以标示变量或函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。


2)C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。


3.Objective-C是如何管理内存的?


Objective-C语言是使用引用计数来管理一个对象的生命周期,当对象被其他“人”使用的时候引用计数加1,不使用时减1,当此对象的引用计数为0时,则对象被系统回收。


4.什么是动态绑定(多态)?


动态绑定是面向对象特性之一多态的体现,声明一个变量,在运行的时候可以绑定不同的对象,比如在方法的参数中声明这样一个变量UIView *view,运行的时候,我们可以根据不同的应用场景给view变量传入不同的对象,可以传递一个UIButton对象,也可以传入UIImageView对象。


5.如何理解delegate?


delegate,又称为委托或代理,它是一种设计模式。delegate主要用于两个对象之间的通信交互,并且解除两个通信对象的耦合性,iOS中大量使用了delegate设计,主要用于视图与使用对象之间的通信交互。


6.block与函数有何异同?block有何优点?


1)block类似于C里面的函数指针,都可以作为参数进行传递,用于回调。但是block的实现可以定义在方法中,函数则不可以。


2)block语法简洁,可以在方法中定义实现,这样可以访问方法中的局部变量,使代码更加的紧凑,结构化。


7.为什么标准头文件都有类似以下的结构?


#ifndef __INCvxWorksh

#define __INCvxWorksh

#ifdef __cplusplus

extern "C" {

#endif

/*...*/

#ifdef __cplusplus

}

#endif

#endif /*__INCvxWorksh*/

显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif”的作用是防止该头文件被重复引用。


8.CocoaTouch框架?


UIKit、Foundation、CoreGraphic、CoreAnimation


1)音频和视频:Core Audio、OpenAL、Media Library、AV Foundation


2)数据管理:Core Data、SQLite


3)图形和动画:Core Animation、OpenGL ES、Quartz 2D、Core Graphic


4)用户应用:Address Book、Core Location、Map Kit、Store Kit


9.栈结构与队列的区别?


栈(stack):限定只能在表的一端进行插入和删除操作的线性表。


队列(queue):限定只能在表的一端插入和在另一端进行删除操作的线性表。


1)队列先进先出,栈先进后出。


2)对插入和删除操作的“限定”不同。


3)遍历数据速度不同。队列遍历数据的速度要快得多。


10.Objective-C中有无多重继承?如何实现多重继承?


Objective-C是没有多重继承的。


Cocoa中所有的类都是NSObject的子类,多继承在这里是用protocol委托代理来实现的。


面向对象语言大部分都是单继承,例如:Java、C#。


C++支持多继承。


11.static全局变量与普通的全局变量的区别?局部变量呢?函数呢?


1)static全局变量与普通全局变量的区别:static全局变量只初始化一次,防止在其他文件单元中被引用。


2)static局部变量与普通局部变量的区别:static局部变量只被初始化一次,下一次依据上一次结果值。


3)static函数与普通函数的区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。


12.什么是类目与延展?


类目:为已知的类增加新的方法。


延展:通知在本类的定义里使用类目来声明私有方法。


13.Objective-C中的协议和Java中的接口区别?


协议定义的方法,可以设置可选实现和必须实现。


接口则是必须全部实现。


14.在一个对象的方法里self.name=”object”和name=”object”有什么不同?


前者调用的是设置器方法,后者是普通赋值。


15.单例设计模式的实现?为什么使用单例设计?


static File *instance = nil;

@implementation File

//获取单例的方法

+(id)shareInstance {

@synthesize (self) {

if(instance == nil) {

instance = [[File alloc] init];

}

}

return instance;

}

//覆写allocWithZone、copyWithZone、retain、release和autorelease方法,目的是限制这个类只创建一个对象

为什么使用单例设计?


1)单例设计是用来限制一个类只能创建一个对象,那么此对象中的属性可以存储全局共享的数据,所有的类都可以访问、设置此单例对象中的属性数据。


2)如果一个类创建的时候非常的耗费性能,那么此类如果能满足要求,可以设置为单例节约性能。


第四部分

1.层CALayer和UIView的区别是什么?


两者最大的区别是,图层不会直接渲染到屏幕上。UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它,它本身是由CoreAnimation来实现的,它真正绘图的部分是由一个CALayer类来管理的。UIView本身更像是一个CALayer的管理器。一个UIView上可以有多个CALayer,每个CALayer显示一种东西,增强UIView的展现能力。


2.什么是GCD?


GCD是Apple开发的一个多核编程的较新的解决方法。在Mac OS X 10.6雪豹中首次推出,并引入到iOS4.0。GCD是一个替代诸如NSThread等技术的很高效和强大的技术。GCD完全可以处理诸如数据锁定和资源泄漏等复杂的异步编程问题。


3.TCP/UDP的区别和联系?


1)TCP的全称为传输控制协议,这种协议可以提供面向连接的、可靠的、点到点的通信。


2)UDP的全称为用户数据报协议,它可以提供非连接的不可靠的点到多点的通信。


3)用TCP还是UDP,需要看程序注重哪一个方面,需要可靠还是快速。


4.Socket连接和Http连接的区别?


Http连接:Http连接就是所谓的短链接,即客户端向服务器发送一次请求,服务器响应后连接即会断掉。


Socket连接:Socket连接就是所谓的长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉。


5.什么是TCP连接的三次握手?


第一次握手:客户端发送SYN包(SYN=j)到服务器,并进入SYN_SEND状态,等待服务器确认。


第二次握手:服务器收到SYN包,必须确认客户的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。


第三次握手:客户端接收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。


6.frame和bounds的区别?


frame指的是:该view在父view坐标系统中的位置大小(参照点是父视图的坐标系统)。


bounds指的是:该view在本身坐标系统中的位置和大小(参照点是本身的坐标系统)。


7.如何理解MVC设计模式?


MVC是一种架构设计,M表示数据模型,V表示视图,C表示控制器。


数据模型:负责存储、定义、操作数据。


视图:用来展示数据给用户,和用户进行操作交互。


控制器:它是M与V的协调者,控制器获取数据,将数据交给视图去展示。


8.控制器的xib是怎么加载的?


当UIViewController的loadView被调用时,在此方法中,通过NSBundle加载xib,先通过控制器的类名作为xib的文件名加载此xib文件。如果找到此xib文件,则加载为view对象作为控制器的根视图,如果没有xib文件,则通过alloc创建一个view对象作为根视图。


9.控制器如何处理系统内存不足警告?


内存不足时,系统会调用控制器didReceiveMemoryWaring方法通知控制器内存不足。iOS6.0与6.0之前的处理方式不一样。


1)iOS6.0之前:调用didReceiveMemoryWaring后,将self.view设置为nil,并且再调用viewDidUnload方法,在此方法中我们应该释放子视图。


2)iOS6.0之后:调用didReceiveMemoryWaring后,不再调用viewDidUnload方法,则应该在didReceiveMemoryWaring方法中手动将self.view=nil,并且释放子视图。


10.iOS中对象间有哪些通信方式?


代理delegate、block、通知和KVO。


11.block在内存管理上的特点?需要注意循环引用,如何解决循环引用?


1)block中使用了局部对象,则会将此对象retain,引用了当前对象的属性或者方法,则会将当前对象retain。


2)解决循环引用:将当前对象赋值给一个局部变量,并且使用__block关键字修饰该局部变量,使用该变量访问当前对象的属性和方法。


12.Objective-C中有线程池(线程队列)吗?NSOperationQueue是如何管理线程的?


NSOperationQueue是Objective-C的线程池,线程池中可以存放多个线程。


NSOperationQueue可以管理线程的并发数,还可以管理线程间的优先级。


13.timer的间隔周期准吗?为什么?怎样实现一个精准的timer?


定时器timer一般都是准确的,但是当主线程有些时候难免会出现堵塞情况,这样就有可能导致定时器timer会延迟从而不准确。我们可以开发一个多线程,在此多线程上运行定时器,这样多线程只运行定时器,不会因堵塞而导致误差。


14.Http协议的特点?GET与POST的区别?什么是Https协议?


1)Http协议是短链接,都是客户端主动发送请求,服务器做出响应,服务器响应之后,连接则断开。


2)GET请求没有请求体,POST含有请求体,请求参数可以放入请求体中,所以,POST可以提交大量的数据给服务器,更加安全。


3)HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议,它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息。它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的安全版。


15.XML数据的解析方式各有什么不同?JSON解析有哪些框架?


XML数据解析有两种方式:DOM解析和SAX解析。


DOM解析:必须完成DOM树的构造,在处理规模较大的XML文档时就很耗费内存,占用资源较多。


SAX解析:与DOM不同的是,SAX是用事件驱动模型,解析XML文档时每遇到一个开始或者结束标签、属性或一条指令时,程序就产生一个事件来进行相应的处理。因此,SAX相对于DOM来说更适合操作大的XML文档。


JSON解析:现在性能比较好的主要是第三方的JSONKit和iOS自带的JSON解析类,自带的JSON解析性能是最高的,但是只能是iOS5之后才可以使用。


第五部分

1.tableView是如何复用的?


如果屏幕上能显示10个单元格,则tableView只会创建11个单元格,也就是n+1,当滑到第12个单元格时就会复用第1个单元格对象。tableView中有个单元格池的概念,tableView调用协议方法获取单元格时,先从池子中查找是否有可复用的单元格,如果有则复用,如果没有则创建一个单元格对象。


2.如何优化tableView的滑动速度?


1)复用单元格。


2)使用不透明的视图,单元格中尽量少使用动画。


3)图片加载使用异步加载,并且设置图片加载的并发数。


4)滑动时不加载图片,停止滑动开始加载。


5)文字、图片可直接drawInRect绘制。


6)如非必要,减少reloadData全部cell,只reloadRowsAtIndexPaths。


7)如果cell是动态行高度,计算出高度后缓存。


8)cell高度固定的话直接用cell.rowHeight设置高度。


3.谈谈对Runloop的理解?


Run loops是线程相关的基础框架的一部分。一个run loop就是一个事件处理的循环,用来不停的调度工作以及处理输入事件。使用run loop的目的是让你的线程在有工作的时候忙于工作,而没有工作的时候处于休眠状态。


4.如何调用drawRect方法与layoutSubView方法?这两个方法的作用?


通过setNeedsLayout方法异步调用layoutSubView方法。


通过setNeedsDisplay方法异步调用drawRect方法。 drawRect方法用于绘图,layoutSubView方法用于布局子视图。


5.UIView与UIViewController的关系?


每个控制器都有一个根视图,控制器UIViewController用来管理此视图的加载和显示。


6.iOS中有哪些手势?


轻击、捏合、平移、轻扫、旋转和长按。


7.Http和Socket的区别?


Http是客户端用Http协议进行请求,发送请求时需要封装http请求头,并绑定请求的数据,服务器一般有Web服务器配合(当然也非绝对)。Http请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开连接,以节省资源。服务器不能主动给客户端响应(除非采用http长连接技术)。iPhone主要使用的类是NSURLConnection。


Socket是客户端跟服务器直接使用Socket套接字进行连接,并没有规定连接后断开,所以客户端和服务器可以保持连接通道,双方都可以主动发送数据。一般在游戏开发或股票开发,这种要求即时性很强并且保持发送数据量比较大的场合使用。主要使用的类是CFSocketRef。


8.storyboard有什么特点?


storyboard是iOS5新增的特性,是对xib的升级版本,引入了一个容器用于管理多个xib文件,和它们之间的跳转交互。


优点:不用再为每个控制器创建xib文件;可以使用静态cell,当cell固定且不多时,使用起来比较方便。


缺点:storyboard单个文件,不利于团队协作开发。


9.如何打包静态库?


新建一个Framework&Library的项目,编译的时候会将项目中的代码文件打包成一个.a静态库文件。


10.APP发布的上架流程?


1)在苹果官网的开发者中心,新建一个APP,填写此APP相关的一些描述信息。


2)下载安装发布证书。


3)选择发布证书,使用Archive编译发布包。


4)使用Xcode提交发布包。


11.iOS5有哪些新特性?


iCloud、定制UI、storyboard、ARC、CoreImage滤镜、新增JSON解析类。


12.iOS6有哪些新特性?


UIRefreshControl水滴效果下拉刷新、UICollectionView控件的使用、SLComposeViewController新浪微博控件、PassKit中Passbook、AutoLayout自动布局。


13、iOS7有哪些新特性?


系统:全新的UI设计与交互;Control Center控制中心;全新的多任务Multitasking;AirDrop共享文件;全新的Safari浏览器交互式体验。


SDK:动态UIKit,新增了UIDynamicItem委托,用来为UIView制定动态行为;新增游戏引擎Sprite Kit Framework框架,类似于Cocos2D。


14.ARC有什么特点?


ARC是编译器特性,iOS5.0新添加的特性,使用ARC开发者不需要再retain、release、autorelease,因为编译器会在合适的地方自动插入retain、release。


ARC不会因少release而导致内存泄漏,过度使用release导致程序崩溃,


ARC可以产生更简洁的代码和更健壮的应用。


15.SVN、Git协作开发,怎么防止代码文件冲突?


防止代码冲突:不要多人同时修改同一个文件。例如,A、B都修改同一个文件,先让A修改,然后提交到服务器,然后B更新下来,再进行修改。 服务器上的项目文件xcodeproj,仅让一个人管理提交,其他人只更新。防止此文件产生冲突。


第六部分

1.什么是ARC?


ARC是automatic reference counting自动引用计数,在程序编译时自动加入retain/release。在对象被创建时retain count+1,在对象被release时count-1,当count=0时,销毁对象。程序中加入autoreleasepool对象会由系统自动加上autorelease方法,如果该对象引用计数为0,则销毁。那么ARC是为了解决MRC手动管理内存存在的一些而诞生的。


MRC下内存管理的缺点:


1)释放一个堆内存时,首先要确定指向这个堆空间的指针都被release了。(避免提前释放)


2)释放指针指向的堆空间,首先要确定哪些指向同一个堆,这些指针只能释放一次。(避免释放多次,造成内存泄露)


3)模块化操作时,对象可能被多个模块创建和使用,不能确定最后由谁释放。


4)多线程操作时,不确定哪个线程最后使用完毕。 虽然ARC给我们编程带来的很多好多,但也可能出现内存泄露。如下面两种情况:


1)循环参照:A有个属性参照B,B有个属性参照A,如果都是strong参照的话,两个对象都无法释放。


2)死循环:如果有个ViewController中有无限循环,也会导致即使ViewController对应的view消失了,ViewController也不能释放。


2.block一般用哪个关键字修饰,为什么?


block一般使用copy关键之进行修饰,block使用copy是从MRC遗留下来的“传统”,在MRC中,方法内容的block是在栈区的,使用copy可以把它放到堆区。但在ARC中写不写都行:编译器自动对block进行了copy操作。


3.用@property声明的NSString(或NSArray,NSDictionary)经常


使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题? 用@property声明 NSString、NSArray、NSDictionary 经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。


如果我们使用是strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性。


copy此特质所表达的所属关系与strong类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为NSString时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例。这个类是NSString的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。


4.runloop、autorelease pool以及线程之间的关系?


每个线程(包含主线程)都有一个Runloop。对于每一个Runloop,系统会隐式创建一个Autorelease pool,这样所有的release pool会构成一个像callstack一样的一个栈式结构,在每一个Runloop结束时,当前栈顶的Autorelease pool会被销毁,这样这个pool里的每个Object会被release。


5.@property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的?


“属性”(property)有两大概念:ivar(实例变量)、存取方法(access method=getter),即@property = ivar + getter + setter。 例如下面的这个类:


@interface WBTextView :UITextView  

@property (nonatomic,copy)NSString *placehold;  

@property (nonatomic,copy)UIColor *placeholdColor;  

@end

类完成属性的定以后,编译器会自动编写访问这些属性的方法(自动合成autosynthesis),上述代码写出来的类等效与下面的代码:


@interface WBTextView :UITextView  

- (NSString *)placehold;  

-(void)setPlacehold:(NSString *)placehold;  

-(UIColor *)placeholdColor;  

-(void)setPlaceholdColor:(UIColor *)placeholdColor;  

@end

详细介绍见:http://blog.csdn.net/jasonjwl/article/details/49427377


6.分别写一个setter方法用于完成@property (nonatomic,retain)NSString *name和@property (nonatomic,copy) NSString *name?


retain属性的setter方法是保留新值并释放旧值,然后更新实例变量,令其指向新值。顺序很重要。假如还未保留新值就先把旧值释放了,而且两个值又指向同一个对象,先执行的release操作就可能导致系统将此对象永久回收。


-(void)setName:(NSString *)name{

    [name retain];

    [_name release];

    _name = name;

}

-(void)setName:(NSString *)name{     

    [_name release];

    _name = [name copy];

}

7.说说assign和weak,_block和 _weak的区别?


assign适用于基本数据类型,weak是适用于NSObject对象,并且是一个弱引用。


assign其实也可以用来修饰对象,那么为什么不用它呢?因为被assign修饰的对象在释放之后,指针的地址还是存在的,也就是说指针并没有被置为nil。如果在后续内存分配中,刚巧分到了这块地址,程序就会崩溃掉。而weak修饰的对象在释放之后,指针地址会被置为nil。


_block是用来修饰一个变量,这个变量就可以在block中被修改。


_block:使用_block修饰的变量在block代码块中会被retain(ARC下,MRC下不会retain)。


_weak:使用_weak修饰的变量不会在block代码块中被retain。


8.请说出下面代码是否有问题,如果有问题请修改?


@autoreleasepool {

        for (int i=0; i<largeNumber; i++) {

            Person *per = [[Person alloc] init];

            [per autorelease];

        }

    }

内存管理的原则:如果对一个对象使用了alloc、copy、retain,那么你必须使用相应的release或者autorelease。咋一看,这道题目有alloc,也有autorelease,两者对应起来,应该没问题。但autorelease虽然会使引用计数减一,但是它并不是立即减一,它的本质功能只是把对象放到离他最近的自动释放池里。当自动释放池销毁了,才会向自动释放池中的每一个对象发送release消息。这道题的问题就在autorelease。因为largeNumber是一个很大的数,autorelease又不能使引用计数立即减一,所以在循环结束前会造成内存溢出的问题。


解决方案如下:


@autoreleasepool {

        for (int i=0; i<100000; i++) { 

            @autoreleasepool {

            Person *per = [[Person alloc] init];

            [per autorelease];

        }

      }

    }

在循环内部再加一个自动释放池,这样就能保证每创建一个对象就能及时释放。


9.请问下面代码是否有问题,如有问题请修改?


@autoreleasepool {

        NSString *str = [[NSString alloc] init];

        [str retain];

        [str retain];

        str = @"jxl";

        [str release];

        [str release];

        [str release];

}

这道题跟第8题一样存在内存泄露问题,


1)内存泄露 ;


2)指向常量区的对象不能release。


指针变量str原本指向一块开辟的堆区空间,但是经过重新给str赋值,str的指向发生了变化,由原来指向堆区空间,到指向常量区。常量区的变量根本不需要释放,这就导致了原来开辟的堆区空间没有释放,造成内存泄露。


10.什么情况下使用weak关键字,相比assign有什么不同?什么情况使用weak关键字?


1)在ARC中,在有可能出现循环引用的时候,往往要通过让其中一端使用weak来解决。比如delegate代理。


2)自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用weak,自定义控件属性一般也使用weak。


不同点:


1)weak此特性表明该属性定义了一种“非拥有关系”。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特性与assign一样,然而在属性所指的对象遭到销毁时,属性值也会清空。而assign的“设置方法”只会执行针对“纯量类型” (scalar type,例如 CGFloat 或 NSlnteger 等)的简单赋值操作。


2)assign可以用非OC对象,而weak必须用于OC对象。


11.内存管理语义(assign、strong、weak等的区别)?


1)assign “设置方法” 只会执行针对“纯量”的简单赋值操作。


2)strong 此特性表明该属性定义了一种“拥有关系”。为这种属性设置新值时,设置方法会先保留新值,并释放旧值,然后再将新值设置上去。


3)weak 此特性表明该属性定义了一种“非拥有关系”。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特性同assign类似,然而在属性所指的对象遭到销毁时,属性值也会清空。


4)unsafe_unretained 此特性的语义和assign相同,但是它适用于“对象类型”,该特性表达一种“非拥有关系”,当目标对象遭到销毁时,属性值不会自动清空,这一点与weak有区别。


5)copy 此特性所表达的所属关系与strong类似。然而设置方法并不保留新值,而是将其“拷贝”。当属性类型为NSString*时,经常用此特性来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例。这个类是NSString的子类,表示一种可以修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变”的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的”,就应该在设置新属性值时拷贝一份。



面向過程 vs 面向對象

https://zhuanlan.zhihu.com/p/28427324

本文以設計五子棋程式為例,比較「面向過程」與「面向對象」的差異、優缺點。

總結來說,兩種思想各有優勢,不同的需求使用不同的方法和設計模式即可,實務上往往是混合使用的。




学习编程, 基本功是掌握编程语言,但编程的本质是逻辑,所以编程思维的培养也很重要。面向过程和面向对象是两种重要的编程思想,下面讲述一下这两者的区别和优缺点比较。

1. 面向过程

面向过程是一种以事件为中心的编程思想,编程的时候把解决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步的具体步骤中再按顺序调用函数。



举个例子,下五子棋,面向过程的设计思路是首先分析解决这个问题的步骤:

(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。

用函数实现上面一个一个的步骤,然后在下五子棋的主函数里依次调用上面的函数(不同的编程语言有不同的调用方法,我这里写的是直接调用):

下五子棋{

开始游戏();

黑子先走();

绘制画面();

判断输赢();

轮到白子();

绘制画面();

判断输赢();

返回到 黑子先走();

输出最后结果;

}

可见,面向过程始终关注的是怎么一步一步地判断棋局输赢的,通过控制代码,从而实现函数的顺序执行。

2. 面向对象

在日常生活或编程中,简单的问题可以用面向过程的思路来解决,直接有效,但是当问题的规模变得更大时,用面向过程的思想是远远不够的。所以慢慢就出现了面向对象的编程思想。世界上有很多人和事物,每一个都可以看做一个对象,而每个对象都有自己的属性和行为,对象与对象之间通过方法来交互。面向对象是一种以“对象”为中心的编程思想,把要解决的问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个对象在整个解决问题的步骤中的属性和行为。



在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:

(1)黑白双方,这两方的行为是一样的。

(2)棋盘系统,负责绘制画面

(3)规则系统,负责判定犯规、输赢等。

然后赋予每个对象一些属性和行为:

(4)第一类对象(黑白双方)负责接受用户输入,并告知第二类对象(棋盘系统)棋子布局的变化,棋盘系统接收到了棋子的变化,并负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。

可以看出,面向对象是以功能来划分问题,而不是以步骤解决。比如绘制画面这个行为,在面向过程中是分散在了多个步骤中的,可能会出现不同的绘制版本,所以要考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘系统这个对象中出现,从而保证了绘图的统一。


3. 优缺点比较

面向过程

优点:

流程化使得编程任务明确,在开发之前基本考虑了实现方式和最终结果,具体步骤清楚,便于节点分析。

效率高,面向过程强调代码的短小精悍,善于结合数据结构来开发高效率的程序。

缺点:

需要深入的思考,耗费精力,代码重用性低,扩展能力差,后期维护难度比较大。

面向对象

优点:

结构清晰,程序是模块化和结构化,更加符合人类的思维方式;

易扩展,代码重用率高,可继承,可覆盖,可以设计出低耦合的系统;

易维护,系统低耦合的特点有利于减少程序的后期维护工作量。

缺点:

开销大,当要修改对象内部时,对象的属性不允许外部直接存取,所以要增加许多没有其他意义、只负责读或写的行为。这会为编程工作增加负担,增加运行开销,并且使程序显得臃肿。

性能低,由于面向更高的逻辑抽象层,使得面向对象在实现的时候,不得不做出性能上面的牺牲,计算时间和空间存储大小都开销很大。



举例说明两者的优缺点,比如在五子棋游戏中增加悔棋的功能。在面向过程中,从输入到显示再到最后判断的整个步骤都要改动,甚至函数的调用顺序也要改动,而在面向对象的设计中,只需在棋盘系统中增加一个回溯的功能就可以了,黑白双方和规则系统的属性和行为都不需改动。这个例子说明了面向对象程序设计中代码间的相关性低(低耦合特性),使得代码很容易被复用和扩展,同时也说明了面向过程的代码重用性低、扩展能力差。



C 語言、Golang 各是如何定義「函數」的

https://segmentfault.com/a/1190000016329960

在 C、C++ 等 C 兼容的語言中,函數通常是一組指令的集合,這組指令的入口地址可以用函數名稱取得。

但是在 Go 語言中,函數是一種類型,而且是第一類型 (first-class),它的地位和 int、string 等類型是一樣的。

在 Golang,我們可以聲明一個值類型為某個函數的變量,這種類型叫做函數變量,也就是說,函數可以被當作一個值類型賦值給變量。

C 語言程式的記憶體配置


https://blog.gtwang.org/programming/memory-layout-of-c-program/

在使用 C 語言開發比較低階的程式之前,多少都要了解一下程式實際在執行時的記憶體配置情況,下圖為典型的 C 語言程式在執行時的記憶體配置圖,記憶體的使用主要可分為 text、data、bss、stack、heap 與 system 這幾個部分。


text:程式碼

文字區段(text segment)也稱為程式碼區段(code segment),這裡存放的是可執行的 CPU 指令(instructions)。

這個區段通常位於 heap 或 stack 之後,避免因 heap 或 stack 溢位而覆寫 CPU 指令。

通常文字區段的資料是可以共用的,當多個同樣的程式在執行時,在記憶體中只需要存有一份就夠了,而這個文字區段通常都是唯讀的,避免程式本身誤改了自己的 CPU 指令。

data:初始化靜態變數

初始化資料區段(initialized data segment)儲存的是一些已經初始化的靜態變數,例如有經過初始化的 C 語言的全域變數(global variables)以及靜態變數(static variables)都是儲存於此處。

這個區段的變數又可分為唯讀區域(read-only area)以及可讀寫區域(read-write area),可讀寫區域用於存放一般變數,其資料會隨著程式的執行而改變,而唯讀區域則是存放固定的常數。

bss:未初始化靜態變數

未初始化資料區段(uninitialized data segment)又稱為 bss 區段(這個名稱的起源來自於古老的組譯器,代表 block started by symbol)是儲存尚未被初始化的靜態變數,而這些變數在程式執行之前會被系統初始化為 0 或是 null。

stack:區域變數

堆疊區段(stack segment)用於儲存函數的區域變數,以及各種函數呼叫時需要儲存的資訊(例如函數返回的記憶體位址還有呼叫者函數的狀態等),每一次的函數呼叫就會在堆疊區段建立一個 stack frame,儲存該次呼叫的所有變數與狀態,這樣一來同一個函數重複被呼叫時就會有不同的 stack frame,不會互相干擾,遞迴函數就是透過這樣的機制來執行的。

heap:動態配置變數

heap 區段的記憶體空間用於儲存動態配置的變數,例如 C 語言的 malloc 以及 C++ 的 new 所建立的變數都是儲存於此。

堆疊區段一般的狀況會從高記憶體位址往低記憶體位址成長,而 heap 剛好從對面以相反的方向成長。

system:命令列參數與環境變數

system 區段用於儲存一些命令列參數與環境變數,這部分會跟系統有關。




實際範例

這是一個最簡單的 C 語言程式:
#include <stdio.h>
int main() {
  return 0;
}
編譯之後,可使用 size 查看它的內部記憶體配置:
gcc source.c
size a.out
   text    data     bss     dec     hex filename
   1099     544       8    1651     673 a.out
新增一個未初始化的全域靜態變數:
#include <stdio.h>
double global[30];  // 儲存於 bss 的未初始化靜態變數
int main() {
  return 0;
}
查看內部記憶體配置:
gcc source.c
size a.out
   text    data     bss     dec     hex filename
   1099     544     272    1915     77b a.out
這一個未被初始化的陣列被放在 bss 區段。
接著增加一個已初始化的靜態變數:
#include <stdio.h>
int main() {
  // 儲存於 data 的已初始化靜態變數
  static int x[5] = {1, 2, 3, 4, 5};
  return 0;
}
查看內部記憶體配置:
gcc source.c
size a.out
   text    data     bss     dec     hex filename
   1099     564       4    1667     683 a.out
有初始化的靜態變數或全域變數都會被放進 data 區段中。
儲存於 stack 與 heap 的變數在這裡看不到,以下是儲存於各種區段的變數:
#include <stdio.h>
const int global_x = 1;  // 儲存於 data 區段(唯讀區域)
int global_y = 1;        // 儲存於 data 區段(可讀寫區域)
int global_z;            // 儲存於 bss 區段
int main() {
  const static int x = 1; // 儲存於 data 區段(唯讀區域)
  static int y = 1;       // 儲存於 data 區段(可讀寫區域)
  static int z;           // 儲存於 bss 區段
  int w = 1;              // 儲存於 stack 區段

  // 儲存於 heap 區段
  char *buf = (char*) malloc(sizeof(char) * 100);
  // ...
  free(buf);

  return 0;
}
參考書籍:
  • Randal E. Bryant and David R. O’Hallaron. 2010. Computer Systems: A Programmer’s Perspective (2nd ed.). Addison-Wesley Publishing Company, USA.
  • W. Richard Stevens and Stephen A. Rago. 2013. Advanced Programming in the UNIX Environment (3rd ed.). Addison-Wesley Professional

Stack 與 Heap 有何差別

https://antrash.pixnet.net/blog/post/70456505

三分天下。程式執行過程中其實主要分成三大區塊:global、stack、heap三塊。其中global區塊最最易理解,主要存放全域變數或宣告為static的靜態變數在此就不多做贅述;另外兩個區塊分別為stack跟heap這兩者往往混淆不清,尤其在java中有時候會出現stack overflow或heap overflow到底兩者差異在哪,若工程師連這都不清楚那以後怎麼去調整JVM中的heap memory space跟stack memory space的大小呢?

貼心的系統全自動化管理區塊:Stack Memory Space!在記憶體中不外乎就是要存放變數、函式相關資訊等資料,使運作過程可以順利取得所需的變數或函式所在地。要讓系統可以全自動化管理,代表需可被預期此變數或函數資訊的生命週期,一旦完全可預測代表可以安心的交由系統管理,這些資訊也將在執行過程中被存放在stack空間。Stack中常見的存放資訊如下:區域變數(local variable)、函式參數(function/method parameter)、函數的返回位址(function/method return address)等資訊。為何上述資訊會放於stack之中,簡單來說:
void method1() {
  int x = 100;
}
上述的int x = 100,系統會在stack中找一個區塊給x,另外裡面的內容為100。然而,x會被放入stack主要是因為在編譯時期系統已經可以預知x從何時開始配置跟何時結束回收(當然就是看所屬block結束就跟著回收),由於配置跟回收的規則明確,當然就往stack擺囉。
在舉一例子:
void method2() {
  method1();
}
上述當呼叫method1()時,系統會先把method2的返回位址存到stack當中,為何是存放在stack呢,因為函式的呼叫有後進先出的概念,當method1()被呼叫而開始執行,待結束時必定會查找該返回何處,故最後一定會讀取函式的返回位址,既然如此明確而有條理,當然也是往stack放!

可預測性外加後進先出的生存模式,令stack無疑是最佳的存放策略。由於程式語言中變數跟函式的生命週期皆為後進先出的概念,也就是越晚產生的會越先被回收或銷毀。正因如此只要是可預測性的相關資訊都是往stack存放。此外,由於stack中的資料之存活週期規律故由系統自行產生與回收其空間即可,就不勞工程師們費心啦!

天啊!程式中竟然有不可預測其存活時間的資料存在。在程式中,有部分的需求總是在執行中依據實際情況才會動態增減,這些資訊是難以被預測哪時候開始有?量有多少?何時該回收?…這些不可預測的因素造成上述的stack區塊不適合運用於此。當資訊為動態配置產生,系統會存放在另外一塊空間,稱之為『Heap』(注意這裡的Heap跟資料結構中的Heap不相關,可別會錯意!)。Heap的區塊專收執行期間動態產生的資料,由於為動態產生故結束點無法由系統來掌握,故需使用者自行回收空間。在C++或Java中利用new語法產生的就是動態配置的物件,需存放於heap中。
奇怪跑越久記憶體用越多的怪現象。許多時候執行的程式都沒有改變,但卻常出現隨時間執行越久程式所耗用的空間將越多,最後造成out of memory。工程師也不知為何如此,就是定期在out of memory之前restart程式即可。這中現象層出不窮,一般大多是因為工程師沒有正確將記憶體回收所導致。Heap中的資料如果沒有正常的回收,將會逐步成長到將記憶體消耗殆盡,下次發生上述問題的實後,切記自己檢查一下heap空間的資料有無正常回收。論述到此有些讀者可能會覺得納悶:為何在寫Java都不需要注意回收空間的問題?~答案是因為Java中會採用Garbage Collection(垃圾回收)的機制自動檢查Heap中哪些資料已經沒有被使用,當確認資料已經沒有使用會自動將空間回收,如此工程師就專注撰寫程式即可,不用擔心記憶體回收不當等問題。

The conclusion is…。當產生stack overflow一般是因為過多的函式呼叫(例如:遞迴太深)、或區域變數使用太多,此時請試著將stack size調大一點,另外檢查看看函式的呼叫跟變數的使用量。反之,當發生heap overflow請檢查是否都有正確將heap space的資料回收,另外採行的動態配置是否合理,不要過渡濫用而new出無謂的空間,若真的是程式過於複雜造成,請將heap size調大一些。


https://nwpie.blogspot.com/2017/05/5-stack-heap.html

簡單來說, 從記憶體配置的角度, 用一個二分法

stack 用於靜態記憶體配置, 大陸翻譯為棧, 棧, 棧 (why ?)
heap 用於動態記憶體配置, 大陸翻譯為堆

引用
https://www.codeproject.com/Articles/76153/Six-important-NET-concepts-Stack-heap-value-types#Stack%20and%20Heap

public void Method1()
{
    // Line 1
    int i=4;

    // Line 2
    int y=2;

    //Line 3
    class1 cls1 = new class1();
}


總結是 :

  • value type 的變數, 包括指標變數會放在 stack
  • reference type 的變數 (如 string, object) 本身也會放 stack, 然而他的值 (value) 則是放 heap
  • box 就是 value types to reference types 的過程, 所以 value 會被放到 heap 中, 而產生一個 object 變數來指向這個 value, 變數指標則是在 stack
  • unbox 是  reference types to value types 的過程,  所以原本 object 所指向的值 (heap 中) 會被複製到 stack 中並賦予明確 value type 型別


程式語言編年史

程式語言編年史原文 下面這張圖片描繪了整個程式語言的歷史。包括各種程式語言的發明人、程式語言的特點和適用領域、被什麼網站或公司使用等 (檢視 完整高清圖 )。 之所以會有那麼多不同的程式語言是因為設計程式語言的初衷不同、對語言學習曲線的追求不同、不同程式之間的執行成本差異...