一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - IOS - Objective-C 入門篇(推薦)

Objective-C 入門篇(推薦)

2022-01-24 14:35會飛的狗~ IOS

由C語言和Smalltalk擴(kuò)展出來的,是C語言的超集,最大的區(qū)別是OC是面向?qū)ο蟮?,其火星文寫法對于之前從事Java開發(fā)的同學(xué)頗感蛋疼,OC最大特點(diǎn)之一是使用消息結(jié)構(gòu)而不是函數(shù)調(diào)用

 

前言

Objective-C is the primary programming language you use when writing software for OS X and iOS. It"s a superset of the C programming language and provides object-oriented capabilities and a dynamic runtime. Objective-C inherits the syntax, primitive types, and flow control statements of C and adds syntax for defining classes and methods. It also adds language-level support for object graph management and object literals while providing dynamic typing and binding, deferring many responsibilities until runtime.

Objective-C(下面簡稱OC)是由C語言和Smalltalk擴(kuò)展出來的,是C語言的超集,最大的區(qū)別是OC是面向?qū)ο蟮?,其火星文寫法對于之前從事Java開發(fā)的同學(xué)頗感蛋疼,OC最大特點(diǎn)之一是使用“消息結(jié)構(gòu)”而不是“函數(shù)調(diào)用”,所以在運(yùn)行時(shí)執(zhí)行的代碼由運(yùn)行環(huán)境決定,而Java是由編譯器決定。個(gè)人感覺有關(guān)于IOS學(xué)習(xí)的文章相較于Android質(zhì)量較低,有可能是蘋果系統(tǒng)封閉的原因,本文側(cè)重介紹常用的語法,通過對比Java并結(jié)合本人入門的過程和經(jīng)驗(yàn),幫助有需求的同學(xué)快速掌握OC基本編程,為IOS的入門奠定語言基礎(chǔ)。下面首先是寫出第一行代碼,恭喜正式進(jìn)入OC學(xué)習(xí)階段。

int main(int argc, char *argv[])
{
    @autoreleasepool //創(chuàng)建自動內(nèi)存釋放池
    {
    	//打印輸出
        NSLog(@"hello world ios!");
        return 0;
    }
}

下面介紹OC代碼的文件擴(kuò)展名:

 

文件擴(kuò)展名 類型
.h 頭文件,作用是對類、屬性、變量、函數(shù)等的聲明
.m 實(shí)現(xiàn)文件,對頭文件的生命實(shí)現(xiàn)或者擴(kuò)展
.mm 實(shí)現(xiàn)文件,一般是C++代碼

 

如果實(shí)現(xiàn)文件需要引入頭文件時(shí),推薦使用#import,跟#include作用相同,優(yōu)化了確保相同文件只會被引入一次,所以傾向用#import。

 

基本數(shù)據(jù)類型

包括:int float double char

類型 字節(jié)數(shù) 格式化輸出
char 1 %c
int 4 %i,%x,%o
unsigned int 4 %i,%x,%o
short int 2 %hi,%hx,%ho
unsigned short int 2 %hi,%hx,%ho
long int 8 %li,%lx,%lo
unsigned long int 8 %lu,%lx,%lo
long long int 8 %lli,%llx,%llo
unsigned long long int 8 %llu,%llx,%llo
float 4 %f
double 8 %f
long double 16 %Lf

 

其他數(shù)據(jù)類型

 

id類型

可以存放任何數(shù)據(jù)類型的對象,類似Java中的Object類,其被定義為指向?qū)ο蟮闹羔槪ū旧砭褪侵羔樍耍?,故定義比如id instance = nil;id類型是多態(tài)和動態(tài)綁定的基礎(chǔ)。

 

BOOL類型

布爾值為YES/NO或1/0。Java對應(yīng)是true/false

 

nil和Nil

nil相當(dāng)于Java中的null,表示一個(gè)對象,這個(gè)對象的指針指向空。Nil是定義一個(gè)指向空的類而不是對象。

 

NSString(不可變字符串)

字符串是非常重要常用的,務(wù)必要掌握常用的基礎(chǔ)用法,包括創(chuàng)建、截取、遍歷、比較、大小寫轉(zhuǎn)換、搜索等,語義跟基本類似Java。

