在上班之余學習IOS已經有三個多月了,因為基礎有些薄弱從OC的基本語法開始學習的,相繼看了青柚子和紅柚子的書,現在在看編程實戰,趁這個機會好好的總結一下:
1.命名約定
對象類型和名稱一致,以免混淆
-(void) setURL:(NSString *)URL;//錯誤的命名方法//更改為-(void)setURLString:(NSString *)string;-(void)setURL:(NSURL *)URL;
靜態變量(包括作用域)以s開頭,而全集變量采用g開頭,在通常情況下應避免使用常量之外的全局變量:
static MYThing *sSharedInstance
常量在Cocoa和Core Foundation中以k開頭,在Cocoa中則不是,建議文件作用域內的(靜態)常量都以k開頭:
static const NSUInteger kMaximumNumberOfRows=3;NSString *const MYSomethingHappenedNotification=@"SomethingHappeded";
方法參數名稱通常要加一個冠詞(a,an,the)(樓主注:貌似不是很常見啊),用這種方式對參數進行命名可以避免與方法中的局部變量和實例名稱混淆
實例變量以下劃線開頭
類名以大寫字母開頭,方法名和變量名則應該以小寫字母開頭,所有類名,方法名都采用駝峰式大小寫(即每個單詞的首字母大小寫)進行分隔,而不采用下劃線
2.自動引用計數
ARC不是垃圾回收,它只是一種編譯器優化,因此它不能處理循環引用的問題:
垃圾回收機制如果外部對象到對象A的引用鏈接中斷,則對象A和對象B都會被銷毀,但那時ARC中因為A,B的相互引用,其引用計數都大于1,因此在IOS開發中必須做好對強引用的管理
屬性的關系有兩種主要類型:strong和weak,相當于非ARC環境中的retain和assign,只要存在一個強引用對象就會一直存在,不會被銷毀。而weak在引用的對象被銷毀后,weak的引用會被自動置為nil,所以delegate的屬性總是應該聲明為weak。
3.屬性
在頭文件聲明公有屬性,.m文件中聲明私有屬性:
//MyClass.h@interface class: NSObject@PRoperty (nonatomic,readwrite,weak) id delegate;@property (noatomic,readonly,strong) NSString *readonlyString;
@end//MyClass.m@interface MyClass() @property (noatomic,readwrite,strong) NSString *readonlyString;@property (noatomic,strong) NSString *privateString;
@end
編譯器會自動創建_delegate,_readonlyString,_privateString幾個變量,不過只能再init,dealloc中調用這些實例變量
另外可以看到在.m文件中重新聲明了一下readonlyString變量,為它增加了一個setter的私有方法
屬性的修飾關鍵字:
1)原子性(atomic,nonatomic)
本意是指屬性的存取器方法是線程安全的,并不保證整個對象是線程安全的。比如使用NSMutableArray聲明一個stuff,使用
self.stuff和self.stuff=otherstuff(只涉及到存取),而采用objectAtIndex的方法訪問數組的時候并不是線程安全的。
但是如果屬性并不需要其他線程訪問的時候,使用原子屬性是一種極大的浪費,因此通常情況下采用的是nonatomic
2)讀寫屬性(readwrite和readonly)
3)設置方法修飾的關鍵詞(weak,strong,copy)
注意的是對于不可變類如NSString和NSArray使用copy修飾
屬性是用來表示對象的狀態的,getter方法必須沒有任何外部副作用,執行速度要快,不應該有阻塞。
屬性和私有實例變量,在@implementation中可以使用私有實例變量
如@implementation{
NSString *_name;
}
默認的存儲類型是strong
4.存儲器
使用的一些范圍,或者說必須使用存取器而最好別用實例變量:
KVO(鍵值觀察Key-Value Observing)
屬性可被自動觀察,那次修改一個屬性的時候可以調用willChangeValueForKey:和didChangeValueForKey:方法。
副作用(樓主太菜不是很懂副作用)
類或者子類可能會在設置的方法中引用副作用。可能會有一些注冊到NSUndoManager的通知或者事件,除非真的必要,否則這些事件都不應該被忽略。類似的,類或者子類可能會在獲取方法中使用緩存,而直接訪問實例變量則不會用到緩存。
鎖
在多線程代碼中直接使用實例變量會突破鎖機制,不用多說后果了吧
不應該用存儲器的地方:
存儲器內部
dealloc方法
初始化方法:這里可以用_Value,而不應該用屬性
5.分類和擴展
category個人認為是比較好用的。可以減少繼承,向現有的類添加新的方法,類似C#中的擴展方法
分類用于以模塊化的方式將一個大型類分解成多個易于維護的類。
分類的聲明非常簡單,跟接口有些相像,在類名后的小括號里寫上分類名稱即可:
@interface NSMutableString (Capitalize)
-(void) capitalize
@end
Capitalize為分類的名稱。從技術上講,分類中可以進行方法覆蓋,但是不建議這么做,如果兩個分類包含了同名的方法,無法預測哪個方法會被使用。
關于分類,合理的使用就是為現有類添加某些適用的方法。使用原先的類名+分類的名稱作為新的頭文件和實現文件的名字。
比如為NSDate增加一個MyExtensions的簡單分類:
//NSDate+MyExtensions.h@interface NSDate(MyExtensions)-(NSTimeInterval) timeIntervalUntilNow;@end;//NSDate+MyExtensions.m@implementation NSDate(MyExtensions)-(NSTimeInterval) timeIntervalUntilNow{ return [self timeIntervalSinceNow];}@end
如果只是添加幾個少數使用的方法,比較好的方式就是把這些方法都放在該MyExtensions類中,但是需要權衡一下防止代碼膨脹。
關聯引用為分類添加數據
在分類中不能創建實例變量,但是可以創建關聯引用,通過關聯引用為任何對象添加鍵值數據。
由于在分類中不能合成屬性,
比如聲明
//person類,并為其增加一個分類 email@interface Person:NSObject@property (nonatomic,copy) NSString *name;@end;@implementation Person@end;//增加一個分類#import <objc/runtime.h>@interface Person(emailAdress)@property (nonatomic,copy) NSString *emailAdress;@end;///如果這么寫,在引用或者復制的時候出現屬性無法獲取或者復制的錯誤//因為在分類中無法合成屬性//@implementation Person(emailAdress)//@end;//正確的做法@implementation Person(emailAdress)static char emailAdressKey;-(NSString *)emailAdress{return objc_getAssociateObject(self,&emailAdressKey);}-(void) setEmailAdress:(NSString *)emailAdress{objc_setAssociateObject(self,&emailAdressKey,emailAdress,OBJC_ASSOCIATE_COPY);}@end;
可以看到關聯引用是基于key的內存地址,而不是鍵的值.
如果在警告面板或者警告的控件上附加一個相關對象,使用關聯引用是非常好的一個形式.
objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)//(目標類實例,關聯引用key,關聯引用值
,復制、賦值、保留語義)
objc_getAssociatedObject(<#id object#>,<#const void *key#>)//(目標類實例,關聯引用key)
#import "ViewController.h"#import <objc/runtime.h>@implementation ViewControllerstatic const char kRepresentedObject;- (IBAction)doSomething:(id)sender { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; objc_setAssociatedObject(alert,&
kRepresentedObject, sender, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [alert show]; }- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { UIButton*sender = objc_getAssociatedObject(alertView, &
kRepresentedObject); self.buttonLabel.text = [[sender titleLabel] text];}@end
類擴展
看網上說可以算是category的一個匿名類,可以自由聲明合成屬性,但是聲明的方法必須在implementation中實現
6.協議
聲明一個協議
@protocol 名稱 <NSObject>
@required
//必須實現的
@optional
//選擇實現的
協議和類一樣可以繼承,協議總是繼承<NSObject>,NSObject 被劃分為一個類和一個協議
委托協議(delegate protocol)
第一個參數是委托對象,這樣一個委托才能管理多個委托對象
創建協議后還需要一個屬性來便于操作它
@property (nonatomic,weak) id<Mydelegate>delegate;
新聞熱點
疑難解答