Objective-C tips

Objective-C tips

nil

下面兩種OC語(yǔ)法是等價(jià)的:

if (venue == nil) {
    [organizer remindToFindVenueForParty];
}
if (!venue) {  //類似JS的語(yǔ)法,判斷對(duì)象為空或非空
    [organizer remindToFindVenueForParty];
}

其他語(yǔ)言經(jīng)常要加非空判斷物遇,像JAVA JS都需要俩功,避免出現(xiàn)空指針異常,OC中不需要像下面這樣判斷扔傅,如果對(duì)象為nil耍共,OC會(huì)直接忽略被調(diào)用的方法。

// Is venue non-nil?
if (venue) { //例如JS猎塞,判斷對(duì)象不為空
    [venue sendConfirmation];
}

@

創(chuàng)建字符串對(duì)象:

NSString *myString = @"Hello, World!";

NSLog格式化字符串试读,不同類型使用不同占位符:

int a = 1;
float b = 2.5;
char c = 'A';
NSLog(@"Integer: %d Float: %f Char: %c", a, b, c);

        
NSString *str = @"hello oc";
NSLog(@"print %@", str);

%@代表“a pointer to any object”,當(dāng)對(duì)象被Log時(shí)荠耽,會(huì)發(fā)送給給對(duì)象description消息钩骇,返回字符串。就像java中的toString()方法铝量。

實(shí)例變量 set&get方法

在頭文件中聲明實(shí)例變量倘屹,ANDROID中實(shí)例變量以m開(kāi)頭,OC中實(shí)例變量以 _ 開(kāi)頭慢叨,約定而已纽匙,不是必須的。
get方法不需要以get開(kāi)頭插爹。

#import <Foundation/Foundation.h>

@interface BKItem : NSObject
{
    NSString *_itemName; //*號(hào)說(shuō)明變量是個(gè)指針
    NSString *_serialNumber;
    int _valueInDollars;
    NSDate *_dateCreated;
}

//在頭文件中聲明set get方法哄辣,像是java中聲明接口的抽象方法
- (void)setItemName:(NSString *)str;
- (NSString *)itemName;

- (void)setSerialNumber:(NSString *)str;
- (NSString *)serialNumber;

- (void)setValueInDollars:(int)v;
- (int)valueInDollars;

- (NSDate *)dateCreated; //只有g(shù)et方法

@end

類的實(shí)現(xiàn)中實(shí)現(xiàn)set get方法:

#import "BKItem.h"

@implementation BKItem

- (void)setItemName:(NSString *)str
{
    _itemName = str;
}
- (NSString *)itemName
{
    return _itemName;
}

- (void)setSerialNumber:(NSString *)str
{
    _serialNumber = str;
}
- (NSString *)serialNumber
{
    return _serialNumber;
}

- (void)setValueInDollars:(int)v
{
    _valueInDollars = v;
}
- (int)valueInDollars
{
    return _valueInDollars;
}

- (NSDate *)dateCreated
{
    return _dateCreated;
}

@end

set get的兩種訪問(wèn)語(yǔ)法,使用點(diǎn)語(yǔ)法最終會(huì)被編譯器轉(zhuǎn)成第一種方法赠尾,但是使用點(diǎn)語(yǔ)法更方便力穗。

        BKItem *item = [[BKItem alloc] init];
        [item setItemName:@"Red Sofa"];
        [item setSerialNumber:@"A1B2C"];
        [item setValueInDollars:100];
        
        NSLog(@"%@ %@ %@ %d", [item itemName], [item dateCreated],
              [item serialNumber], [item valueInDollars]);
        
       // 推薦使用下面的點(diǎn)語(yǔ)法 dot syntax:等號(hào)左邊調(diào)用set方法,等號(hào)右邊調(diào)用get方法
        item.itemName=@"Red Sofa";
        item.serialNumber=@"A1B2C";
        item.valueInDollars = 100;
        NSLog(@"%@ %@ %@ %d", item.itemName, item.dateCreated,
              item.serialNumber, item.valueInDollars);

重寫(xiě)方法

重寫(xiě)父類方法气嫁,只需在子類的實(shí)現(xiàn)文件中重寫(xiě)当窗,頭文件中不需要聲明,因?yàn)楸恢貙?xiě)的方法已經(jīng)被父類的頭文件聲明過(guò)了寸宵。