//字符串
NSString *str1 = @"ABC3456789";
//拼接成新的字符串
 NSString *str2 = [str1 stringByAppendingString:@"wwww"];
NSLog(@"str = %@", str2);
//遍歷
for (int i = 0; i < [str2 length]; i++) {
    char temp = [str2 characterAtIndex:i];
    NSLog(@"字符串第 %d 位輸出 %c", i, temp);
}
//比較
// sEqualToString方法 :比較字符串是否完全相等,大小寫不一樣也無法完全匹配。
//hasPrefixe方法:逐一匹配字符串頭部。haSuffix方法:匹配字符串的尾部
if ([str2 isEqualToString:str1]) {
    NSLog(@"相等");
}
if ([str2 hasPrefix:@"www"]) {
    NSLog(@"有該頭部");
}
if ([str2 hasSuffix:@"www"]) {
    NSLog(@"有該尾部");
}
if ([str2 compare:str options:NSCaseInsensitiveSearch | NSNumericSearch] == NSOrderedSame) {
}
NSLog(@"比較結(jié)果:%d", [str2 caseInsensitiveCompare:str1]);
//大小寫轉(zhuǎn)換
NSLog(@"str3轉(zhuǎn)大寫:%@",[str2 uppercaseString]);
NSLog(@"str3轉(zhuǎn)小寫:%@",[str2 lowercaseString]);
NSLog(@"str3首字母轉(zhuǎn)大寫:%@",[str2 capitalizedString]);
//字符串截取
NSRange rang = NSMakeRange(2, 2);
NSLog(@"str3截?。?@",[str2 substringWithRange:rang]);
//搜索
NSRange rang1 = [str2 rangeOfString:@"www"];
NSLog(@"location: %d,length: %d",rang1.location,rang1.length);
//替換
//全部替換
NSString *str3 = [str2 stringByReplacingOccurrencesOfString:@" " withString:@"@"];
NSLog(@"替換后字符串為%@", str3);
//局部替換
NSString *str4 = [str2 stringByReplacingCharactersInRange:rang withString:@"met"];
NSLog(@"替換后字符串為%@", str4);

 

NSMutableString(可變字符串)

創(chuàng)建對象的基本寫法是[[NSMutableString alloc]init],*號代表對象,[]代表方法調(diào)用,只能通過類或者對象才能調(diào)用。[NSMutableString alloc]類似Java中new得到一個(gè)對象,然后再調(diào)用init初始化方法。

		//創(chuàng)建對象并初始化
		NSMutableString *mStr = [[NSMutableString alloc]init];
        //appendstring:向字符串尾部添加一個(gè)字符串。
        //appendFormat:向字符串尾部添加多個(gè)類型的字符串,可以添加任意數(shù)量與類型的字符串。
        [mStr appendString:@"hello world!"];
        NSLog(@"字符串創(chuàng)建%@", mStr);
        [mStr deleteCharactersInRange:[mStr rangeOfString:@"hello"]];
        //刪除
        NSLog(@"字符串刪除%@", mStr);
        //插入
        [mStr insertString:@"love you" atIndex: mStr.length];
        NSLog(@"字符串插入%@", mStr);

 

NSInteger、NSUInteger和NSNumber

NSInteger不是一個(gè)對象,而是基本數(shù)據(jù)類型中的typedef,NSUInteger是無符號的。 當(dāng)需要使用int類型的變量時(shí),推薦使用NSInteger,這樣不需要考慮設(shè)備是32位或者64位。NSNumber是一個(gè)類,用于包裝基本數(shù)據(jù)類型成為對象,可以理解為Java中的裝箱,為一些集合只能存放對象使用,通過字面量方式非常方便將基本數(shù)據(jù)類型轉(zhuǎn)成對應(yīng)的對象。例如:

//包裝
NSNumber *intNumber = [[NSNumber alloc]initWithInt:43];
//或者字面量方式
NSNumber *intNumber1 = @43;
//還原基本數(shù)據(jù)類型,解包
NSLog(@"%d",[intNumber intValue]);

 

集合

集合不能接受nil,nil是作為集合結(jié)束標(biāo)識符。

 

1. NSArray(不可變)

