你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> [IOS 開發]Objective - C 面向對象高級特性 - 包裝類 | 類處理 | 類別 | 擴展 | 協議 | 委托 | 異常處理 | 反射

[IOS 開發]Objective - C 面向對象高級特性 - 包裝類 | 類處理 | 類別 | 擴展 | 協議 | 委托 | 異常處理 | 反射

編輯:IOS開發綜合

 

 

 

 

一. Objective-C 對象簡單處理

 

 

 

 

 

 

1. 包裝類

 

 

 

 

(1) 包裝類簡介


 

NSValue 和 NSNumber :

-- 通用包裝類 NSValue : NSValue 包裝單個 short, int, long, float, char, id, 指針 等數據;

-- NSNumber 包裝類 : 用於包裝 C 語言數據類型;

 

NSNumber 方法 :

-- + numberWithXxx : : 將特定類型的值包裝成 NSNumber;

-- - initWithXxx : : 先創建一個 NSNumber 對象, 再用一個基本類型的值來初始化 NSNumber;

-- - xxxValue : : 返回 NSNumber 對象包裝的基本類型的值;

 

 

(2) 包裝類代碼示例


 

 

代碼示例 :

 

/*************************************************************************
    > File Name: OCNSNumberDemo.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 六 10/ 3 12:50:15 2015
 ************************************************************************/

#import 

int main(int argc, char * argv[])
{
	@autoreleasepool {
		NSNumber * num_int = [NSNumber numberWithInt : 10];
		NSNumber * num_double = [NSNumber numberWithDouble : 10];
		NSNumber * num_char = [NSNumber numberWithChar : 'A'];

		NSLog(@number_int : %d, number_double : %g, num_char : %c, 
			[num_int intValue], [num_double doubleValue], [num_char charValue]);
		
		NSNumber * num_int1 = [[NSNumber alloc] initWithInt : 10];
		NSNumber * num_double1 = [[NSNumber alloc] initWithDouble : 10];
		NSNumber * num_char1 = [[NSNumber alloc] initWithChar : 'A'];

		NSLog(@number_int1 : %d, number_double1 : %g, num_char1 : %c,
			[num_int1 intValue], [num_double1 doubleValue], [num_char1 charValue]);
	}
}

-- 執行結果 :

 

 

localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSNumberDemo.m
localhost:oc_object octopus$ ./a.out 
2015-10-03 13:00:46.465 a.out[887:507] number_int : 10, number_double : 10, num_char : A
2015-10-03 13:00:46.468 a.out[887:507] number_int1 : 10, number_double1 : 10, num_char1 : A


 

 

 

 

 

2. description 方法

 

 

 

 

 

(1) description 方法簡介


 

description 方法簡介 : 類似於 Java 中 Object 的 toString() 方法;

-- 方法來源 : description 是 NSObject 中定義的, 所有的方法都有該方法;

-- 默認方法 : description 默認方法返回 <類名: 地址>;

-- 輸出對象 : NSLog() 函數輸出一個對象, 其實輸出的是該對象的 description 方法;

-- 示例 : OCPerson * person, 打印 [person description] 和 person 輸出結果是一樣的;

 

 

 

(2) description 示例代碼


 

 

示例代碼 :

 

/*************************************************************************
    > File Name: OCDescriptionDemo.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 六 10/ 3 14:25:28 2015
 ************************************************************************/
#import 

@interface OCDescriptionDemo : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;
- (id) initWithNameAndAge : (NSString *) set_name setAge : (int) set_age;
@end

@implementation OCDescriptionDemo
@synthesize name;
@synthesize age;
- (id) initWithNameAndAge : (NSString *) set_name setAge : (int) set_age
{
	self.name = set_name;
	self.age = set_age;
	return self;
}
- (NSString *) description
{
	NSString * des = [NSString stringWithFormat : 
		@, self.name, self.age];
	return des;
}
@end

int main(int argc, char * argv[])
{
	@autoreleasepool {
		OCDescriptionDemo * description = [[OCDescriptionDemo alloc] initWithNameAndAge : @Tom setAge : 18];
		NSLog(@%@, description);
	}
}

-- 執行結果 :

 

 

localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCDescriptionDemo.m 
localhost:oc_object octopus$ ./a.out 
2015-10-03 14:50:18.665 a.out[970:507] 


 

 

 

 

3. == 或 isEqual : 方法

 

 

 

 

 

(1) == 運算符


 

== 簡介 :

-- 作用 : 判斷兩個變量是否相等;

-- 前提 : 兩個變量都是基本類型, 兩個變量相等返回 true; 指針類型變量比較地址沒有任何意義;

 

 

(2) 常量池


 

 

常量池 :

-- 作用 : 保證相同的字符串常量至右一個, 不能出現多個相同的副本;

-- 例外 : 使用 [NSString stringWithFormat] 方法創建的字符串不會放入常量池;

 

 

 

(3) isEqual 方法


 

 

isEqual 方法簡介 :

-- 來源 : isEqual 方法是 NSObject 類提供的實例方法, 用於判斷相同類型的兩個變量是否相等;

-- 默認 : 默認方法還是比較地址, 需要開發者重寫這個方法;

-- NSString 的 isEqual 方法 : NSString 的 isEqual 方法是判斷兩個字符串是否相等, 包含的字符串相同就會返回 true;

-- isEqualToString 方法 : 方法 : NSString 中定義的 isEqualToString 方法用於判斷當前字符串 與 另一個字符串的字符串序列是否相等;

 

 

重寫 isEqual 方法標准 :

-- 自反性 : 對象 x, [x isEqual : x] 必須返回 true;

-- 對稱性 : 對象 x 和 y, 如果 [x isEqual : y] 返回值 必須與 [y isEqual : x] 返回值相同;

