GeekBand Objective-C編程語言學(xué)習(xí)筆記(第一周)

第一天視頻課程:


Objective-C 語言簡介

Objective-C 語言是一門在C語言基礎(chǔ)上做了面向?qū)ο髷U展的編程語言访得,1983年由Brad Cox 和Tom Love發(fā)明龙亲,是目前蘋果開發(fā)平臺的主力語言,與Cocoa 和Cocoa Touch框架高度集成悍抑,支持開發(fā)Mac OS X鳄炉、iOS應(yīng)用。在蘋果開發(fā)平臺上通過LLVM(LowLevelVirtualMachine)編譯器架構(gòu)支持與Swift語言雙向互操作搜骡。


iOS開發(fā)平臺

Cocoa框架部分包括了系統(tǒng)內(nèi)核(Core OS)拂盯、內(nèi)核服務(wù)(Core Service)、媒體(Media)记靡、觸摸(Cocoa Touch)這幾個內(nèi)庫谈竿。通過LLVM編譯框架和Objective-C運行時編譯和運行团驱。目前主要有Objective-C、Swift和C/C++這幾種語言來進行編碼空凸,常用的開發(fā)工具為Xcode嚎花。


掌握高級編程語言的思維方式

底層思維:從微觀、機器的層面理解語言的構(gòu)造呀洲、編譯轉(zhuǎn)換紊选、內(nèi)存模型和運行時機制。

抽象思維:將我們周圍世界抽象為程序代碼道逗,即面向?qū)ο蟮乃季S方式丛楚,組件封裝、設(shè)計模式憔辫、架構(gòu)模式。


“時空人”三位一體分析方法

時間分析仿荆,發(fā)生在什么時候贰您?編譯時還是運行時。

空間分析拢操,變量放在那里锦亦?堆空間還是棧空間令境。

人物分析杠园,代碼哪里來的?程序員還是編譯器舔庶、運行時抛蚁、框架。


Objective-C 語言的兩種開發(fā)方式

Clang 或 GCC命令行:適合調(diào)試惕橙、研究瞧甩、微觀探查。

Xcode項目:適合構(gòu)建正規(guī)工程項目弥鹦,使用大型框架肚逸,追求設(shè)計質(zhì)量與代碼組織。


Objective-C 語言代碼學(xué)習(xí)

#import 導(dǎo)入頭文件(類似C語言的#include)彬坏,可以避免相同頭文件的重復(fù)導(dǎo)入朦促,推薦使用#import代替#include。

@autoreleasepool 支持ARC(Automatic Reference Counting)的一個池栓始,用來表明啟用了內(nèi)存自動回收機制务冕。

NSlog(@"Hello,world!"); NSlog類似C語言里的printf用來打印字符串,OC語言里的字符串前需要加@符號(@"Hello,world!")混滔。

?頭文件的擴展名是.h洒疚,主程序文件的擴展名是.m

編譯命名行:clang -fobjc-arc HelloWorld.m -o HelloWorld其中-fobjc-arc為ARC內(nèi)存管理的開關(guān)命名歹颓,其中-o HelloWorld,-o 為output即輸出的意思油湖,一起為將輸出的文件命名為HelloWorld巍扛。clang也可以換成gcc即用gcc編譯器編譯。(推薦用clang)

命名行:clang -help 用來顯示clang的設(shè)置幫助文檔乏德,可以用來了解clang的設(shè)置撤奸。

命名行:./HelloWorld 執(zhí)行生成的HelloWorld文件。


ObjC編譯過程

目前主流為LLVM-Clang的編譯過程喊括,由OC胧瓜、C\C++代碼通過Clang前端再通過LLVM優(yōu)化和LLVM代碼生成器生成出X86-64機器碼。


學(xué)習(xí)資源

蘋果官方文檔:https://developer.apple.com/library/

programming with Objective-C: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/

iOS專區(qū):https://developer.apple.com/library/ios/

蘋果開發(fā)者大會WWDC:https://developer.apple.com/videos/wwdc/2014/

??????????????????????WWDC:https://developer.apple.com/videos/wwdc/2015/


第二天視頻課程:


類型系統(tǒng)


引用類型 reference type:包括class郑什、pointer府喳、block。