Initializers

構(gòu)造器崖面,類默認(rèn)只有init一個(gè)初始化方法元咙,可以添加自定義的初始化方法。

#import <Foundation/Foundation.h>

@interface BKItem : NSObject
{
    NSString *_itemName; //*號(hào)說(shuō)明變量是個(gè)指針
    NSString *_serialNumber;
    int _valueInDollars;
    NSDate *_dateCreated;
}

// 聲明自定義的初始化方法
- (instancetype)initWithItemName:(NSString *)name valueInDollars:(int) value serialNumber:(NSString *)sNumber;
- (instancetype)initWithItemName:(NSString *)name;

@end

實(shí)現(xiàn)在頭文件中聲明的初始化方法巫员,通常參數(shù)最多的初始化方法是指定初始化方法(designated initializer)
instancetype 關(guān)鍵字是初始化方法的返回類型庶香,誰(shuí)來(lái)調(diào)用初始化方法,instancetype 就是誰(shuí)(an instance of the receiving object)简识。

#import "BKItem.h"

@implementation BKItem

// Designated initializer (指定的構(gòu)造器赶掖,通常是參數(shù)最多的那個(gè)init方法)
- (instancetype)initWithItemName:(NSString *)name valueInDollars:(int) value serialNumber:(NSString *)sNumber{
    // Call the superclass's designated initializer
    self = [super init];
    // Did the superclass's designated initializer succeed?
    if (self) { // 判斷對(duì)象非空,類似JS語(yǔ)法
        // Give the instance variables initial values
        _itemName = name;
        _serialNumber = sNumber;
        _valueInDollars = value;
        // Set _dateCreated to the current date and time
        _dateCreated = [[NSDate alloc] init];
    }
    // Return the address of the newly initialized object
    return self;
}
- (instancetype)initWithItemName:(NSString *)name{
    return [self initWithItemName:name
                   valueInDollars:0
                     serialNumber:@""];
}

// 重寫(xiě)父類的init方法七扰,調(diào)用子類的designated initializer
- (instancetype)init
{
    return [self initWithItemName:@"Item"];
}

// 重寫(xiě)父類的description方法
- (NSString *)description
{
    NSString *descriptionString =
    [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d, recorded on %@",
     self.itemName,
     self.serialNumber,
     self.valueInDollars,
     self.dateCreated];
    return descriptionString;
}

@end

id - a pointer to any object

Because id is defined as “a pointer to any object,” you do not include an * when declaring avariable or method parameter of this type.

用id來(lái)聲明變量時(shí)奢赂,由于他已經(jīng)是指針了,所以不需要添加 * 號(hào)颈走。

Class method 類方法(靜態(tài)方法)

類方法常被用來(lái)創(chuàng)建對(duì)象實(shí)例(類似JAVA中獲取單例類對(duì)象的方法)或是獲取全局屬性膳灶。類方法不能訪問(wèn)實(shí)例變量(instance variables)。
通過(guò) + 號(hào)來(lái)聲明類方法立由。

在頭文件中聲明類方法轧钓,注意頭文件內(nèi)容的順序:instance variable, class method, initializer, instance method.

#import <Foundation/Foundation.h>

@interface BKItem : NSObject
{
    NSString *_itemName; //*號(hào)說(shuō)明變量是個(gè)指針
    NSString *_serialNumber;
    int _valueInDollars;
    NSDate *_dateCreated;
}

+ (instancetype)randomItem; //類方法

- (instancetype)initWithItemName:(NSString *)name valueInDollars:(int) value serialNumber:(NSString *)sNumber;
- (instancetype)initWithItemName:(NSString *)name;

@end

在實(shí)現(xiàn)文件中實(shí)現(xiàn)類方法:

#import "BKItem.h"

@implementation BKItem