-- 傳遞性 : 對象 x , y 和 z, [x isEqual : y] = true, [y isEqual : z] = true, 那麼 x z 也相等;

-- 一致性 : x , y 對象無論調用多少次, 返回值結果都應該保持一致;

-- nil 對比 : 如果 x 不是 nil, [x isEqual : nil] 必須返回 false;

 

 

 

(4) == 和 isEqual 示例源碼


 

 

示例源碼 :

 

/*************************************************************************
    > File Name: OCEqual.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 六 10/ 3 16:07:56 2015
 ************************************************************************/
#import 

@interface OCEqual : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age;

- (id) initWithName : (NSString *) set_name setAge : (int) set_age;
@end

@implementation OCEqual
@synthesize name;
@synthesize age;

- (id) initWithName : (NSString *) set_name setAge : (int) set_age
{
	self.name = set_name;
	self.age = set_age;
	return self;
}

- (BOOL) isEqual : (id) other
{
	if(self == other)
		return YES;

	if(other != nil && [other isMemberOfClass : OCEqual.class])
	{
		OCEqual * equal = (OCEqual *) other;
		return [self.name isEqual : equal.name] && (self.age == equal.age);
	}
	return NO;	
}
@end


int main(int argc, char * argv[])
{
	@autoreleasepool {
		int int_a = 10;
		int double_a = 10.0;

		NSLog(@int_a == double_a : %d, (int_a == double_a));
	
		NSString * str_a = @Octopus;
		NSString * str_b = @Octopus;
		NSString * str_c = [NSString stringWithFormat : @Octopus];
		NSString * str_d = [NSString stringWithFormat : @Octopus];

		NSLog(@str_a == str_b : %d, str_c == str_d : %d, [str_c isEqual : str_d] : %d, 
			str_a == str_b, str_c == str_d, [str_c isEqual : str_d]);
		
		OCEqual * equal_a = [[OCEqual alloc] initWithName : @Tom setAge : 18];
		OCEqual * equal_b = [[OCEqual alloc] initWithName : @Jerry setAge : 20];
		OCEqual * equal_c = [[OCEqual alloc] initWithName : @Jerry setAge : 20];

		NSLog(@[equal_a isEqual : equal_b] : %d, [equal_b isEqual : equal_c] : %d, 
			[equal_a isEqual : equal_b], [equal_b isEqual : equal_c]);
	}
}

-- 執行結果 :

 

 

localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCEqual.m 
localhost:oc_object octopus$ ./a.out 
2015-10-03 16:58:35.690 a.out[1168:507] int_a == double_a : 1
2015-10-03 16:58:35.693 a.out[1168:507] str_a == str_b : 1, str_c == str_d : 0, [str_c isEqual : str_d] : 1
2015-10-03 16:58:35.693 a.out[1168:507] [equal_a isEqual : equal_b] : 0, [equal_b isEqual : equal_c] : 1


 

 

 

 

 

二. 類別 與 擴展

 

 

 

 

 

 

1. Category 類別

 

 

 

 

(1) 擴展類簇需求


 

類簇擴展需求 : 開發過程中有時需要擴展類行為;

-- 繼承 : 通過繼承, 子類在父類基礎上添加方法 或者 重寫父類方法;

-- 問題 : 如果想要為父類增加一個方法, 子類同時也繼承這些方法, 此時使用繼承就滿足不了這個功能了;

-- 類簇 : OC 中沒有接口, 需要接口時, 就會選擇定義一個父類, 以該父類派生 N 個子類, 該系列的類被成為 類簇;

-- 類簇擴展方法 : 為父類增加方法, 類簇中得子類同時也增加該方法, 擴展類簇中得父類是最合適的方法;

 

 

 

(2) Category 類別


 

 

類別 (category) 簡介 :

-- 作用 : 為現有類添加方法, 不需要訪問原有類代碼, 不需要繼承;

-- 有點 : 動態地為現有類添加方法, 將類定義模塊化 分布到多個文件中;

 

 

 

(3) Category 類別 接口 語法格式


 

 

類別 (category) 接口部分語法格式 :

-- 接口文件類命名 : 類名+類別名.h, 如 要擴展 OCPerson 類, 類別名為 SB, 那麼接口文件名就是 OCPerson+SB.h;

-- 示例 :

 

@interface 已有類 (類別名)
//方法定義
...
@end

-- 類別名 : 必須是項目中沒有的類, 定義類別時使用的類名, 必須是已有的類;

 

-- 圓括號 : 類別名 定義在 需要擴展的已有類之後, 必須使用圓括號括起來;

-- 定義內容 : 類別中一般情況下只定義方法;

 

 

 

(4) Category 類別 實現類 語法格式


 

 

 

類別 (category) 實現部分語法格式 :

-- 實現類文件命名 : 類名+類別名.m, 如 要擴展 OCPerson 類, 類別名為 SB, 那麼接口文件名就是 OCPerson+SB.m;

-- 示例 :

 

@implementation 已有類 (類別名)
//方法定義
...
@end


 


 

 

(5) Category 類別 注意點


 

 

注意事項 :

-- 影響范圍 : 通過 category 添加新方法後, 會影響到 指定的被擴展的類, 同時也會影響到其子類;

-- 多個類別 : 一個類可以 對應多個類別, 這些類別都可以為類增加方法定義;

-- 類別優點 : 進行模塊化設計, 調用私有方法, 實現非正式協議;

 

 

 

(6) Category 擴展 NSNumber 示例


 

 

NSNumber 擴展示例 : 為其添加一個計算圓面積的方法;

-- NSNumber+SB.h :

 

/*************************************************************************
    > File Name: NSNumber+SB.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 六 10/ 3 18:58:53 2015
 ************************************************************************/