值類型 value type:包括基礎(chǔ)數(shù)值類型蘑拯、結(jié)構(gòu)struct钝满、枚舉enum。

類型裝飾:包括協(xié)議protocol申窘、類別category弯蚜、擴展extension


類 class VS. 結(jié)構(gòu) struct

類型與實例:類的實例是對象,結(jié)構(gòu)的實例是值剃法。

類是一個引用類型碎捺,是位于棧上的指針指向了一個位于堆上的實體對象。

結(jié)構(gòu)是一個值類型贷洲,它直接位于棧中收厨。

例子1:聲明一個類(建立一個對外接口)

@interface RPoint:NSObject? //聲明一個類,類名RPoint优构,繼承自類NSObject帽氓。:表示繼承。

@property int x; //聲明一個屬性 int X

@property int y;

-(void)print; //聲明一個實例方法 print

@end

在OC中創(chuàng)建類時要先在頭文件中(.h)創(chuàng)建一個對外借口俩块,@interface來表示對外接口的起始黎休,用@end來對應(yīng)結(jié)束。

@property 在類中定義屬性的關(guān)鍵字玉凯,用來表示這個類的狀態(tài)势腮。

-(void)print 是在類中定義方法的語句,其中-表示是一個實例方法漫仆,方法的返回值是void,方法的名字是print.類中的方法來表示這個類的行為捎拯。

例子2:實現(xiàn)一個類

#import<Foundation/Foundation.h> //導(dǎo)入Foundation.h頭文件

#import"rpoint.h" //導(dǎo)入rpoint.h頭文件,即上面我們創(chuàng)建的類聲明文件盲厌。

@implementation RPoint? //定義一個類名為RPoint?的類

-(void)print{

NSLog(@"[%d,%d]", self.x, self.y);? //print方法的實現(xiàn)

}

@end

OC的類需要在主文件中(.m)實現(xiàn)署照,@implementation 來表示實現(xiàn)的起始祸泪,用@end來對應(yīng)結(jié)束。

NSLog(@"[%d,%d]", self.x, self.y);? NSLog表示打印一個字符串建芙,self表示當(dāng)前的事例没隘,整句語句表示將當(dāng)前事例的屬性x和y打印出來。

例子3:

#import<Foundation/Foundation.h>

#import"rpoint.h" //導(dǎo)入類所在的文件

#import"spoint.h"? //導(dǎo)入結(jié)構(gòu)體所在的文件

void process(RPoint* rp3, SPoint sp3); //函數(shù)process的聲明

int main(int argc, const char * argv[]){ //入口函數(shù)

??? @autoreleasepool{

????? RPoint* rp1=[[RPoint alloc]init]; //生成一個RPoint類的對象rp1

????? rp1.x=10;

????? rp1.y=20;

????? [rp1 print]; //顯示結(jié)果為10禁荸, 20

????? SPoint sp1; //生成一個SPoint結(jié)構(gòu)體實例右蒲。

????? sp1.x=10;

????? sp2.y=20;

????? NSLog(@"拷貝----------");

????? RPoint* rp2=rp1;

????? rp2.x++;

????? rp2.y++;

????? [rp1 print]; //顯示結(jié)果為11赶熟, 21

????? [rp2 print]; //顯示結(jié)果為11瑰妄, 21

????? SPoint sp2=sp1;

????? sp2.x++;

????? sp2.y++;

????? NSLog(@"[%d,%d]",sp1.x, sp1.y);?//顯示結(jié)果為10, 20

????? NSLog(@"[%d,%d]",sp2.x, sp2.y); //顯示結(jié)果為11映砖, 21

????? NSLog(@"傳參----------")

????? process(rp1, sp1);

????? [rp1 print]; //顯示結(jié)果為12间坐, 22

????? NSLog(@"[%d,%d]",sp1.x, sp1.y); //顯示結(jié)果為10, 20

??? }

??? return0;

}

void process(RPoint* rp3, SPoint sp3){

? rp3.x++;

? rp3.y++;

? sp3.x++;

? sp3.y++;

? [rp3 print];

? NSLog(@"[%d,%d]",sp3.x, sp3.y);

}