+ (instancetype)randomItem
{
    // Create an immutable array of three adjectives
    NSArray *randomAdjectiveList = @[@"Fluffy", @"Rusty", @"Shiny"];
    // Create an immutable array of three nouns
    NSArray *randomNounList = @[@"Bear", @"Spork", @"Mac"];
    // Get the index of a random adjective/noun from the lists
    // Note: The % operator, called the modulo operator, gives
    // you the remainder. So adjectiveIndex is a random number
    // from 0 to 2 inclusive.
    NSInteger adjectiveIndex = arc4random() % [randomAdjectiveList count];
    NSInteger nounIndex = arc4random() % [randomNounList count];
    // Note that NSInteger is not an object, but a type definition
    // for "long"
    NSString *randomName = [NSString stringWithFormat:@"%@ %@",
                            [randomAdjectiveList objectAtIndex:adjectiveIndex],
                            [randomNounList objectAtIndex:nounIndex]];
    int randomValue = arc4random() % 100;
    NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
                                    '0' + arc4random() % 10,
                                    'A' + arc4random() % 26,
                                    '0' + arc4random() % 10,
                                    'A' + arc4random() % 26,
                                    '0' + arc4random() % 10];
    BKItem *newItem = [[self alloc] initWithItemName:randomName
                                       valueInDollars:randomValue
                                         serialNumber:randomSerialNumber];
    return newItem;
}

@end

NSArray NSMutableArray

在Objective-C中,同一數(shù)組可以包含任意類型的對(duì)象拆吆,但是必須是Objective-C的對(duì)象聋迎,不能是基本類型和C struct。

不能將 nil 添加到數(shù)組中枣耀,但是 NSNull 可以霉晕。

NSMutableArray *items = [[NSMutableArray alloc] init];
[items addObject:nil]; //ERROR -[__NSArrayM insertObject:atIndex:]: object cannot be nil
[items addObject:[NSNull null]]; // this is OK

數(shù)組下標(biāo)訪問(wèn),以下兩個(gè)方法等價(jià):

NSString *str = [items objectAtIndex:0];
NSString *rts = items[0];

isa instance variable

每個(gè)對(duì)象都有一個(gè) isa 實(shí)例變量指針捞奕,指向?qū)ο笏鶎俚念悺?/p>

Exception

 // id 可以代表任何類型牺堰,就像JAVA中的Object
id lastObj = [items lastObject];
[lastObj count];

如果lastObj沒(méi)有count方法,會(huì)報(bào)出以下錯(cuò)誤:

2015-07-07 19:31:16.787 RandomItems[3647:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[BKItem count]: unrecognized selector sent to instance 0x7fd1a2c0c650'

unrecognized selector颅围,selector就是message伟葫,就是類中的方法。
-[BKItem count]院促,- 表示receiver是BKItem的實(shí)例筏养,如果是 + 則receiver是BKItem class.

類名前綴

OC中沒(méi)有包或命名空間的概念(這點(diǎn)也真是醉了)...
所以O(shè)C的類名都有前綴來(lái)區(qū)分,可以是公司名的縮寫(xiě)或是項(xiàng)目名的縮寫(xiě)常拓,通常使用三個(gè)字母渐溶,因?yàn)閮蓚€(gè)字母被蘋(píng)果使用了,防止命名沖突弄抬。
NS -- NeXTSTEP茎辐,蘋(píng)果收購(gòu)的公司

Strong and Weak References

如果兩個(gè)對(duì)象都引用了對(duì)方,并且都是強(qiáng)引用,那么會(huì)造成內(nèi)存泄漏拖陆〕诨保可以通過(guò)弱引用來(lái)解決這個(gè)問(wèn)題,通常兩個(gè)對(duì)象互相引用對(duì)方時(shí)依啰,這兩個(gè)對(duì)象存在父子關(guān)系乎串,父對(duì)象會(huì)強(qiáng)引用子對(duì)象,子對(duì)象只需弱引用父對(duì)象速警。

//聲明一個(gè)弱引用變量
__weak BNRItem *_container;

@property

之前每聲明一個(gè)實(shí)例變量灌闺,都需要寫(xiě)對(duì)應(yīng)的set get方法,通過(guò)property來(lái)聲明可以不用寫(xiě)set get方法坏瞄,編譯器會(huì)幫你將實(shí)例變量和set get訪問(wèn)方法聲明好。

@property NSString *itemName;

下表為是否使用@property的區(qū)別:

file Without properties With properties
BNRThing.h @interface BNRThing : NSObject
{
NSString *_name;
}
- (void)setName:(NSString *)n;
- (NSString *)name;
@end
@interface BNRThing : NSObject
@property NSString *name;
@end
BNRThing.m @implementation BNRThing
- (void)setName:(NSString *)n
{
_name = n;
}
- (NSString *)name
{
return _name;
}
@end
@implementation BNRThing
@end

