OC基礎
一、Foundation
[NSNull null] => 表示NSNull對象
nil => (null) 表示nil值
基礎
NSString:字符串
NSInteger、NSUInteger
集合
NSArray:數組,順序存儲,總不可存儲基本數據類型,只能存放類的實例;需要把基礎數據類型、結構體放入其中需要放入NSNumber\NSValue中進行封裝
NSSet:集合,hash無序,查找效率比NSArray高
NSDictonary:字典
數據封裝
NSNumber:主要是用來封裝ANSI C內置的數據,比如char,float,int,bool,(NSInteger是基礎類型,NSNumber是一個類)
NSValue:主要用來封裝數據結構,包括系統(CGPoint/CGSize等)和自定義
NSData:主要是提供一塊原始數據的封裝,方便數據的封裝與流動,比較常見的是NSString/NSImage數據的封裝與傳遞。在應用中,最常用於訪問存儲在文件中或者網絡資源中的數據。
其他
NSDate:日期、時間
NSTimer :定時器
以上為不可變類型,其對可變類型如:NSMutableString 、NSMutableInteger 、NSMutableArray
二、協議和委托
協議僅僅聲明方法,用作接口,本身並不實現,遵循該協議的類則負責具體實現。@protocol、@required、@required
委托是一種避免對復雜的UIKit對象(比如缺省的UIApplication對象)進行子類化的機制。在這種機制下,您可以不進行子類化和方法重載,而是將自己的定制代碼放到委托對象中,從而避免對復雜對象進行修改。
比如:Student遵循_protocolDelegate協議,實現work方法;Student委托給Teacher,Teacher通過call_work使Student執行協議方法work
三、interface類
初始化
如果實現一個初始化程序,確保調用超類的初始化;
如果超類的初始化不止一個方法,選擇一個指定初始值設定;
屬性
@property(nonatomic,strong)NSString*name;
系統為我們自動生成的。命名規則是以_為前綴,加上屬性名,如_name
@property與@synthesize配對使用,用來讓編譯器自動生成與數據成員同名的方法聲明
C++中的.也可以用於訪問屬性:user.id 類似 [user id];user.id = 12類似[user setId:12];
@property特性:分為三類,分別是:
原子性:
atomic(默認)線程安全
nonatomic 非線程安全(nonatomic比atomic速度要快)
存取器控制:
readwrite(默認)同時擁有setter和getter。
readonly 只有getter
內存管理:
assign(默認)表示單純的復制,
retain:在setter方法中,需要對傳入的對象進行引用計數加1的操作
strong:是retain的一個可選的替代。strong跟retain的相同(語意上更好更能體現對象的關系)
weak:在setter方法中,需要對傳入的對象不進行引用計數加1的操作。(就是對傳入的對象沒有所有權)
copy:與strong類似,但區別在於實例變量是對傳入對象的副本擁有所有權,而非對象本身。
類目
使用類目,為現有的類NSString擴展方法,是新方法成為類的一部分,且子類也能繼承
類目的不足:
類目還可以覆寫現有類的方法。覆寫後,原始方法則無法調用。
類目不能為類擴展實例屬性。
方法
重載方法description,實現類指針打印的描述字符串;
單例模式:重載實現類方法allocWithZone,(實現限制方法,限制這個類只能創建一個對象)
四、內存管理
init\alloc\copy\retain之後需要有相互對應的release
其他方法獲取一個對象(一般是autorelease)如arrayWithCapacity、arrayWithObjects是自動釋放不需要release;
對象拷貝
對象要具備復制功能,必須實現協議或者協議,自定義對象實現協議的CopyWithZone方法/MutableCopyWithZone方法;常用的可復制對象有:NSString、NSMutableString、NSArray等;
拷貝方法:
copy:產生對象的副本是不可變的
mutableCopy:產生的對象的副本是可變的
淺拷貝和深拷貝
淺拷貝值復制對象本身,對象裡的屬性、包含的對象不做復制(默認)
深拷貝則既復制對象本身,對象的屬性也會復制一份
五、KVC
鍵值:forKey/valueForKey
鍵路徑:forKeyPath/valueForKeyPath
運算:左側指定集合的運算;需要解析字符串路徑,所以性能慢
NSPredicate謂詞
六、數據持久化 歸檔
NSKeyedArchiver
NSKeyedUnarchiver
七、文件管理
沙盒
路徑:~資源庫/Application Support/iPhone Simulator/文件夾
Documents:程序中建立的或在程序中浏覽到的文件數據保存在該目錄下,iTunes備份和恢復的時候會包括此目錄
Library:系統文件,存儲程序的默認設置或其它狀態信息;Library/Caches:存放緩存文件,iTunes不會備份此目錄,此目錄下文件不會在應用退出刪除
tmp:臨時文件的地方。App重啟會被清空。
文件操作
NSFileManager 是一個單例類 (全局的能被整個系統訪問到)對文件進行管理的各種操作(遍歷\創建\拷貝\移動\刪除)
NSFileHandle 操作系統返回給我們程序的文件指針,用NSData類型的二進制數據,對文件進行讀寫的
OC進階
一、語法
靜態分析器:
1、函數對象釋放檢查:NS_RETURNS_RETAINED\NS_RETURNS_NOT_RETAINED
2、不放回對象:CLANG_ANALYZER_NORETURN
instancetype和id的異同
1、相同點
都可以作為方法的返回類型
2、不同點
①instancetype可以返回和方法所在類相同類型的對象,id只能返回未知類型的對象;
②instancetype只能作為返回值,不能像id那樣作為參數,比如下面的寫法:
二、利用arc4random_uniform()產生隨機數
Objective-C 中有個arc4random()函數用來生成隨機數且不需要種子
但是這個函數生成的隨機數范圍比較大,需要用取模的算法對隨機值進行限制,
有點麻煩。其實Objective-C有個更方便的隨機數函數arc4random_uniform(x),
可以用來產生0~(x-1)范圍內的隨機數,
不需要再進行取模運算。如果要生成1~x的隨機數,可以這麼寫:arc4random_uniform(x)+1
三、消息處理方法performSelector: withObject:和直接調用的區別
Objective-C中調用函數的方法是“消息傳遞”,這個和普通的函數調用的區別是,你可以隨時對一個對象傳遞任何消息,而不需要在編譯的時候聲明這些方法。所以Objective-C可以在runtime的時候傳遞人和消息。
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second {
NSLog(@"Logs %@ then %@", first, second);
}
然後調用它
[selfperformSelector:@selector(fooFirstInput:secondInput:)withObject:@"first"withObject:@"second"afterDelay:1.5];
1、performSelector是運行時系統負責去找方法的,在編譯時候不做任何校驗;如果直接調用編譯是會自動校驗。如果fooFirstInput:secondInput不存在,那麼直接調用在編譯時候就能夠發現(借助Xcode可以寫完就發現),但是使用performSelector的話一定是在運行時候才能發現(此時程序崩潰);Cocoa支持在運行時向某個類添加方法,即方法編譯時不存在,但是運行時候存在,這時候必然需要使用performSelector去調用。所以有時候如果使用了performSelector,為了程序的健壯性,會使用檢查方法
- (BOOL)respondsToSelector:(SEL)aSelector;
2、直接調用方法時候,一定要在頭文件中聲明該方法的使用,也要將頭文件import進來。而使用performSelector時候,可以不用import頭文件包含方法的對象,直接用performSelector調用即可。
afterDelay 是一種dispatch_after()函數,支持在未來的某個時間執行
四、如何在Objective-C中定義代碼塊(Block)
1、作為變量
//1
返回值類型 (^block的名稱)(參數類型) = ^返回值類型(參數) {...};
//2
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
2、作為屬性
//1@property (nonatomic, copy) 返回值類型 (^block的名稱)(參數類型);
//2@property (nonatomic, copy) returnType (^blockName)(parameterTypes);
3、作為方法聲明的參數
//1
- (void)方法名:(返回值類型 (^)(參數類型))block的名稱;
//2
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
4、作為方法實現的參數
//1
[對象/類 方法名:^返回值類型 (參數) {...}];
//2
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
5、作為typedef
//1typedef 返回值類型 (^類型名稱)(參數類型);
類型名稱 block的名稱 = ^返回值類型(參數) {...};
//2typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
五、Grand Central Dispatch (GCD)
voiddispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
該函數接收一個dispatch_once用於檢查該代碼塊是否已經被調度的謂詞(是一個長整型,實際上作為BOOL使用)。它還接收一個希望在應用的生命周期內僅被調度一次的代碼塊,對於本例就用於shared實例的實例化。
dispatch_once不僅意味著代碼僅會被運行一次,而且還是線程安全的
+ (AccountManager *)sharedManager {
static AccountManager *sharedAccountManagerInstance = nil;
static dispatch_once_t predicate; dispatch_once(&predicate, ^{
sharedAccountManagerInstance = [[self alloc] init];
});
return sharedAccountManagerInstance;
}