#import 
@interface NSNumber (SB)
- (NSNumber *) circleAera : (double) radius;
@end

-- NSNumber+SB.m :

 

 

/*************************************************************************
    > File Name: NSNumber+SB.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 六 10/ 3 19:02:05 2015
 ************************************************************************/
 #import NSNumber+SB.h
 @implementation NSNumber (SB)

 - (NSNumber *) circleAera : (double) radius
 {
	double aera = 3.1415926 * radius * radius;
	return [NSNumber numberWithDouble : aera];
 }

 @end

-- NSNumber+SBTest.m :

 

 

/*************************************************************************
    > File Name: NSNumber+SBTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 六 10/ 3 19:08:19 2015
 ************************************************************************/
#import 
#import NSNumber+SB.h

int main(int argc, char * argv[])
{
	@autoreleasepool {
		NSNumber * num = [NSNumber numberWithInt : 3];
		NSNumber * circleAera = [num circleAera : 1];
		NSLog(@%@, circleAera);
	}
}

-- 執行結果 :

 

 

localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation NSNumber+SB.m NSNumber+SBTest.m 
localhost:oc_object octopus$ ./a.out 
2015-10-03 19:18:13.625 a.out[1333:507] 3.1415926


 

 

 

 

2. Category 類別實際用法

 

 

 

 

 

(1) 類的模塊化設計


模塊化設計簡介 :

-- 實現部分唯一 : 定義一個類是, 使用 類名.h 定義接口部分, 使用 類名.m 定義實現部分, 不能將實現部分定義在多個 .m 後綴 文件中;

-- 文件臃腫 : 如果類很大, 將所有的代碼放在一個 類名.m 文件中, 非常難維護;

 

 

 

(2) 調用私有方法


 

 

私有方法調用簡介 :

-- 私有方法 : 接口中沒有定義, 在實現部分定義的方法是 私有方法, 不允許被外部調用;

-- 調用私有方法一 : 使用 NSObject 的 performSelector :執行調用, 也是可以調用私有方法的, 不過此方法會避開語法檢查, 導致未知問題;

 

 

 

(3) 調用私有方法 代碼示例


 

 

代碼示例 :

-- OCPrivate.h :

 

/*************************************************************************
    > File Name: OCPrivate.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 06:55:34 2015
 ************************************************************************/
#import 

@interface OCPrivate : NSObject
@property (nonatomic, copy) NSString * name;
-(void) info;
@end


 

-- OCPrivate.m :

 

/*************************************************************************
    > File Name: OCPrivate.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 06:57:48 2015
 ************************************************************************/
#import OCPrivate.h

@implementation OCPrivate
@synthesize name;

- (void) info
{
	NSLog(@name : %@, self.name);
}

- (void) speak
{
	NSLog(@Hello World !);
}
@end


 

-- OCPrivate+SB.h :

 

/*************************************************************************
    > File Name: OCPrivate+SB.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 07:19:35 2015
 ************************************************************************/
#import OCPrivate.h
@interface OCPrivate (SB)
- (void) speak;
@end


 

-- OCPrivateTest.m :

 

/*************************************************************************
    > File Name: OCPrivateTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 07:22:04 2015
 ************************************************************************/
#import OCPrivate+SB.h

int main(int argc, char * argv[])
{
	@autoreleasepool
	{
		OCPrivate * priva = [[OCPrivate alloc] init];
		priva.name = @Tom;
		[priva info];
		[priva speak];
		
	}
}


 

 

 

 

 

3. extension 擴展

 

 

 

 

(1) extension 簡介


 

extension 簡介 :

-- 作用 : 擴展相當於匿名類別;

-- 語法 :

 

@interface 已有類 ()
{
	//實例變量 ...
}
// 方法定義 ...
@end

-- 用法 : 定義兩個頭文件, OCExtension.h 和 OCExtension+speak.h, OCExtension.m 導入 OCExtension+speak.h 頭文件;

 

 

 

 

 

(2) extension 源碼示例


 

 

源碼示例 :

-- OCExtension.h :

 

/*************************************************************************
    > File Name: OCExtension.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 08:18:43 2015
 ************************************************************************/
#import 
@interface OCExtension : NSObject
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) int age; 

- (void) info;
@end


 

-- OCExtension+speak.h :

 

/*************************************************************************
    > File Name: OCExtension+speak.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 08:31:37 2015
 ************************************************************************/
#import OCExtension.h
@interface OCExtension ()
@property (nonatomic, copy) NSString * home;
- (void) speak : (NSString *) content;
@end


 

-- OCExtension.m :

 

/*************************************************************************
    > File Name: OCExtension.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 08:27:50 2015
 ************************************************************************/
#import OCExtension+speak.h
@implementation OCExtension
@synthesize name;
@synthesize age;
@synthesize home;
- (void) info
{
	NSLog(@info : name : %@ , age : %d, self.name, self.age);
}
- (void) speak : (NSString *) content
{
	NSLog(@%@ speak %@, self.name, content);
}
@end


 

-- OCExtensionTest.m :

 

/*************************************************************************
    > File Name: OCExtensionTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 日 10/ 4 13:20:42 2015
 ************************************************************************/
#import OCExtension+speak.h

int main(int argc, char * argv[])
{
	@autoreleasepool {
		OCExtension * extension = [[OCExtension alloc] init];
		extension.name = @Tom;
		extension.age = 18;
		extension.home = @China;

		[extension info];
		[extension speak : @Are you fucking kidding me];
	}
}


 

 

 

 

 

三. 協議 與 委托

 

 

 

 

 

 

1. 類別實現非正式協議

 

 

 

 

(1) 非正式協議簡介


 

協議簡介 :

-- 作用 : OC 中得協議作用相當於其它語言中得接口;