RPoint* rp1=[[RPoint alloc] init]; //在內(nèi)存椧赝耍空間創(chuàng)建了一個名字為rp1的RPpoint類實例對象眶诈。[]為調(diào)用符號,調(diào)用也可以稱為發(fā)送消息瓜饥。alloc的用處是手動在堆空間申請內(nèi)存空間,init為初始化所分配的空間浴骂。


拷貝行為內(nèi)存視圖


傳參行為內(nèi)存視圖

堆(heap):堆空間用于存儲引用類型對象乓土,由程序員手動申請內(nèi)存空間,釋放由運行時ARC機制自動釋放溯警,函數(shù)之間通過拷貝引用(指針)傳遞趣苏。堆空間具有全局性,總體大小受制于系統(tǒng)內(nèi)存整體大小梯轻。

由于rp1是一個類的實例對象食磕,所以無論是復(fù)制還是傳參,都是由一個棧中的指針指向堆中的實體對象喳挑,復(fù)制副本和傳參參數(shù)的改變都能直接導(dǎo)致rp1指向的實際對象發(fā)生改變彬伦。

SPoint sp1; //在內(nèi)存的堆空間創(chuàng)建了一個名字為sp1的結(jié)構(gòu)體。

棧(stack):椧了校空間用于存儲值類型单绑,無ARC負擔(dān),由系統(tǒng)自動管理曹宴,以執(zhí)行函數(shù)為單位搂橙。棧的空間大小在編譯時確定(根據(jù)參數(shù)+局部變量來計算),在函數(shù)執(zhí)行時由系統(tǒng)自動分配一個棧笛坦,函數(shù)執(zhí)行結(jié)束系統(tǒng)立即自動收回該椙空間苔巨,函數(shù)之間通過拷貝值傳遞。椃侠耄空間具有局部性侄泽,大小有限額(編譯工具可以設(shè)定棧的大小,一般為1M)厅缺,超出會棧溢出(stack overflow)蔬顾。

由于sp1是一個結(jié)構(gòu)值,它存儲于棧中湘捎,無論復(fù)制還是傳參诀豁,都將在棧中復(fù)制一個sp1的副本,sp1的原始值保持不變窥妇。


第三天視頻課程:


OC類的類型成員

OC類所包含的類型成員(Type Member)主要分為兩大類舷胜,一類是數(shù)據(jù)成員(data member)用來描述對象的狀態(tài),還有一類是函數(shù)成員(function member)用來描述對象的行為活翩。其中數(shù)據(jù)成員又有實例變量(instance variable)和屬性(property)兩種烹骨。函數(shù)成員分為方法(method)、初始化器(init)和析構(gòu)器(dealloc)三種材泄。

認識屬性


屬性表達實例狀態(tài)沮焕,描述類型對外接口。相比直接訪問實例變量拉宗,屬性可以做更多控制峦树。

默認情況下,編譯器會為屬性定義propertyName自動合成一個getter訪問器方法:propertyName旦事、一個setter訪問器方法:setPropertyName還有一個實例變量_propertyName魁巩。

舉例:

在OC類中聲明一個屬性:@property NSString* firstName; //聲明一個類所包含的屬性。

此時編譯器會自動生成類似如下代碼姐浮,但是并不顯示出來:

-(NSString*)firstName{? //生成一個getter函數(shù)

???return _firstName;

}

-(void)setFirstName:(NSString *)newValue{? //生成一個setter函數(shù)

??_firstName=newValue;

}

NSString* _firstName; //創(chuàng)建一個以 _(下劃線)+屬性名的實例變量

由于編譯器自動生成了類似如上代碼谷遂,我們可以用編譯器生成的getter方法和setter方法來訪問或修改該屬性的內(nèi)容。

例如:

Employee* employee=[[Employee alloc] init];

[employee setFirstName: @"Tom"]; //將employee類的FirstName屬性設(shè)置為“Tom”卖鲤,setFirstName這個setter方法是編譯器自動生成的肾扰。

NSLog(@"First Name: %@", [employee firstName]); //打印出employee類的FirstName屬性,此處[employee firstName]是調(diào)用了編譯器自動生成的getter方法firstName蛋逾。

除了以上的方法來訪問getter和setter方法外白对,可以用類名+.(點表達式)+屬性名來訪問屬性的getter和setter方法。