類似Java中的ArrayList,可以存儲不同類型的對象,一般情況下數(shù)組元素的類型是相同的,特點(diǎn)是有序、可重復(fù)。下面展示一位數(shù)組的基本操作: 

//字面量創(chuàng)建方式
    NSArray *arr2 = @[@"aaa",@"bbbbb"];
//工廠方法創(chuàng)建
    NSArray *array = [[NSArray alloc] initWithObjects:@"1", @"2", nil];
    //取最后一個(gè)元素
    [array lastObject];
//    取第一個(gè)元素
    [array firstObject];
//    數(shù)組是否包含某個(gè)元素
    [array containsObject:@"1"];
//    數(shù)組的大小
    int count = (int) array.count;
//    第一種方式遍歷
    for (int i = 0; i < count; i++) {
        NSString *_str = [array objectAtIndex:i];
    }

那么數(shù)據(jù)要求是多維的呢?多維數(shù)組可以理解為數(shù)組的數(shù)組,通過嵌套的方式,創(chuàng)建如下:

// 字面量創(chuàng)建二維數(shù)組并訪問
NSArray *arr2 = @[@[@11, @12, @13], @[@21, @22, @23], @[@31, @32, @33]];
// 字面量訪問方式(推薦)
NSLog(@"arr2[2][2]:%@", arr2[2][2]);
// 數(shù)組對象函數(shù)訪問
NSLog(@"arr2[2][2]:%@", [[arr2 objectAtIndex:2] objectAtIndex:2]);

 

2. NSMutableArray(可變的)

派生于NSArray,理解為動態(tài)數(shù)組,提供增加、刪除、插入、替換等語法糖。

		//創(chuàng)建,當(dāng)然還有其他方式
        NSMutableArray *mutableArr = [NSMutableArray arrayWithObjects:@"one",@"two",@"three", nil];
        //添加
        [mutableArr addObject:@"hello"];
        //替換
        [mutableArr replaceObjectAtIndex:2 withObject:@"tihuan"];
        //刪除
        [mutableArr removeObjectAtIndex:1];
        //插入
        [mutableArr insertObject:@"ios" atIndex:1];

多維數(shù)組創(chuàng)建方式如下:

   		// 初始化作為列的數(shù)組,看做4列
NSMutableArray *columnArray = [[NSMutableArray alloc]initWithCapacity:4];

// 初始化2個(gè)一維數(shù)組,每個(gè)一維數(shù)組有4個(gè)元素,看做1行4列,2行加起來就是2行4列
NSMutableArray *rowArray1 = [[NSMutableArray alloc]initWithCapacity:4];
NSMutableArray *rowArray2 = [[NSMutableArray alloc]initWithCapacity:4];

// 每個(gè)行依次增加數(shù)組元素
// 第一行
[rowArray1 addObject:@"11"];
[rowArray1 addObject:@"12"];
[rowArray1 addObject:@"13"];
[rowArray1 addObject:@"14"];

// 第二行
[rowArray2 addObject:@"21"];
[rowArray2 addObject:@"22"];
[rowArray2 addObject:@"23"];
[rowArray2 addObject:@"24"];

// 分別打印數(shù)組
NSLog(@"myRowArray1: %@", rowArray1);
NSLog(@"myRowArray2: %@", rowArray2);
NSLog(@"myColumnArray: %@", columnArray);

 

字典

類似于Java中的HashMap,是一種映射型數(shù)據(jù)結(jié)果,存儲鍵值對,有可變和不可變兩種類型。

 

NSDictionary

主要特點(diǎn)是不可變,如果集合初始化完成,將內(nèi)容無法修改,無序。

	//標(biāo)準(zhǔn)創(chuàng)建
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"cat",@"name1",@"dog",@"name2", nil];
    //字面量創(chuàng)建
    NSDictionary *dict1 = @{@"name1":@"cat",@"name2":@"dog"};
	//第一種遍歷
    for (NSString *key in [dict1 allKeys]) {
        NSLog(@"key: %@,value: %@", key, dict1[key]);
    }
    //第二種遍歷方式,通過遍歷器
    NSEnumerator *rator = [dict keyEnumerator];
    NSString *temp;
    while (temp = [rator nextObject]) {
        NSLog(@"%@", temp);
    }
    //獲取元素
	dict1[@"name"];
	[dict1 objectForKey:@"name"];
	//集合元素的個(gè)數(shù)
	NSInteger count = dict1.count;
	//沙盒文件存儲和讀取Plist
	[dict5 writeToFile:@"路徑" atomically:YES];
	NSDictionary *dict7 = [NSDictionary dictionaryWithContentsOfFile:@"路徑"];

 