-- 協議表現 : 協議定義的是 多個類 共同的行為規范, 通常定義一組公用方法, 這些方法都沒有實現, 方法由類來實現;

 

非正式協議簡介 :

-- 創建 NSObject 類別 : 以 NSObject 為基礎, 為 NSObject 創建類別, 為該類別指定新增方法, 即給所有的 NSObject 子類增加了新方法;

-- 實現 NSObject 類別 : 實現 NSObject 類別時, 實現該列別下地所有方法, 即之前在 NSObject 類別中定義的方法;

 

 

 

(2) 非正式協議代碼示例


 

 

非正式協議代碼示例 :

-- NSObject+speak.h : 為 NSObject 定義的類別接口, 所有的繼承 NSObject 的類都必須實現該類別中得抽象方法;

 

/*************************************************************************
    > File Name: NSObject+speak.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 08:55:48 2015
 ************************************************************************/
#import 
@interface NSObject (speak)
- (void) speak;
@end


 

-- OCNSObjectProtocal.h : NSObject 子類接口, 該接口繼承 NSObject 類, 注意 需要導入 NSObject+speak.h 頭文件;

 

/*************************************************************************
    > File Name: OCNSObjectProtocal.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:00:37 2015
 ************************************************************************/
#import NSObject+speak.h
@interface OCNSObjectProtocal : NSObject
@end


 

-- OCNSObjectProtocal.m : OCNSObjectProtocal 實現類, 在該實現類中必須實現 類別中定義的 speak 方法;

 

/*************************************************************************
    > File Name: OCNSObjectProtocal.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:02:03 2015
 ************************************************************************/
#import OCNSObjectProtocal.h
@implementation OCNSObjectProtocal
- (void) speak
{
	NSLog(@Speak Hello World);
}
@end


 

-- OCNSObjectProtocalTest.m : 測試類, 測試以上代碼是否可以執行;

 

/*************************************************************************
    > File Name: OCNSObjectProtocalTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:04:31 2015
 ************************************************************************/
#import OCNSObjectProtocal.h

int main(int argc, char * argv[])
{
	@autoreleasepool {
		OCNSObjectProtocal * obj = [[OCNSObjectProtocal alloc] init];
		[obj speak];
	}
}


 

-- 執行結果 :

 

bogon:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSObjectProtocal.m OCNSObjectProtocalTest.m 
bogon:oc_object octopus$ ./a.out 
2015-10-05 09:06:44.895 a.out[2100:507] Speak Hello World


 

 

 

 

2. 定義正式協議


 

 

 

 

(1) 正式協議語法


 

 

正式協議語法 :

-- 語法 :

 

@protocol 協議名稱 <父類協議1, 父類協議2 ...>
// N 個協議方法
@end

-- 協議名稱規范 : 采用與類名相同的命名規則;

 

-- 繼承規則 : 一個協議 可以有 多個父類協議, 協議只能繼承協議, 不能繼承類;

-- 方法規則 : 協議中只能定義抽象方法, 不能定義方法實現, 既可以定義類方法, 也可以定義實例方法;

 

 

 

(2) 實現協議


 

 

實現協議語法 :

-- 語法 :

@interface 類名 : 父類 <協議1, 協議2...>
-- 對應關系 : 一個類可以實現多個協議;

 

 

 

 

(3) 聲明協議變量


 

 

變量聲明 :

-- 使用原變量聲明 : 變量名 * 對象名 , 如 OCCat * cat;

-- 使用協議定義 : NSObject <協議1, 協議2 ...> * 對象名, 如 NSObject * cat;

-- 使用 id 類型定義 : id 對象名, 如 id cat, 注意此處沒有指針標識;

 

 

 

(4) 正式協議實現代碼


 

 

代碼示例 :

-- OCAnimalProtocol.h : 最基礎的協議1;

 

/*************************************************************************
    > File Name: OCAnimalProtocol.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:25:41 2015
 ************************************************************************/
#import 
@protocol OCAnimalProtocol
- (void) name;
- (void) age;
@end


 

-- OCProtocolBord.h : 最基礎的協議2;

 

/*************************************************************************
    > File Name: OCProtocolBord.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:40:08 2015
 ************************************************************************/
#import 
@protocol OCProtocolBord
- (void) fly;
@end


 

-- OCProtocolCat.h : 該協議實現了 上面的兩個協議;

 

/*************************************************************************
    > File Name: OCProtocolCat.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:45:17 2015
 ************************************************************************/

#import 
#import OCAnimalProtocol.h
#import OCProtocolBord.h

@protocol OCProtocolCat 
- (void) purr;
@end


 

-- OCCat.h : OCCat 類接口部分, 生命了該類 實現協議 OCProtocolCat 協議;

 

/*************************************************************************
    > File Name: OCCat.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:50:21 2015
 ************************************************************************/

#import OCProtocolCat.h

@interface OCCat : NSObject 
@end


 

-- OCCat.m : OCCat 類實現部分;

 

/*************************************************************************
    > File Name: OCCat.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 09:52:45 2015
 ************************************************************************/

 #import OCCat.h

 @implementation OCCat
 - (void) name
 {
	NSLog(@name : cat);
 }
 - (void) age
 {
	NSLog(@age : 18);
 }
 - (void) fly
 {
	NSLog(@cat fly);
 }
 - (void) purr
 {
	NSLog(@cat purr);
 }
 @end


 

-- OCProtocolTest.m : 以上類的功能測試類;

 

/*************************************************************************
    > File Name: OCProtocolTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 10:14:38 2015
 ************************************************************************/

#import 
#import OCCat.h