注意property屬性名字不需要下劃線前綴

property attribute (這兩個(gè)單詞有意思甩卓,都能翻譯成屬性...)

@property (nonatomic, readwrite, strong) NSString *itemName;

nonatomic, atomic鸠匀,默認(rèn)值是atomic,和多線程相關(guān)的attribute(原子的逾柿,即線程安全的缀棍;非原子,即非線程安全机错,性能更高)爬范,iOS中通常用nonatomic

readwrite, readonly,默認(rèn)值是readwrite弱匪,告訴編譯器是否生成set方法青瀑,只讀不生成set方法。

strong, weak, copy, unsafe_unretained萧诫,針對(duì)OC的對(duì)象斥难,其默認(rèn)值是strong。如果是非OC的對(duì)象(如基本類型)帘饶,其只有一個(gè)可選值unsafe-unretained哑诊,也是非OC對(duì)象的默認(rèn)值,所以可以不用聲明及刻。

什么時(shí)候用copy镀裤?當(dāng)要聲明的變量類型有可變的子類時(shí),如NSString/NSMutableString or NSArray/NSMutableArray缴饭,這時(shí)要用copy暑劝,其生成的最終代碼如下,copy會(huì)復(fù)制對(duì)象茴扁,并將變量強(qiáng)引用到復(fù)制生成的對(duì)象

- (void)setItemName:(NSString *)itemName
{
    _itemName = [itemName copy];
}
@property (nonatomic, strong) BNRItem *containedItem;
@property (nonatomic, weak) BNRItem *container;
@property (nonatomic, copy) NSString *itemName;
@property (nonatomic, copy) NSString *serialNumber;
@property (nonatomic) int valueInDollars;
@property (nonatomic, readonly, strong) NSDate *dateCreated;

The memory management attribute’s values are strong, weak, copy, and unsafe_unretained. This
attribute describes the type of reference that the object with the instance variable has to the object that
the variable is pointing to.

上面的第二句話怎么理解铃岔? 好多that...

自定義set get方法

當(dāng)你的set get方法中有邏輯時(shí),需要在類實(shí)現(xiàn)文件中添加自定義的set get方法:

- (void)setContainedItem:(BNRItem *)containedItem
{
    _containedItem = containedItem;
    self.containedItem.container = self;
}

如果你同時(shí)實(shí)現(xiàn)了set get方法,則需要在頭文件中聲明實(shí)例變量毁习,@property不會(huì)再幫你自動(dòng)添加實(shí)例變量了智嚷。


本文是對(duì)《iOS Programming The Big Nerd Ranch Guide 4th Edition》第二,三章的總結(jié)纺且。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盏道,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子载碌,更是在濱河造成了極大的恐慌猜嘱,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嫁艇,死亡現(xiàn)場(chǎng)離奇詭異朗伶,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)步咪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)论皆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人猾漫,你說(shuō)我怎么就攤上這事点晴。” “怎么了悯周?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵粒督,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我禽翼,道長(zhǎng)屠橄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任捐康,我火速辦了婚禮仇矾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘解总。我一直安慰自己贮匕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布花枫。 她就那樣靜靜地躺著刻盐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪劳翰。 梳的紋絲不亂的頭發(fā)上敦锌,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音佳簸,去河邊找鬼乙墙。 笑死颖变,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的听想。 我是一名探鬼主播腥刹,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼汉买!你這毒婦竟也來(lái)了衔峰?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蛙粘,失蹤者是張志新(化名)和其女友劉穎垫卤,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體出牧,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吧凉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年钧敞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了满粗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栓拜。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡调煎,死狀恐怖培己,靈堂內(nèi)的尸體忽然破棺而出巡揍,到底是詐尸還是另有隱情蘑斧,我是刑警寧澤耿眉,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布边翼,位于F島的核電站,受9級(jí)特大地震影響鸣剪,放射性物質(zhì)發(fā)生泄漏组底。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一筐骇、第九天 我趴在偏房一處隱蔽的房頂上張望债鸡。 院中可真熱鬧,春花似錦铛纬、人聲如沸厌均。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棺弊。三九已至,卻和暖如春擒悬,著一層夾襖步出監(jiān)牢的瞬間模她,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工懂牧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侈净,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像畜侦,于是被迫代替她去往敵國(guó)和親元扔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容