顯示具有 Objective-C 標籤的文章。 顯示所有文章
顯示具有 Objective-C 標籤的文章。 顯示所有文章

2012年7月29日 星期日

實現彼得潘偷懶欲望的新一代Objective-C

隨著Xcode 4.4的推出, Objective-C也有了大幅的進步。其實偷懶是人類的天性,科技的進步正是朝著偷懶的目標前進。接下來彼得潘將介紹的Objective-C三大新功能,完全實現了彼得潘不為人知的偷懶欲望,我們可以打愈少的字,犯更少的錯,開發更多的App,賺更多的錢,環遊世界玩更多的國家!

1.  自動補上@synthesize

只要打@property,@synthesize會自動幫我們補上。

例子:

TestViewController.h


@interface TestViewController : UIViewController

@property (strong, nonatomic) NSString *name;

@end


TestViewController.m

@implementation TestViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

    _name = @"彼得潘"; 
    self.name = @"彼得潘";
}

@end
說明:

自動補上的@synthesize,其實長得像這樣

@synthesize name = _name;

因此若要直接存取物件的member,於前面加 _ 即為member名稱。



2.  神奇的@


Objective-C的物件讓人又愛又恨。因為物件,讓我們可以輕易設計許多天馬行空的App。但也因為物件,讓我們在使用某些常用型別,比方int, Array, Dictionary時,需要寫許多令人心煩的程式碼。現在有了神奇的@,一切都簡單多了。

例子:

(1) NSNumber

a.  一拍即合型

沒有@的世界末日
    NSNumber * endOfTheWorld = [NSNumber numberWithInt: 2012];
神奇@的世界末日
   NSNumber *endOfTheWorld = @2012;

說明:
如果對象是數字,它和@完全是一拍即合,可以直接結合。

b.  月下老人 ( ) 牽線型

如果不是數字,還是可以結合,只不過需要 ( ) 的幫忙。

-(int)getEndOfTheWorld
{
    return 2012;
}

沒有@的世界末日
NSNumber * endOfTheWorld = [NSNumber numberWithInt: [self getEndOfTheWorld]];

神奇@的世界末日
NSNumber *endOfTheWorld = @([self getEndOfTheWorld]);

(2) NSArray

結合@ 和 [ ] ,我們可以輕易創造NSArray。

沒有@的蝙蝠俠三部曲
NSArray *batmanMovies = [NSArray arrayWithObjects:@"開戰時刻", @"黑暗騎士", @"黎明升起", nil];

神奇@的蝙蝠俠三部曲
NSArray *batmanMovies = @[@"開戰時刻", @"黑暗騎士", @"黎明升起"];

不過如果蝙蝠俠想再拍第四集,要先變型為NSMutableArray才能加入第四集,例如以下例子:

NSMutableArray *batmanMovies = [@[@"開戰時刻", @"黑暗騎士", @"黎明升起"] mutableCopy];
[batmanMovies addObject:@"當蝙蝠俠遇上彼得潘"];

(3) NSDictionary


結合@ 和 { },我們可以輕易創造NSDictionary。

沒有@的蔡淳佳新專輯主打歌
NSDictionary *joiNewAlbum = [NSDictionary dictionaryWithObjectsAndKeys:@"Love You", @"song1", @"不透光", @"song2", nil];


神奇@的蔡淳佳新專輯主打歌
NSDictionary *joiNewAlbum = @{ @"song1" : @"Love You", @"song2": @"不透光" };



3.  更方便的存取集合裡的元素 (Object Subscripting) 



 NSMutableArray *batmanMovies = [@[@"開戰時刻", @"黑暗騎士", @"黎明升起"]
       mutableCopy];
 [batmanMovies addObject:@"當蝙蝠俠遇上彼得潘"];

沒有subscripting的蝙蝠俠第4集
 movieLabel.text = [batmanMovies objectAtIndex:3];


支援subscripting的蝙蝠俠第4集
 movieLabel.text = batmanMovies[3];

說明:
在 [ ] 內指定index

 
 NSDictionary *joiNewAlbum = @{ @"song1" : @"Love You", @"song2": @"不透光" };


沒有subscripting的蔡淳佳抒情主打歌

 songLabel.text = [joiNewAlbum objectForKey:@"song2"];

支援subscripting的蔡淳佳抒情主打歌

 songLabel.text = joiNewAlbum[@"song2"];

說明:
在[ ]內指定key



執行結果:



想要具有Object Subscripting的神奇魔力,其實很簡單,想要像NSArray一樣透過index存取,只要定義以下2兩個method:

- (id)objectAtIndexedSubscript:(NSUInteger);
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;

想要像NSDictionary一樣透過key存取,只要定義以下2兩個method:

- (id)objectForKeyedSubscript:(id)key;
- (void)setObject:(id)object forKeyedSubscript:(id)key;