int main(int argc, char * argv[])
{
	@autoreleasepool {
		OCCat * cat = [[OCCat alloc] init];
		[cat name];
		[cat age];
		[cat fly];
		[cat purr];

		NSObject * cat1 = [[OCCat alloc] init];
		[cat1 name];
		[cat1 age];
		[cat1 fly];
		[cat1 purr];

		id cat2 = [[OCCat alloc] init];
		[cat2 name];
		[cat2 age];
	}
}


 

-- 執行結果 :

 

bogon:6.4 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCProtocolTest.m 
bogon:6.4 octopus$ ./a.out 
2015-10-05 10:24:20.099 a.out[2271:507] name : cat
2015-10-05 10:24:20.101 a.out[2271:507] age : 18
2015-10-05 10:24:20.102 a.out[2271:507] cat fly
2015-10-05 10:24:20.102 a.out[2271:507] cat purr
2015-10-05 10:24:20.102 a.out[2271:507] name : cat
2015-10-05 10:24:20.103 a.out[2271:507] age : 18
2015-10-05 10:24:20.103 a.out[2271:507] cat fly
2015-10-05 10:24:20.104 a.out[2271:507] cat purr
2015-10-05 10:24:20.104 a.out[2271:507] name : cat
2015-10-05 10:24:20.104 a.out[2271:507] age : 18


 

 

 

 

 

3. 委托


 

 

委托概念 : 定義協議的類定義協議的方法 委托給 實現協議的類;

-- 好處 : 類具有更好地通用性, 具體的動作交給實現類完成;

 

 

創建工程 :

-- 歡迎界面, 選擇 Create a new xcode project;

/

-- 創建一個 OS 下地 Cocoa Application :

/

-- 創建 工程 :

/

 

 

項目中得源文件 :

-- main.m : main() 函數入口;

-- OCAppDelegate.h : OCAppDelegate 類接口文件;

-- OCAppDelegate.m : OCAppDelegate 類實現部分;

/

 

 

代碼示例 :

-- 前置操作 : 刪除 MainMenu.xib 文件, 刪除 Hello-Info.plist 中的 MainMenu 選項;

/

-- OCAppDelegate.h :

 

//
//  OCAppDelegate.h
//  Hello
//
//  Created by octopus on 15-10-5.
//  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import 

//該接口 實現 NSApplicationDelegate 協議
@interface OCAppDelegate : NSObject 
//定義窗口
@property (strong) NSWindow *window;

@end


 

-- OCAppDelegate.m :

 

//
//  OCAppDelegate.m
//  Hello
//
//  Created by octopus on 15-10-5.
//  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import OCAppDelegate.h

@implementation OCAppDelegate
@synthesize window;

//應用加載完成時回調的方法
- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
    //設置窗口屬性
    self.window = [[NSWindow alloc] initWithContentRect :
                   NSMakeRect(300, 300, 320, 200)
                   styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask |NSClosableWindowMask)
                   backing:NSBackingStoreBuffered
                   defer:NO];
    self.window.title = @Hello World;
    
    //設置文本框屬性
    NSTextField * label = [[NSTextField alloc] initWithFrame:NSMakeRect(60, 120, 200, 60)];
    [label setSelectable:YES];
    [label setBezeled:YES];
    [label setDrawsBackground:YES];
    [label setStringValue:@HELLO WORLD];
    
    //設置按鈕屬性
    NSButton * button = [[NSButton alloc] initWithFrame:NSMakeRect(120, 40, 80, 30)];
    button.title = @OCTOPUS;
    [button setBezelStyle:NSRoundedBezelStyle];
    [button setBounds:NSMakeRect(120, 40, 80, 30)];
    
    //將 文本框 和 按鈕 添加到窗口中
    [self.window.contentView addSubview:label];
    [self.window.contentView addSubview:button];
}

//加載完成時回調的方法
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
    //顯示窗口
    [self.window makeKeyAndOrderFront:self];
}

@end


 

-- main.m :

 

//
//  main.m
//  Hello
//
//  Created by octopus on 15-10-5.
//  Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//

#import 
#import OCAppDelegate.h

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        //創建一個實現了 NSApplicationDelegate 協議的對象
        OCAppDelegate * delegate = [[OCAppDelegate alloc] init];
        //獲取 NSApplication 單例對象
        [NSApplication sharedApplication];
        //設置代理, 將處理方法委托給 delegate
        [NSApp setDelegate : delegate];
        //開始運行程序
        return NSApplicationMain(argc, argv);
    }
    
}


 

-- 運行結果 :

/

 

 

 

 

 

 

四. 異常處理

 

 

 

 

 

 

1. @try ... @catch ... @finally ... 異常捕捉

 

 

 

 

(1) Objective-C 異常機制


 

Objective-C 異常機制 :

-- 作用 : 開發者將引發異常的代碼放在 @try 代碼塊中, 程序出現異常 使用 @catch 代碼塊進行捕捉;

-- 每個代碼塊作用 : @try 代碼塊存放可能出現異常的代碼, @catch 代碼塊 異常處理邏輯, @finally 代碼塊回收資源;

-- 語法示例 :

 

@try
{
	// 業務邏輯
}
@catch (異常類型名1 ex)
{
	//異常處理代碼
}
@catch (異常類型名2 ex)
{
	//異常處理代碼
}
// 可以捕捉 N 個 異常 ...
@finally
{
	//回收資源
}

 

 

 

 

 

(2) Objective-C 異常處理過程


 



異常處理過程 :

-- 生成異常對象 : @try 中出現異常, 系統會生成一個異常對象, 該對象提交到系統中 系統就會拋出異常;

-- 異常處理流程 : 運行環境接收到 異常對象時, 如果存在能處理該異常對象的 @catch 代碼塊, 就將該異常對象交給 @catch 處理, 該過程就是捕獲異常, 如果沒有 @catch 代碼塊處理異常, 程序就會終止;