例如:

employee.lastName=@"Chen"; //訪問了lastName屬性的setter表達式,等價于[employee setFirstName: @"Chen"];

NSLog(@"First Name: %@", employee.lastName); //訪問了lastName屬性的getter表達式换怖,等價于NSLog(@"First Name: %@", [employee firstName]);

兩種方法在本質(zhì)上沒有什么區(qū)別甩恼,推薦用點表達式,使用比較方便。


可自定義訪問器方法条摸,也可更改訪問器方法名或?qū)嵗兞棵?/strong>

例如:

@property (readonly) NSString* fullName; //在頭文件中定義了一個只讀屬性fullName

-(NSString *)fullName{

? return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];

} //在主文件中自定義了fullName屬性的getter訪問器方法悦污。stringWithFormat函數(shù)是用來鏈接兩個字符串類實例。

@property (getter=GivenName, setter=GivenName:) NSString* firstName; //聲明firstName屬性時將該屬性的getter钉蒲、setter訪問器的名字都設(shè)置為GivenName切端。

@synthesize firstName=givenName; //在主文件中將firstName屬性由系統(tǒng)自動生成的_firstName實例變量改名為givenName。

可以使用靜態(tài)全局變量(C語言)+類方法顷啼,模擬類型屬性踏枣。

static int _max=100; //在主文件中定義一個靜態(tài)變量_max

+(int)max; //在頭文件中聲明一個類方法(getter訪問器) +(int)max

+(void)setMax:(int)newValue; //在頭文件中聲明一個類方法(setter訪問器)? +(void)setMax

+(int)max{

return _max;? //在主文件中實現(xiàn)類方法+(int)max

}

+(void)setMax:(int)newValue{

????? _max=newValue;? //在主文件中實現(xiàn)類方法+(void)setMax

}

完成以上步驟后,可以實現(xiàn)訪問類型屬性钙蒙。

[Employee setMax:400]; 等同于Employee.max=400; 模擬出來的類屬性茵瀑。


實例變量

可以定義實例變量,而不定義屬性(這樣外部不能訪問到實例變量)躬厌,只有實例變量马昨,沒有類變量(使用靜態(tài)全局變量+類方法可以模擬出類變量的效果)。

如果同時自定義了getter和setter訪問器方法扛施,或者針對只讀屬性定義了getter訪問器方法鸿捧,編譯器將不再合成實例變量。

引用類型的實例變量在類外一律使用屬性來訪問疙渣,類內(nèi)大多也通過self使用屬性訪問匙奴。只有以下情就卡了況使用實例變量來訪問:1、初始化器 init? 2妄荔、析構(gòu)器 dealloc 3泼菌、自定義訪問器方法。?


實例變量的生存周期

實例變量的儲存:跟隨對象實例存儲在堆上懦冰。

值類型實例變量直接“內(nèi)嵌”在對象實例中。跟隨對象實例內(nèi)存釋放而被釋放谣沸。

引用類型實例變量通過指針“引用”堆上的引用類型實例刷钢,ARC針對引用進行計數(shù)管理,自動釋放引用計數(shù)為0的對象乳附。


屬性的描述特性(Attribute)

屬性的描述特性可以指定屬性不同環(huán)境下的不同功能内地。

讀寫特性,默認情況屬性都是可讀寫(readwrite)的赋除,也可以設(shè)置為只讀(readonly)屬性阱缓。

例如:

@property (readonly) NSString* fullName; //在頭文件中定義了一個只讀屬性fullName

多線程特性,默認情況下是屬性是原子性(atomic)的举农,表示多線程時原子性屬性不能被線程搶走荆针,要么沒有運行,開始運行了必須運行到結(jié)束。也可以設(shè)置為非原子性(nonatomic).

例如:

@property (nonatomic) NSString* fullName; //在頭文件中定義了一個非原子性屬性fullName


內(nèi)存管理特性

引用屬性默認為強(strong)引用屬性航背,弱(weak)引用阻止循環(huán)引用喉悴。當(dāng)兩個實例對象屬性相互強引用時會形成循環(huán)引用,這時ARC內(nèi)存管理將視這兩個互引用的屬性都占用玖媚,無法將這兩個實例的引用屬性釋放箕肃。