NSMutableDictionary

NSMutableDictionary是NSDictionary的子類。NSMutableDictionary是可變的,動態(tài)添加、更改、刪除元素,因此不能使用字面量方式(@{})來創(chuàng)建一個(gè)可變字典。如果是不可變字典,出現(xiàn)了同名的key,那么后面的key對應(yīng)的值不會被保存,反之是可變字典,出現(xiàn)了同名的key,那么后面的值會覆蓋前面的值。

//創(chuàng)建
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
//添加
[dict setObject:@"dog" forKey:@"name"];
[dict setValue:@"18" forKey:@"age"];
//會將傳入字典中所有的鍵值對取出來添加到dict中
[dict setValuesForKeysWithDictionary:@{@"name1":@"dog"}];
//取元素
[dict objectForKey:@"name"];
dict[@"name"];
//刪除
[dict removeAllObjects];
[dict removeObjectForKey:@"name"];
[dict removeObjectsForKeys:@[@"name", @"age"]];
//更新,如果利用setObject方法給已經(jīng)存在的key賦值,新值會覆蓋舊值
[dict setObject:@"20" forKey:@"age"];
dict[@"age"] = @"30";

 

NSSet && NSMutableSet

具有很好的存取和查找功能,與NSArray相比NSSet的元素沒有索引,特點(diǎn)是無序,不可重復(fù),類似Java中的HashSet,其中NSMutableSet提供計(jì)算交并集的方法。

NSSet存儲元素的過程:

Objective-C 入門篇(推薦)

注意:推薦使用字面量方式創(chuàng)建對象,可以縮短代碼長度,增加可讀性。但是在創(chuàng)建數(shù)組的時(shí)候要注意,如果含有nil就會拋異常,因?yàn)樽置媪繉?shí)際上”語法糖“,效果等同于先創(chuàng)建一個(gè)數(shù)組,然后再把所有的對象添加進(jìn)來,保證數(shù)組不添加nil。

 

消息傳遞

前言提到Objective-C最大特點(diǎn)之一是繼承了Smalltalk消息傳遞模型,因此在OC中的方法調(diào)用準(zhǔn)備的說法是消息傳遞,類別與消息關(guān)系松散,調(diào)用方法是給對象發(fā)送消息,而方法是對消息的回應(yīng),所有消息的處理直到運(yùn)行時(shí)(即runtime)才會動態(tài)確定,并交由類自行決定如何處理收到的消息。總結(jié)是一個(gè)類不保證一定會回應(yīng)收到的消息,當(dāng)收到的一個(gè)無法處理的消息,會拋出異常。

Java或者C++方法調(diào)用:

obj.method(argument);

OC方法調(diào)用:

[obj method: argument];

我們都知道在Java或者C++中,如果類沒有定義method方法,那么編譯肯定不會通過,但是在OC中,理解是發(fā)送method的消息給obj,obj收到消息后再決定如何回應(yīng)消息,如果類內(nèi)定義了method方法則運(yùn)行,反之不存在運(yùn)行期拋出異常。

 

所有面向?qū)ο蟮木幊潭加蓄惖母拍睿糜诜庋b數(shù)據(jù),這樣的語言特性都有封裝、繼承和多態(tài)。OC對象是類在運(yùn)行期的實(shí)例,包含了類聲明的實(shí)例變量、內(nèi)存拷貝、類成員的指針等。由于OC是C語言的超集,類由兩個(gè)部分組成,分別是定義(interface)和實(shí)現(xiàn)(implementation),下面舉個(gè)?。新建一個(gè)People類,@interface是接口聲明的開始,@end終止結(jié)束,所有的OC編譯指令都是以”@“開始的。類的實(shí)現(xiàn)是通過@implementation指令開頭以@end結(jié)束。對應(yīng)People.h和People.m兩份文件,下圖是類聲明(People.h)的展示,主要包括繼承關(guān)系、成員變量、屬性、方法聲明等,方法的具體實(shí)現(xiàn)是在People.m。