-- @catch 代碼塊捕獲過程 : 運行環境接收到 異常對象 時, 會依次判斷該異常對象類型是否是 @catch 代碼塊中異常或其子類實例, 如果匹配成功, 被匹配的 @catch 就會處理該異常, 都則就會跟下一個 @catch 代碼塊對比;

-- @catch 處理異常 : 系統將異常對象傳遞給 @catch 形參, @catch 通過該形參獲取異常對象詳細信息;

 

其它注意點 :

-- @try 與 @catch 對應關系 : 一個 @try 代碼塊 可以對應 多個 @catch 代碼塊;

-- {} 省略問題 : 異常捕獲的 @try @catch @finally 的花括號不可省略;

 

NSException 異常類 :

-- 簡介 : NSException 是 OC 中所有異常的父類;

-- 位置永遠在最後 : @catch 代碼塊捕獲異常時查看 異常對象類型是否是 捕獲的異常類型 或者其子類, 一旦放在開頭, 後面的異常永遠不可能捕獲;

 

 

 

(3) 異常信息訪問


 

 

異常信息訪問 :

-- name : 返回異常的詳細名稱;

-- reason : 返回異常引發的原因;

-- userInfo : 返回異常的用戶信息, 一個 NSDictionary 對象;

 

 

 

 

(4) 使用 finally 回收資源


 

 

回收物理資源 : @try 代碼塊中打開物理資源, 數據庫 網絡連接 文件等, 都需要回收, 在 @finally 中回收最好;

-- 回收位置分析 : 如果再 @try 中回收, 出現異常, 異常後面的代碼無法執行, @catch 中回收, 如果不出現異常, 該代碼塊就不會執行; 因此 finally 中是必執行的代碼, 在這裡回收最合適;

 

 

 

 

(5) 異常代碼示例


 

 

異常代碼示例 :

-- OCAnimal.h : 定義協議;

 

/*************************************************************************
    > File Name: OCAnimal.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 16:30:02 2015
 ************************************************************************/
#import 

@protocol OCAnimal
@optional
- (void) run;
@end


 

-- OCCat.h : 定義 OCCat 接口;

 

/*************************************************************************
    > File Name: OCCat.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 16:33:59 2015
 ************************************************************************/
#import OCAnimal.h

@interface OCCat : NSObject 
@end


 

-- OCCat.m : 定義 OCCat 實現類;

 

/*************************************************************************
    > File Name: OCCat.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 16:36:36 2015
 ************************************************************************/
#import OCCat.h

@implementation OCCat
@end


 

-- OCCatTest.m : 測試類;

 

/*************************************************************************
    > File Name: OCCatTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 16:38:01 2015
 ************************************************************************/
#import OCCat.h

int main(int argc, char * argv[])
{
	@autoreleasepool {
		OCCat * cat = [[OCCat alloc] init];
		[cat run];
	}
}


 

-- 執行結果 :

 

bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatTest.m 
bogon:6.5 octopus$ ./a.out 
2015-10-05 16:39:23.589 a.out[2985:507] -[OCCat run]: unrecognized selector sent to instance 0x7fd7a3401870
2015-10-05 16:39:23.611 a.out[2985:507] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[OCCat run]: unrecognized selector sent to instance 0x7fd7a3401870'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff903dd25c __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x00007fff8ecdbe75 objc_exception_throw + 43
	2   CoreFoundation                      0x00007fff903e012d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
	3   CoreFoundation                      0x00007fff9033b044 ___forwarding___ + 452
	4   CoreFoundation                      0x00007fff9033adf8 _CF_forwarding_prep_0 + 120
	5   a.out                               0x0000000108575efd main + 109
	6   libdyld.dylib                       0x00007fff851f35fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6


 

 

 

 

(6) 異常捕獲代碼示例


 

 

異常捕獲取示例 : 該示例扔使用上面的 OCAnimal.h, OCCat.h, OCCat.m 示例;

-- OCCatTest.m :

 

/*************************************************************************
    > File Name: OCCatTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 16:38:01 2015
 ************************************************************************/
#import OCCat.h

int main(int argc, char * argv[])
{
	@autoreleasepool {
		@try
		{
			OCCat * cat = [[OCCat alloc] init];
			[cat run];
		}
		@catch (NSException * ex)
		{
			NSLog(@exception name : %@, reason : %@, ex.name, ex.reason);
		}
		@finally
		{
			NSLog(@finally execute);
		}
		NSLog(@success);
	}
}


 

-- 執行結果 :

 

bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatTest.m 
bogon:6.5 octopus$ ./a.out 
2015-10-05 16:53:46.850 a.out[3008:507] -[OCCat run]: unrecognized selector sent to instance 0x7f884bc018b0
2015-10-05 16:53:46.853 a.out[3008:507] exception name : NSInvalidArgumentException, reason : -[OCCat run]: unrecognized selector sent to instance 0x7f884bc018b0
2015-10-05 16:53:46.853 a.out[3008:507] finally execute
2015-10-05 16:53:46.854 a.out[3008:507] success


 

 

 

 

 

 

2. 拋出自定義異常


 

 

 

 

(1) 自定義異常語法


 

 

自定義異常拋出 :

-- 語法 :

@throw 異常對象;

 

 

 

 

(2) 自定義異常代碼示例


 

 

自定義異常代碼示例 :

-- OCException.h 接口 :

 

/*************************************************************************
    > File Name: OCException.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 16:58:24 2015
 ************************************************************************/
#import 

@interface OCException : NSException
@end


 

-- OCException.m 實現類 :

 

/*************************************************************************
    > File Name: OCException.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 17:03:15 2015
 ************************************************************************/
#import OCException.h

@implementation OCException
@end


 