兩個類型相互強引用導(dǎo)致內(nèi)存泄露。

為了避免上述情況發(fā)生把其中一個對象屬性設(shè)置為弱引用今魔,這樣就不會出現(xiàn)不能釋放的問題了勺像。


一個弱引用一個強引用就可以互相引用,并可以正常釋放內(nèi)存


拷貝(copy)屬性創(chuàng)建獨立拷貝错森,當(dāng)引用屬性不想被外界直接引用時吟宦,可以用拷貝屬性,讓外界引用一個拷貝副本问词,來確保原始數(shù)據(jù)不會被外界修改督函。

不使用拷貝特性時,被引用將多一條指針指向?qū)嵗龑傩?/div>


使用拷貝特性后激挪,被引用時多一條指針指向?qū)嵗龑傩缘母北?/div>


第四天視頻課程:


認識方法 Method

代碼段上的可執(zhí)行指令序列就是函數(shù)辰狡,函數(shù)有全局函數(shù)(C語言函數(shù)),和成員函數(shù)(OC中也叫方法)垄分。

方法是類的成員函數(shù)宛篇,表達實例行為或類型行為。

舉例:

以下聲明了4個方法

-(void) print; //-表示是實例方法薄湿,返回值是void, 方法名是print, 無參數(shù)

-(BOOL) isEqualToPoint: (BLNPoint*) point; //返回值是BOOL, 參數(shù)名是point, 參數(shù)類型是BLNPoint*

-(void) moveToX: (int)x toY: (int)y;? //有兩個(int)類型的參數(shù)x和y

+(BLNPoint*) getOriginPoint; //+表示getOriginPoint是一個類方法

所有方法默認為公有方法叫倍。沒有private或protected方法(可以在接口文件中不要聲明方法,而在實現(xiàn)文件中實現(xiàn)方法來做到類似private方法)豺瘤。

動態(tài)消息發(fā)布:方法調(diào)用通過運行時動態(tài)消息分發(fā)實現(xiàn)吆倦,在對象上調(diào)用方法又稱“向?qū)ο蟀l(fā)送消息”。

例子:

[p1 print]; //實例p1調(diào)用了print方法坐求,也可以說向?qū)ο髉1發(fā)送了一個print消息

[p1 moveToX:100 toY:200]; //向?qū)ο髉1發(fā)送了一個moveToX消息蚕泽,其中還包含了兩個參數(shù),100和200

BLNPoint* origin=[BLNPoint getOriginPoint]; //向BLNPoint類發(fā)送了一個getOriginPoint消息桥嗤,返回值賦值給BLNPoint的類型實例origin


實例方法或類型方法

實例方法用來表達實例的行為所以只能通過實例對象來調(diào)用须妻,實例方法在內(nèi)部實現(xiàn)時可以訪問實例成員包括實例屬性、實例變量和實例方法泛领。也可以訪問類型方法和靜態(tài)變量荒吏。

類方法用來表達類的行為只能通過類來調(diào)用,類型方法在實現(xiàn)時可以訪問類型方法和靜態(tài)變量渊鞋,不能訪問實例成員包括實例屬性绰更、實例變量和實例方法瞧挤。

編譯器背后對實例方法和類方法的不同處理:self指針

例子:

實例方法實現(xiàn)

-(void) print{

????? NSLog(@"[%d, %d]", self.x, self.y);

}

上面的實例方法實現(xiàn)中self實際上是一個隱藏的指針參數(shù),用來傳遞當(dāng)前實例地址,編譯器編譯后用C語言的表達方式可以寫成:

void print(BLNPoint* self){

????? NSLog(@"[%d, %d]", self.x, self.y);

}

調(diào)用該方法時:[p1 print]; //print(p1);

類方法實現(xiàn)

+(BLNPoint*) getOriginPoint{

????? BLNPoint* origin=[[BLNPoint alloc] init];

????? origin.x=0;

????? origin.y=0;

????? return origin;

}

上述的類方法實現(xiàn)編譯后用C語言表示為

BLNPoint* getOriginPoint(){

????? BLNPoint* origin=[[BLNPoint alloc] init];

????? origin.x=0;

????? origin.y=0;

????? return origin;

}