有一點值得注意的,NSArray和NSDictionary要等到iOS 6 SDK才定義這2個method,因此目前尚未支援iOS 6的Xcode 4.4是無法以[ ] 存取NSArray和NSDictionary裡的元件,只有Xcode 4.5可以。



接下來彼得潘就以Peter Pan的自我介紹為例,說明如何讓自訂類別具有Object Subscripting的神奇魔力。

執行結果:






2012年5月1日 星期二

產生物件的類別method

很多時候,我們會另外定義類別method來快速地生成物件。比方於類別Animal裡定義create method。


有一點十分特別, 在類別method裡我們竟看到self的蹤跡。此時self代表類別物件。比方我們另外有個繼承自Animal的Dog類別,當我們呼叫以下程式碼時
[Dog Create];
最後將呼叫定義於Animal裡create method,而此時的self將是Dog類別,因此我們才能順利建出Dog物件,而不是四不像的Animal物件。

關於產生物件的類別method,還有一點值得注意,當牽扯到ARC時,回傳的物件是否由autorelease pool管理,取決於method名稱的開頭。只要method名稱不是以alloc, new, copy開頭時,回傳的物件即由autorelease pool統一管理。


因此,在以上的例子裡,我們將看到在viewDidLoad end被印出前,allocByGod,copyByGod, newByGod建立的物件都先一步結束生命。唯有createByGod建立的物件一息尚存,還被autorelease pool保護著,因此在viewDidLoad end後才結束生命。

2012年4月13日 星期五

飛天豬的category外掛




   小豬有沒有可能像彼得潘一樣翱翔於天際呢?
   只要發揮想像力,
   沒有什麼不可能的!
 
 
   接下來彼得潘將示範如何利用Objective-C獨門的category,
   施加魔法,
   讓Pig物件具有飛翔的能力。
   (感謝藝術家朋友Jorinde Jankowski (張友鷦)提供可愛的飛天豬)

1. 新增category


2. 設定category的名稱以及外掛作用的類別
   
    如下圖所示,
    Category填入Fly,Category on填入Pig,
    到時候category Fly將讓小豬比人類先一步長出翅膀。



    新產生的category檔案包含.h和.m
    檔名Pig+Fly其實正是外掛作用類別和category名稱的結合。




3. 定義category
    定義category的語法其實和定義類別雷同,
    只不過category名稱必須加在類別名稱後的 ( ) 裡。


 
 有一點值得注意的,
  category只能擴充原有物件的能力,
  因此其只能增添新method,
  並不能增加instance variable。
  比方Pig原本沒有hair,
  我們無法利用category讓其多了hair attribute。

4. 測試


為什麼不用繼承?



如果我們定義繼承自Pig的FlyPig類別,
不是也能實現飛天豬嗎?
category的最大好處在於它擴充的是原有物件的能力,
因此只要是Pig物件,
即可飛翔。
但如果採用繼承,
只有FlyPig可以飛翔。
尤其如果是內建的類別,
我們更可以體會category的美妙。
比方我們想讓NSString物件具有顛倒字串的能力,
此時我們只要創建作用於NSString上的Reverse category,
再定義reverseString method
即可讓所有的NSString物件皆具有顛倒是非,
哦,說錯了,
顛倒字串的能力。


Core Data的應用
我們也常利用category擴充NSManagedObject subclass的能力。
因為如果我們直接將新能力定義於NSManagedObject subclass,
每當我們修改表格欄位,
重新產生檔案時,
原來辛苦填寫的新method將消失無蹤







2011年4月6日 星期三

block in Objective-C

also known as closures or lambdas

block syntax:
1. ^
2. ( parameterType parameterName )
3. { code to be executed }


ex:
// declare a block variable test
void (^test)(void);
//  define block's code
test = ^ { NSLog("test"); };
// execute block
test();

ex:
void (^test)(void) = ^ { NSLog("test"); };

2011年3月25日 星期五

memory management in Objective-C

@property裡的設定:
     設成@property(copy)
     轉化為setter:
     ex:


  -(void)setName:(NSString*)newName
  {
     NSString *temp = name;
     name = [newName copyWithZone:nil];
     [temp release];
  }

     設成@property(retain)

     轉化為setter:
     ex:
     -(void)setName:(NSString*)newName
  {
    [newName retain];
    [name release];
    name = newName;
  }



garbage collection:
當有garbage collection,在@property裡設定retain其實和assign是一樣的。

2011年3月19日 星期六

copy of Objective-C

不是所有類別的物件都能copy,

只有遵從NSCopying protocol,實踐其copyWithZone: method的類別,才能被copy。

如果copy的物件是immutable,那麼將不會真的copy。
ex:
// 假設str的property設為copy
NSString *tempStr = @"abc";
self.str = tempStr;
-> 此時做的事和property設為retain是一樣的