-- OCCatTest.m 測試類 :

 

/*************************************************************************
    > File Name: OCCatTest.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 16:38:01 2015
 ************************************************************************/
#import OCException.h

int main(int argc, char * argv[])
{
	@autoreleasepool
	{
		@throw [[OCException alloc] 
			initWithName : @OCException 
			reason : @this reason is imporant
			userInfo : nil];
	}
}

 

 

-- 執行結果 :

 

bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCException.m OCCatTest.m
bogon:6.5 octopus$ ./a.out 
2015-10-05 17:04:12.432 a.out[3040:507] *** Terminating app due to uncaught exception 'OCException', reason: 'this reason is imporant'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff903dd25c __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x00007fff8ecdbe75 objc_exception_throw + 43
	2   a.out                               0x00000001062abef7 main + 135
	3   libdyld.dylib                       0x00007fff851f35fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type OCException
Abort trap: 6


 

 

 

 

五. Objective-C 反射

 

 

 

 

 

 

 

1. 獲取 Class

 

 

 

 

(1) 程序 與 環境 交互方式


 

程序 與 運行環境交互方式 :

-- 通過 OC 源碼 : 編寫 OC 源碼, 編譯器編譯, 運行在運行環境中;

-- 通過 NSObject 動態編程 : NSObject 是所有類的基類, 所有對象都可以直接調用 NSObject 方法;

-- 調用 運行時函數 動態編程 : 運行時系統是動態庫, 可以直接調用這些動態共享庫;

 

 

 

(2) 獲取 Class 方式


 

 

獲取 Class 方式 :

-- 通過類名 : 使用 Class NSClassFromString (NSString * aClassName) 函數獲取 Class 對象, 傳入 類名 字符串;

-- class 類方法 : 調用類方法 class, 調用方式 [NSString class];

-- class 對象方法 : 調用對象的 class 方法, 調用方式 [@hello class];

-- 推薦使用第二種方式 : 代碼更安全, 編譯階段就可以檢查 Class 是否存在, 程序性能高;

 

 

 

(3) 獲取 Class 代碼示例


 

代碼示例 :

 

/*************************************************************************
    > File Name: OCGetClass.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 23:31:51 2015
 ************************************************************************/

#import 

int main(int argc, char * argv[])
{
	@autoreleasepool {
		//通過 NSClassFromString 方法傳入 類名字符串 獲取 Class 對象
		Class clazz = NSClassFromString(@NSDate);
		NSLog(@%@, clazz);
		id date = [[clazz alloc] init];
		NSLog(@date : %@, date);

		NSString * str = @hello;
		// 通過調用 類 或 對象的 class 方法 
		NSLog(@[str class] : %@, [NSString class] : %@, [str class], [NSString class]);
		// 通過調用 類 或 對象的 getter 方法獲取, 即用 . 方法獲取
		NSLog(@str.class : %@, NSString.class : %@, str.class, NSString.class);

	}
}


 

-- 執行結果 :

 

bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCGetClass.m 
bogon:6.6 octopus$ ./a.out 
2015-10-05 23:39:28.692 a.out[3237:507] NSDate
2015-10-05 23:39:28.699 a.out[3237:507] date : 2015-10-05 15:39:28 +0000
2015-10-05 23:39:28.700 a.out[3237:507] [str class] : __NSCFConstantString, [NSString class] : NSString
2015-10-05 23:39:28.700 a.out[3237:507] str.class : __NSCFConstantString, NSString.class : NSString


 

 

 

 

2. 檢查繼承關系

 

 

 

 

 

(1) 繼承關系判斷


 

繼承關系判斷方法 :

-- 判斷類 : isMemberOfClass 方法, 傳入 Class 對象, 判斷該對象是否是 Class 對象對應類的實例;

-- 判斷類或子類 : isKindOfClass 方法, 傳入 Class 對象, 判斷該對象是否是 Class 對象對應類 或 子類的實例;

-- 判斷協議 : conformsToProtocol 犯法, 傳入 Protocol 參數, 傳入方法 @protocol(協議名稱) 或者 Protocol * NSProtocolFromString(NSString * @協議名稱) 兩種方法獲取協議參數;

 

 

 

(2) 繼承關系判斷代碼示例


 

 

源碼示例 :

-- OCAnimal.h : 定義協議;

 

/*************************************************************************
    > File Name: OCAnimal.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 23:54:14 2015
 ************************************************************************/
#import 

@protocol OCAnimal
- (void) name;
@end


 

-- OCCat.h : 定義接口;

 

/*************************************************************************
    > File Name: OCCat.h
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 23:56:16 2015
 ************************************************************************/
#import OCAnimal.h

@interface OCCat : NSObject 
@end


 

-- OCCat.m : 定義實現類;

 

/*************************************************************************
    > File Name: OCCat.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 一 10/ 5 23:58:47 2015
 ************************************************************************/
#import OCCat.h

@implementation OCCat
- (void) name
{
	NSLog(@My name is Tom);
}
@end


 

-- OCCatMain.m : 測試類;

 

/*************************************************************************
    > File Name: OCCatMain.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 二 10/ 6 00:00:01 2015
 ************************************************************************/
#import OCCat.h

int main(int argc, char * argv[])
{
	@autoreleasepool {
		OCCat * cat = [[OCCat alloc] init];
		NSLog(@%@, cat.class);

		NSLog(@cat isMemberOfClass OCCat : %d, [cat isMemberOfClass : OCCat.class]);
		NSLog(@cat isMemberOfClass NSObject : %d, [cat isMemberOfClass : NSObject.class]);
		NSLog(@cat isKindOfClass OCCat : %d, [cat isKindOfClass : OCCat.class]);
		NSLog(@cat isKindOfClass OCCat : %d, [cat isKindOfClass : NSObject.class]);
		NSLog(@cat conformsToProtocol OCAnimal : %d, [cat conformsToProtocol : @protocol(OCAnimal)]);
	}
}


 