類方法里面不能用self關(guān)鍵字來訪問實例變量动知,但是依然可以使用self關(guān)鍵字皿伺,這時self關(guān)鍵字用來表示當(dāng)前類。在類方法實現(xiàn)里面可以用[self process]來調(diào)用當(dāng)前類中的process方法盒粮,也等同于[BLNPoint process]鸵鸥。


方法參數(shù)

如果參數(shù)類型是值類型,為傳值方式丹皱,如果參數(shù)類型為引用類型妒穴,則為傳指針方式。

方法可以沒有參數(shù)摊崭,也可以沒有返回值讼油。

如果方法有參數(shù),方法名約定包含第一個參數(shù)呢簸,從第二個參數(shù)開始需要顯示提供外部參數(shù)名矮台。

-(void) moveToX: (int)x toY: (int)y;?//toY是第二個參數(shù)的外部參數(shù)名,x是第一個內(nèi)部參數(shù)名根时,y是第二個內(nèi)部參數(shù)名瘦赫。

調(diào)用時,第一個參數(shù)名忽略蛤迎,但后面的參數(shù)名必須顯示標(biāo)明确虱。如: [p1 moveToX:100 toY:200];


動態(tài)方法調(diào)用機制--消息分發(fā)表

在OC里所有的對象類型都可以聲明為id類型

例子:

id obj=[[BLNPoint alloc] init];

[obj moveToX:50 toY:60];

[obj print];

這里類型為id的對象obj可以調(diào)用類型為BLNPoint的對象方法,是由于OC的動態(tài)調(diào)用機制造成的替裆。


消息分發(fā)機制

OC中調(diào)用所有方法都會通過消息分發(fā)表校辩,上圖灰色的部分其中有一個指針,指向class再指向method list辆童。這樣做可以增加靈活性宜咒,支持在運行時向方法表添加新的方法。缺點是每次調(diào)用方法都要多次尋址有性能損失把鉴。


第五天視頻課程:


初始化器與析構(gòu)器

初始化器和析構(gòu)器是類型的特殊函數(shù)成員故黑,初始化器用于初始化對象實例或者類型。

對象初始化器:-(id)init 可以重載多個纸镊。

例子:

在頭文件中可以聲明多個有不同參數(shù)列表的-(id)init函數(shù)倍阐。

-(id)init;

-(id)initWithName:(NSString *)name;

-(id)initWithName:(NSString *)name WithPages:(int)pages;

-(id)initWithName:(NSString *)name WithPages:(int)pages WithCategory:(NSString *)category;

在主文件中實現(xiàn)聲明的init方法

-(id)init{

????? self = [super init];

????? if(self){? //如果父類初始化失敗self指針將等于Null

??????? NSLog(@"Book Object init“); //在調(diào)用了父類的init方法后可以添加自己所需的內(nèi)容。

????? }

????? return self;

}

-(id)initWithName:(NSString *)name WithPages:(int)pages{

????? return [self initWithName:name WithPages:pages WithCategory:@"General"];

}

-(id)initWithName:(NSString *)name WithPages:(int)pages WithCategory:(NSString *)category{ //由于該初始化器的參數(shù)是最多的,作為主初始化器恒界,其他參數(shù)少的初始化器可以直接調(diào)用主初始化器碉渡。

????? self = [super init];

????? if(self){

????? _name = [name copy]; //在初始化器中使用實例變量而不要使用實例屬性。

????? _pages = pages;

????? _category = [category copy];

????? }

????? return self:

}

初始化對象實例時惫霸,init通常和alloc搭配使用寂汇。

Book *b1 = [[Book alloc]init]; //alloc是一個從NSObject繼承過來的類方法西采。Tips: 按住commond健再點擊關(guān)鍵詞可以查看其類庫罐呼。

Book *b1 = [[Book alloc]init]; 也可以拆分為:

Book *b1 = [Book alloc]鞠柄;

b1 =[b1 init]; //這里等號左邊的b1是不可以省略的,因為[b1 init]有一個返回值嫉柴,是返回一個地址厌杜,OC在這里返回的地址有可能和上一行Book *b1 = [Book alloc];其中的b1地址不一樣计螺。

alloc所做的事情--NSObject已實現(xiàn):1夯尽、在對上分配合適大小的內(nèi)存。 2登馒、將屬性或者實例變量的內(nèi)存置0匙握。

init所做的事情--可以自定義:1、調(diào)用父類初始化器[super init](前置調(diào)用)陈轿。 2圈纺、初始化當(dāng)前對象實例變量。

Book *b1= [Book new]; //new相當(dāng)于調(diào)用 alloc/init的無參數(shù)版本,不能傳遞參數(shù)麦射。

類初始化器

類型初始化器:+(void)initialize 只能有一個蛾娶,負責(zé)類型級別初始化,初始化類里面的靜態(tài)變量法褥。

initialize在每個類使用之前被系統(tǒng)自動調(diào)用茫叭,且每個進程周期中只被調(diào)用一次。

子類的initalize會自動調(diào)用父類的initialize(前置調(diào)用)半等。

+(void)initialize{

????? if(self ==[Book class]){ //判斷該類是否是Book類

??????????? NSLog(@"Book Class initialize");

????? }

}

對象析構(gòu)器

對象析構(gòu)器 -(void)dealloc 只能有一個揍愁,用于釋放對象(沒有類型析構(gòu)器)擁有的動態(tài)資源,無返回值杀饵。

-(void)dealloc{

自動調(diào)用:1.ARC將對象屬性引用計數(shù)減持(-1)

手動實現(xiàn):2.釋放不受ARC管理的動態(tài)內(nèi)存莽囤,如malloc分配的內(nèi)存,關(guān)閉非內(nèi)存資源切距,如文件句柄朽缎、網(wǎng)絡(luò)端口

自動調(diào)用:3.父類dealloc

}

dealloc由ARC根據(jù)對象引用計數(shù)規(guī)則,在釋放對象內(nèi)存前自動調(diào)用谜悟,無法手工調(diào)用话肖。

子類的dealloc會自動調(diào)用父類的dealloc(后置調(diào)用)。


第六天視頻課程:


認識面向?qū)ο?/strong>

封裝 encapsulation:隱藏對象內(nèi)部實現(xiàn)細節(jié)葡幸,對外部僅提供公共接口訪問最筒。

繼承 inheritance:一個類型在另外類型基礎(chǔ)上進行的擴展實現(xiàn)。每一個類只能有一個基類蔚叨,子類自動繼承基類的:實例變量床蜘、屬性辙培、實例方法、類方法邢锯。NSObject類是所有類的根類扬蕊,所有類向上追溯最上面的類都是NSObject類。繼承有兩層含義:1丹擎、成員復(fù)用尾抑,子類復(fù)用基類的成員。所有的成員都會被繼承蒂培,就算是私有成員也被繼承蛮穿,只是成員訪問不到。2毁渗、類型抽象践磅,將子類當(dāng)作父類來使用。

例子:

建立一個類Shape

@interface Shape : NSObject{ //Shape類繼承于NSObject Tips:按住option鍵點擊關(guān)鍵字可以看到相關(guān)的參考文檔灸异。

????? @public int _data; //定義了一個公開的實例變量

}

????? @property int no;

????? -(void)draw;

????? +(void)process;

@end

建立一個Shape的子類Circle

@interface Circle:Shape //Circle類繼承了Shape類

@property int radius; //Circle類自己的實例屬性

@end

由于Circle繼承了Shape類府适,所以Shape類的實例變量、屬性肺樟、實例方法檐春、類方法Circle類都可以使用。

Circle* circle=[[Circle alloc]init];

circle.no=200;

circle->_data++; //在訪問父類實例變量時用->來訪問

[circle draw];

[Circle process]; //Circle類也可以調(diào)用父類的類方法么伯。


Circle類繼承Shape類的內(nèi)存模型


第七天視頻課程:


多態(tài) polymorphism:不同類型針對同一行為接口的不同實現(xiàn)方式疟暖。

對比重寫(override)與重載:子類重寫父類同名同參數(shù)方法,子類只可以重寫父類方法田柔。方法名相同俐巴、參數(shù)不同,OC不支持方法的重載(重載指的是方法名相同硬爆,參數(shù)不同欣舵。用不同的參數(shù)傳遞給相同名字的方法,達到不同的運行效果)缀磕。

在子類的代碼中缘圈,可以使用super類調(diào)用基類的實現(xiàn),self具有多態(tài)性袜蚕,可以指向不同子類糟把,super沒有多態(tài)性,僅指向當(dāng)前父類牲剃。

例子:

建立一個Shape的子類Rectangle

@interface Rectangle:Shape

@property int width;

@property int length;

@end

基類Shape中有一個實例方法move:

-(void)move{

????? NSLog(@"Shape object move");

????? [self draw];

}

針對Rectangle類增加了兩個屬性(width和length)重寫(override)繼承過來的方法

@implementation Rectangle

-(id)init{

????? self = [super init];? //重寫時子類初始化器中必須首先調(diào)用基類的初始化器

????? if(self){

??????????? _length = 10;

??????????? _width = 20;

????? }

????? return self;

}

-(void)draw{

????? NSLog(@"Rectangle object draw: length=%d, width=%d", self.length, self.width);

}

-(void)print{

????? NSLog(@"Rectangle Instance variable %d", _data);

}

+(void)process{

????? NSLog(@"Rectangle class process");

}

-(void)dealloc{

?????? NSLog(@"Rectangle dealloc");

}

當(dāng)實例對象調(diào)用時遣疯,Rectangle實例將調(diào)用重寫的方法。Rectangle實例調(diào)用-(void)move時將調(diào)用父類Shape類的實例方法-(void)move颠黎,此方法中調(diào)用的draw方法[self draw]另锋,此時self有多態(tài)性狭归,將調(diào)用Rectangle實例中的draw方法。

對于父類中的屬性也可以在子類中重寫室梅。

父類Shape中的屬性:@property int no;

在子類Rectangle中重寫:

-(int)no{

????? return super.no;? //super表示調(diào)用父類的方法

}

-(int)setNo:(int)no{

????? super.no = no;

}

屬性的重寫本質(zhì)上就是getter和setter兩個訪問器的重寫亡鼠。

繼承中的init和dealloc

初始化器 init:子類自動繼承基類的初始化器,子類也可以重寫初始化器敷待,重寫時子類初始化器中必須首先調(diào)用基類的初始化器(手工調(diào)用)再添加其他內(nèi)容榜揖。

析構(gòu)器 dealloc:子類可以選擇繼續(xù)繼承基類析構(gòu)器,或者重寫基類析構(gòu)器举哟,子類析構(gòu)器執(zhí)行完畢后思劳,會自動調(diào)用基類析構(gòu)器(后置調(diào)用,且不支持手工調(diào)用)妨猩。子類析構(gòu)器自動具有多態(tài)性潜叛。

Tips:盡量避免在父類init和dealloc中調(diào)用子類重寫的方法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末威兜,一起剝皮案震驚了整個濱河市牡属,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扼睬,老刑警劉巖逮栅,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異窗宇,居然都是意外死亡,警方通過查閱死者的電腦和手機军俊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門侥加,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人粪躬,你說我怎么就攤上這事担败∥粞ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵提前,是天一觀的道長吗货。 經(jīng)常有香客問我,道長狈网,這世上最難降的妖魔是什么宙搬? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮拓哺,結(jié)果婚禮上勇垛,老公的妹妹穿的比我還像新娘闲孤。我一直安慰自己,他們只是感情好烤礁,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布玻侥。 她就那樣靜靜地躺著决摧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪煌茬。 梳的紋絲不亂的頭發(fā)上改衩,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天妖异,我揣著相機與錄音,去河邊找鬼烫映。 笑死李请,一個胖子當(dāng)著我的面吹牛瞧筛,可吹牛的內(nèi)容都是我干的厉熟。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼较幌,長吁一口氣:“原來是場噩夢啊……” “哼揍瑟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起乍炉,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤绢片,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后岛琼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體底循,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年槐瑞,在試婚紗的時候發(fā)現(xiàn)自己被綠了熙涤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡困檩,死狀恐怖祠挫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情悼沿,我是刑警寧澤等舔,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站糟趾,受9級特大地震影響软瞎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拉讯,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一涤浇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魔慷,春花似錦只锭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至邀摆,卻和暖如春纵顾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背栋盹。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工施逾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓汉额,卻偏偏與公主長得像曹仗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蠕搜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

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