Objective-C 入門篇(推薦)

下圖是方法聲明的展示:

Objective-C 入門篇(推薦)

當(dāng)然不止Interface區(qū)塊可以定義變量,Implementation區(qū)塊也可以定義,兩者區(qū)別是訪問權(quán)限不一。

前者默認(rèn)權(quán)限為protected,而implementation區(qū)塊的實(shí)體變量則默認(rèn)為private,所以類別私有可以放在implementation區(qū)塊。

 

訪問修飾符

  • @public:任何位置可以訪問。
  • @protected:默認(rèn)情況下成員變量的修飾符。
  • @private:變量只限于聲明它的類訪問,不允許被繼承。
  • @package:限定在當(dāng)前包內(nèi),類似于Java包的概念。

 

屬性

成員變量是給類內(nèi)使用的,屬性是作為類外訪問成員變量的接口,用于封裝對象的數(shù)據(jù),通過@property聲明,編譯器自動生成setter和getter方法,此過程稱為”自動合成“。類實(shí)現(xiàn)文件中@synthesize語法可以指定實(shí)例變量的名字,一般不推薦這樣做。@dynamic語法是告訴編譯器不要自動合成,在OC中訪問修飾符很少用到,主要是靠聲明屬性取值。

屬性有五個(gè)常用的特質(zhì)修飾:

assign:針對基本數(shù)據(jù)類型賦值操作。
strong:定義一種”擁有關(guān)系“,屬性設(shè)置新值時(shí),先保留新值,并釋放舊值,然后再將新值設(shè)置。
weak:跟strong相反,屬性所指的對象銷毀時(shí),屬性值也會清空。
copy:設(shè)置方法不保留新值,而是拷貝一份。
nonatomic:非原子,非線程安全類型。

Q&A:為什么NSString 、 NSArray、 NSDictionary的屬性要用copy,集合的深淺拷貝是怎樣的?

copy屬性作用是為變量賦值的時(shí)候系統(tǒng)自動copy一份內(nèi)存出來,修改新變量不會影響舊變量。在Apple規(guī)范中,NSString,NSArray,NSDictonary,推薦使用copy屬性,而其NSMubtableString,NSMutableArray, NSMutableDictonary屬性則使用strong屬性。

NSString *sourceString = [NSString stringWithFormat:@"hello ios"];
//不產(chǎn)生新的內(nèi)存空間
NSString *copyStr = [sourceString copy];
//產(chǎn)生新的內(nèi)存空間
NSMutableString *mutableStr = [sourceString mutableCopy];
NSLog(@"sourceString : %@   %p",sourceString,sourceString);
NSLog(@"copyStr : %@    %p",copyStr,copyStr);
NSLog(@"mutableStr : %@     %p",mutableStr,mutableStr);

Objective-C 入門篇(推薦)

使用strong這個(gè)屬性就有可能指向一個(gè)可變對象,如果這個(gè)可變對象在外部被修改了,那么會影響該屬性。例如:

//代碼塊   
NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];
NSLog(@"string address is: %p",string);
NSLog(@"stringCopy address is: %p",stringCopy);

結(jié)果:內(nèi)存地址不同

Objective-C 入門篇(推薦)

NSMutableString *string = [NSMutableString stringWithString:@"origin"];
//NSString *stringCopy = [string copy];
NSString *stringCopy = string;
[string appendString:@"change"];
NSLog(@"string address is: %p",string);
NSLog(@"stringCopy address is: %p",stringCopy);

結(jié)果:內(nèi)存地址相同

Objective-C 入門篇(推薦)

結(jié)論:

可變對象指向不可變對象會導(dǎo)致不可變對象的值被篡改,所以需要copy屬性。用@property聲明NSString、NSArray、NSDictionary 經(jīng)常使用copy關(guān)鍵字,是因?yàn)樗麄冇袑?yīng)的可變類型NSMutableString、NSMutableArray、NSMutableDictionary,彼此之間可能進(jìn)行賦值操作,為了不可變對象中的內(nèi)容不會被無意間變動,應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份。

淺拷貝:

在Java中淺拷貝如果是基本數(shù)據(jù),則拷貝的是基本數(shù)據(jù)的值;如果是對象,則拷貝的是內(nèi)存地址,修改該對象會影響另外一個(gè)對象。在OC中是對指針的拷貝,拷貝后的指針和原本對象的指針指向同一塊內(nèi)存地址,故同樣會相互影響。

Objective-C 入門篇(推薦)

深拷貝:

OC中不僅拷貝指針,而且拷貝指針指向的內(nèi)容,指針指向不同的內(nèi)存地址,故修改不會相互影響原本對象。

Objective-C 入門篇(推薦)

非集合類對象中:對immutable對象進(jìn)行copy操作,是指針復(fù)制(淺拷貝),mutableCopy操作時(shí)內(nèi)容復(fù)制;對mutable對象進(jìn)行copy和mutableCopy都是內(nèi)容復(fù)制(深拷貝)。

 

方法

通過”+“、”-“分別聲明類方法和實(shí)例方法,方法如果帶有多個(gè)參數(shù),參數(shù)在方法名之后接冒號定義,多個(gè)參數(shù)由空格隔開,如果參數(shù)個(gè)數(shù)可變,使用逗號接省略號。例如:

//無參數(shù)
- (void)print;
//有參數(shù)
- (void)print:(int)a andB:(int)b;

 

構(gòu)造方法

第一種是重寫init方法,第二種是自定義。

/**
 重寫初始化方法
 **/
- (instancetype)init
{
    self = [super init];
    if (self) {
        _peopleName = @"hello ios";
    }
    return self;
}

/**
 自定義初始化方法
 **/
- (instancetype)initWithNameAndAge:(NSString *)name andAge:(int)age
{
    self = [super init];
    if (self) {
        _peopleName = name;
        _peopleAge = age;
    }
    return self;
}

 

創(chuàng)建類對象

所有對象和類的引用都是通過指針實(shí)現(xiàn),嚴(yán)格地說指針就是一個(gè)地址,是一個(gè)常量,而指針變量可以被賦值不同的指針值,創(chuàng)建的對象就是一個(gè)指針變量,通過[People alloc]創(chuàng)建一個(gè)People對象,分配了內(nèi)存,init是初始化對象。構(gòu)造方法有兩種方式,第一種是重寫init方法,第二種是自定義。

People *p1 = [[People alloc] init];
//調(diào)用自定義的構(gòu)造方法
People *p3 = [[People alloc] initWithNameAndAge:@"mingzi" andAge:12];
//調(diào)用方法
[p3 print];

在OC 2.0中,如果創(chuàng)建的對象不需要參數(shù),可以直接使用new:

People *p1 = [People new];

 

self

作為OC的一個(gè)關(guān)鍵字,代表當(dāng)前類的對象,類似Java中的this,最大的作用是讓類中的一個(gè)方法調(diào)用該類另外一個(gè)方法或者成員變量,可以理解”當(dāng)前類誰調(diào)用了這個(gè)方法,self就代表誰“。

 

繼承

同Java一樣只能單繼承,只允許最多有一個(gè)直接父類。例如:定義一個(gè)父類Computer和子類MacBook。注意方法重寫類似Java,子類要重寫父類方法不需要重新聲明重寫方法,在實(shí)現(xiàn)部分直接重寫目標(biāo)方法即可。如果需要子類調(diào)用父類的方法,可以通過super關(guān)鍵字調(diào)用。

//Computer.h文件
#import <Foundation/Foundation.h>
@interface Computer : NSObject
@property(nonatomic,strong)NSString *name;
-(void)calculate;
@end

//  Computer.m
#import "Computer.h"
@implementation Computer
@synthesize name;
-(void) calculate{
    NSLog(@"i can calculate");
}
@end

//  MacBook.h
#import "Computer.h"
@interface MacBook : Computer
@end

//  MacBook.m
#import "MacBook.h"
@implementation MacBook
@end

//main.m
int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        MacBook *macBook = [[MacBook alloc] init];
        macBook.name = @"mac";
        [macBook calculate];
    }
}

 

多態(tài)

封裝、繼承和多態(tài)是面向?qū)ο缶幊陶Z言的三大特性,OC的多態(tài)是不同對象對同一消息的不同響應(yīng)方式,實(shí)際過程主要分為三種:

  • 繼承
  • 重寫
  • 指向子類的指針指向父類

可以看出跟Java的多態(tài)類似,理解起來應(yīng)該比較容易,注意是沒有方法重載的,在OC中不允許。

 

Runtime

實(shí)例:用Runtime新增一個(gè)類Person, person有name屬性,有sayHi方法

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import <objc/runtime.h>
#import <objc/message.h>
void sayHi(id self, IMP _cmd, id some)
{
    //self指的是調(diào)用該方法傳過來的類
    NSLog(@"%@說:%@,我%@歲", [self valueForKey:@"name"], some, object_getIvar(self, class_getInstanceVariable([self class], "_age")));
}

int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        //該方法動態(tài)創(chuàng)建一個(gè)類,arg1:繼承自哪個(gè)類 arg2:新建類的名稱 arg3:extraBytes
        Class Person = objc_allocateClassPair([NSObject class], "Person", 0);
        //添加兩個(gè)實(shí)例變量name和age,arg2:變量名稱,arg3:內(nèi)存地址大小,arg5:變量類型
        class_addIvar(Person, "_name", sizeof(NSString *), log2(sizeof(NSString *)), @encode(NSString *));
        class_addIvar(Person, "_age", sizeof(int), sizeof(int), @encode(int));
        //注冊方法名
        SEL s = sel_registerName("say:");
        //arg3:IMP是“implementation”的縮寫,這個(gè)函數(shù)指針決定了最終執(zhí)行哪段代碼
        //arg4:方法的參數(shù)及返回值
        class_addMethod(Person, s, (IMP)sayHi, "v@:@");
        //通過該類創(chuàng)建一個(gè)實(shí)體的對象
        id peopleInstance = [[Person alloc]init];
        //給對象的 name 實(shí)例變量賦值,下面是第二種賦值方式
        [peopleInstance setValue:@"XQM" forKey:@"name"];
        //Ivar nameIvar = class_getInstanceVariable(Person, "_name");
        //object_setIvar(peopleInstance, nameIvar, @"XQM");
        //獲取實(shí)例變量
        Ivar ageIvar = class_getInstanceVariable(Person, "_age");
        //為變量賦值
        object_setIvar(peopleInstance, ageIvar, @21);
        //調(diào)用sayHi方法,arg2:注冊指定的方法;arg3:帶上有一個(gè)字符串的參數(shù)
        ((void(*)(id, SEL, id))objc_msgSend)(peopleInstance, s, @"大家好");
        //調(diào)用完成,將對象置為空
        peopleInstance = nil;
        //通過 objc 銷毀類,銷毀的是一個(gè)類不是對象
        objc_disposeClassPair(Person);
    }
}

主要流程是:

定義類的方法->objc_allocateClassPair創(chuàng)建類->class_addIvar給類添加成員變量->sel_registerName注冊方法名->class_addMethod給類添加定義的方法->注冊該類->創(chuàng)建類對象->class_getInstanceVariable獲取成員變量,并通過object_setIvar賦值->objc_msgSend調(diào)用方法->釋放對象,銷毀類

 

Category(類別)

Objective-C借用并擴(kuò)展了Smalltalk實(shí)現(xiàn)中的"分類"概念,用以幫助達(dá)到分解代碼的目的。類別主要特點(diǎn)是不能增加屬性或者成員變量、增加類功能和分離類實(shí)現(xiàn),舉個(gè)例子: 在UIImageView增加了圖片異步加載的功能

@interface UIImageView (ImageViewLoader) <AysncImageDownloaderDelegate>
- (void)setOnlineImage:(NSString *)url placeholderImage:(UIImage *)image withRow:(NSNumber *)row;
@end

@implementation UIImageView (ImageViewLoader)

- (void)setOnlineImage:(NSString *)url placeholderImage:(UIImage *)image withRow:(NSNumber *)row;
{
    self.image = image;
    AsyncImageDownLoader *downloader = [AsyncImageDownLoader sharedImageDownloader];
    [downloader startWithUrl:url delegate:self withRow:row];
}
@end

 

Extension(拓展)

拓展也經(jīng)常用到,主要特點(diǎn)是增加ivar、用于接口分離等。例如:ViewController的實(shí)現(xiàn)文件增加@interface ViewController (),支持定義屬性等。

@interface ViewController ()
@property (nonatomic, copy) block b;
@end

@implementation ViewController
@end

 

異常處理

OC的異常處理極其類似Java中的,包括4個(gè)指示符,分別是@try、@catch、@throw、@finally??赡艽嬖诋惓5拇a寫在@try塊,異常處理邏輯寫在@catch,@finally塊的代碼總是要執(zhí)行的,@throw作用是拋出異常。

 

協(xié)議

類似Java中的接口(interface),類似多重繼承功能,支持協(xié)議繼承協(xié)議,通過定義一系列方法,然后由遵從協(xié)議的類實(shí)現(xiàn)這些方法,協(xié)議方法可以用@optional關(guān)鍵字標(biāo)記為可選,@required關(guān)鍵字標(biāo)記為必選,編譯器會出現(xiàn)檢查警告,一般來說還是可以編譯通過。下面看下語法:

@protocol ClickDelegate
- (void)click;
- (void)unclick;
@end

協(xié)議最常應(yīng)用在委托,分為委托方和代理方,委托方負(fù)責(zé)定義協(xié)議、通過id類型持有協(xié)議和調(diào)用協(xié)議的方法,而代理方則遵從協(xié)議、設(shè)置協(xié)議代理對象以及實(shí)現(xiàn)協(xié)議方法即可。

 

block

類似Java中的Lambda表達(dá)式,比較復(fù)雜,筆者的理解還未達(dá)到一定解說程度,所以這里先不做解釋,放到后續(xù)的文章中介紹。

 

內(nèi)存管理

Java的內(nèi)存管理是由垃圾回收器負(fù)責(zé),OC中引入自動引用計(jì)數(shù)(ARC),內(nèi)存管理交由編譯器決定。引用計(jì)數(shù)是每個(gè)對象都有一個(gè)計(jì)數(shù)器,如果對象繼續(xù)存活,計(jì)數(shù)器遞增其引用計(jì)數(shù),用完之后遞減引用計(jì)數(shù),如果計(jì)數(shù)變?yōu)?,表示對象可以被釋放了。NSObject協(xié)議聲明了Retain、release和autorelease方法用于操作計(jì)數(shù)器,分別是遞增、遞減、自動釋放操作,所有的對象都是收集器的工作對象。

ARC:自動引用計(jì)數(shù),編譯器自動生成retain/release
MRC:手動管理引用計(jì)數(shù),舊版本使用
autoreleasepool:延遲自動釋放

strong/weak/assgin最佳實(shí)踐

基本類型:assgin;
delegate->week;
集合和block用copy;
其他用strong;
block中的self用weak打破循環(huán)引用。

 

參考資料

https://www.jianshu.com/p/eb713b1f22dc
https://www.jianshu.com/p/6ebda3cd8052
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html

原文鏈接:https://blog.csdn.net/xiaoming100001/article/details/94337406

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产91在线精品狼人 | 天天久久综合 | 欧美一级欧美一级高清 | 红杏网| 女教师被学生糟蹋三天 | 肉色欧美久久久久久久蜜桃 | 奇米影视777最新在线 | 欧美日韩国产亚洲人成 | 99精品在线 | ai换脸明星造梦工厂忘忧草 | 亚洲AV午夜精品麻豆AV | 含羞草国产亚洲精品岁国产精品 | 高级黄色片 | 五月天国产精品 | 阿v天堂2020| 亚洲精品卡1卡二卡3卡四卡 | 被夫上司强迫中文 | 欧美军人男同69gay | 风间由美一区二区播放合集 | 欧美8x8x | 国产亚洲精品视频中文字幕 | 91短视频版高清在线观看免费 | 暖暖视频日本 | h肉动漫在线视频无修无遮挡 | 韩国三级视频网站 | 国产精品免费 | 国产成人精品一区 | 国产福利微拍精品一区二区 | 小草观看免费高清视频 | 亚洲免费在线看 | 双性np玩烂了np欲之国的太子 | 精品久久亚洲 | 国产福利一区二区在线精品 | 九九精品免费视频 | 免费观看欧美成人禁片 | 2020中文字幕 | 全是女性放屁角色的手游 | 国产精品久久一区 | 波多野结衣178部中文字幕 | 国产-第1页-草草影院 | 精品国产成a人在线观看 |