-- 執行結果 :

 

bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatMain.m 
bogon:6.6 octopus$ ./a.out 
2015-10-06 00:07:56.838 a.out[3337:507] OCCat
2015-10-06 00:07:56.840 a.out[3337:507] cat isMemberOfClass OCCat : 1
2015-10-06 00:07:56.840 a.out[3337:507] cat isMemberOfClass NSObject : 0
2015-10-06 00:07:56.841 a.out[3337:507] cat isKindOfClass OCCat : 1
2015-10-06 00:07:56.841 a.out[3337:507] cat isKindOfClass OCCat : 1
2015-10-06 00:07:56.842 a.out[3337:507] cat conformsToProtocol OCAnimal : 1


 

 

 

 

3. 動態調用方法

 

 

 

 

 

(1) 動態調用成員變量

 

 

KVC 機制 : 通過該機制可以動態調用對象的 getter 和 setter 方法, 不論 該變量定義位置 (接口 | 實現) 和 使用何種訪問控制符 (private | public), 都可以使用 KVC 訪問;

 

 

 

(2) 判斷方法是否可調用


 

 

判斷對象是否可以調用方法 : NSObject 中定義了 respondsToSelector : 方法, 該方法傳入 SEL 參數, 該參數代表方法, 如果可以調用 返回 YES, 反之 返回 NO;

 

獲取 SEL 對象方法 :

-- 指令獲取 : 使用 @selector 指令獲取當前類中指定的方法, 參數是 完整的方法簽名關鍵字, 只有方法名不夠;

 

@selector(setAge:) withObject

 

-- 方法獲取 : 使用 SEL NSSelectorFromString(NSString * aSelectorName) 函數, 根據方法簽名關鍵字字符串獲取對應方法;

 

NSSelectorFromString(@setAge:)


 

 

 

 

(3) SEL 動態調用方法


 

 

動態調用對象方法 :

-- 動態調用一 : NSObject 的 performSelector : 方法可以調用方法, 需要傳入 SEL 對象, 傳入參數 可以通過 withObject: 標簽傳入參數;

 

[student performSelector : @selector(setAge:) withObject : [NSNumber numberWithInt : 18]];
[student performSelector : NSSelectorFromString(@setAge:) withObject : [NSNumber numberWithInt : 19]];


 

-- 動態調用二 : objc_msgSend(receiver, selector, ...) 函數調用方法, 參數一 方法調用者, 參數二 調用的方法, 剩余參數 方法參數;

 

objc_msgSend (student, @selector(setAge:), [NSNumber numberWithInt : 20]);
objc_msgSend (student, NSSelectorFromString(@setAge:), [NSNumber numberWithInt : 21]);


 

-- 注意 : 使用第二種方法需要導入包 #import , 返回浮點數時調用 objc_msgSend_fpret(), 返回結構體數據時 使用 objc_msgSend_stret() 函數;

 

 

 

 

(4) IMP 動態調用方法


 

 

IMP 動態調用方法 簡介 :

-- 獲取 IMP 對象 : NSObject 定義了 - (IMP) methodForSelector : (SEL) aSelector : 方法, 該方法傳入 SEL 參數, 返回 IMP 對象;

-- IMP 作用 : IMP 是 OC 方法函數指針變量, 代表函數入口, 通過 IMP 也可以調用函數;

-- IMP 調用方法語法 : 返回值類型 (*指針變量) (id, SEL, ...) , 參數一 方法調用者, 參數二 方法 SEL 對象, 後面參數是方法參數;

 

 

 

(5) 動態調用方法 示例代碼


 

 

示例代碼 :

-- OCStudent.m : 接口實現類主函數一體;

 

/*************************************************************************
    > File Name: OCStudent.m
    > Author: octopus
    > Mail: octopus_truth.163.com 
    > Created Time: 二 10/ 6 11:19:49 2015
 ************************************************************************/
#import 
#import 

@interface OCStudent : NSObject
@end

@implementation OCStudent

- (void) setAge : (NSNumber *) age
{
	int age_num = [age intValue];
	NSLog(@age is : %d, age_num);
}
@end

int main(int argc, char * argv[])
{
	@autoreleasepool
	{
		OCStudent * student = [[OCStudent alloc] init];

		[student performSelector : @selector(setAge:) withObject : [NSNumber numberWithInt : 18]];
		[student performSelector : NSSelectorFromString(@setAge:) withObject : [NSNumber numberWithInt : 19]];

		objc_msgSend (student, @selector(setAge:), [NSNumber numberWithInt : 20]);
		objc_msgSend (student, NSSelectorFromString(@setAge:), [NSNumber numberWithInt : 21]);
	}
}


 

-- 執行結果 : 有報警;

 

bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCStudent.m 
OCStudent.m:29:12: warning: performSelector may cause a leak because its selector is unknown [-Warc-performSelector-leaks]
                [student performSelector : NSSelectorFromString(@setAge:) withObject : [NSNumber numberWithInt : 19]];
                         ^
OCStudent.m:29:30: note: used here
                [student performSelector : NSSelectorFromString(@setAge:) withObject : [NSNumber numberWithInt : 19]];
                                           ^
1 warning generated.
bogon:6.6 octopus$ ./a.out 
2015-10-06 12:00:41.669 a.out[747:507] age is : 18
2015-10-06 12:00:41.671 a.out[747:507] age is : 19
2015-10-06 12:00:41.671 a.out[747:507] age is : 20
2015-10-06 12:00:41.672 a.out[747:507] age is : 21


 

 

 

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved