OC-基礎(chǔ)總結(jié)(一)

OC基礎(chǔ)總結(jié)

重新回過頭看這些基礎(chǔ)知識(shí),對(duì)許多知識(shí)點(diǎn)都有新的認(rèn)識(shí),擁有堅(jiān)實(shí)的基礎(chǔ)才能更快的成長(zhǎng)。

#improt

OC程序的源文件的后綴名是.m m代表message表示消息機(jī)制。main 仍然是OC程序的入口和出口,main函數(shù)有一個(gè)int類型的返回值,代表程序的結(jié)束狀態(tài)。

#import預(yù)處理指令,是#inlcude指令的增強(qiáng)版,作用是將文件的內(nèi)容在預(yù)編譯的時(shí)候拷貝到寫指令的地方。 #import做了優(yōu)化,同一個(gè)文件無論#import多少次,都只會(huì)包含一次。
簡(jiǎn)要原理:#import指令在包含文件的時(shí)候,底層會(huì)先判斷這個(gè)文件是否被包含,如果包含過就會(huì)略過。

因此#import #include主要區(qū)別在于使用#include需要處理重復(fù)引用,而#import能防止同一個(gè)文件被多次包含,不需要處理重復(fù)引用。

框架

  1. 一個(gè)功能集蘋果或者第三方事先將一個(gè)協(xié)成員在開發(fā)程序的時(shí)候經(jīng)常要用到的功能事先寫好。把這些功能封裝在一個(gè)類或者函數(shù)中,這些函數(shù)和類的集合就叫做框架。
  2. Foundation框架
    Foundation:基礎(chǔ)框架,這個(gè)框架中提供了一些最基礎(chǔ)的功能,輸入和輸出,一些數(shù)據(jù)類型。

如何使用面向?qū)ο髞碓O(shè)計(jì)程序

面向?qū)ο蠛笃诰S護(hù)和修改十分方便。當(dāng)我們遇到一個(gè)需求的時(shí)候,不要親自去實(shí)現(xiàn)。

  1. 先看看有沒有現(xiàn)成的人是專門做這件事情的,框架,如果有直接使用。
  2. 如果沒有就自己造一個(gè)擁有這樣功能的對(duì)象,并且創(chuàng)造出來的這個(gè)對(duì)象可以多次被使用。

類和對(duì)象

  1. 對(duì)象 - 具體
    對(duì)象是現(xiàn)實(shí)生活中一個(gè)具體存在,看得見,摸得著,拿過來就可以直接使用
  2. 類 - 統(tǒng)稱
    物以類聚,人以群分。
    類時(shí)對(duì)一群具有相同特征或者行為的事物的一個(gè)統(tǒng)稱,抽象的,不能直接使用,如果非要使用類的話,只能去類中找到類的具體存在,也就是對(duì)象,然后使用。

類和對(duì)象的關(guān)系

類是模板,類的對(duì)象是根據(jù)這個(gè)模板創(chuàng)建出來的,類模板中有什么,對(duì)象中就有什么,絕不可能多,也絕不可能少。

如何設(shè)計(jì)一個(gè)類

設(shè)計(jì)類的三要素

  1. 類的名字。
  2. 這類事物具有的相同的特征,這類事物用手什么。
  3. 這類事物的能干什么。

類加載

  1. 在創(chuàng)建對(duì)象的時(shí)候,肯定是需要訪問類的。
  2. 聲明一個(gè)類的指針變量也會(huì)訪問類的。

在程序運(yùn)行期間,當(dāng)某個(gè)類第一次被訪問到的時(shí)候,會(huì)將這個(gè)類存儲(chǔ)到內(nèi)存中的代碼段區(qū)域,這個(gè)過程叫做類加載。

只有類在第一次被訪問的時(shí)候,才會(huì)做類加載,并且一旦類被加載到代碼段以后,直到程序結(jié)束的時(shí)候才會(huì)被釋放。

對(duì)象在內(nèi)存中究竟是如何存儲(chǔ)的。

例:Person *p1 = [Person new];

  1. Person *p1; 會(huì)在棧內(nèi)存中申請(qǐng)一塊空間,在棧內(nèi)存中聲明1個(gè)Person類型的指針變量p1。p1是一個(gè)指針變量,那么只能存儲(chǔ)地址。
  2. [person new];真正在內(nèi)存中創(chuàng)建對(duì)象的其實(shí)是這句代碼。
  3. new方法在堆內(nèi)存中創(chuàng)建一塊合適大小的空間,然后在空間中根據(jù)類的模板創(chuàng)建對(duì)象。
    類模板中定義了什么屬性,就把這些屬性依次聲明在對(duì)象之中。
    對(duì)象中還有另外一個(gè)屬性,叫做isa ,是一個(gè)指針,指向?qū)ο笏鶎俚念愒诖a段中的地址。
  4. 初始化對(duì)象的屬性,給對(duì)象的屬性賦默認(rèn)值。
    如果屬性的類型是基本數(shù)據(jù)類型,那么就賦值為0
    如果屬性的類型是c語言的指針類型,那么就賦值為NULL
    如果屬性的類型為OC語言的類指針類型,那么就賦值為nil
  5. 注意
    1). 對(duì)象中只有屬性沒有方法,屬性包括自己類的屬性,外加一個(gè)isa指針指向代碼段中的類。
    2). 如何訪問對(duì)象的屬性,指針名->屬性名
    根據(jù)指針,找到指針指向的對(duì)象,在找到對(duì)象中的屬性來訪問。
    3). 如何調(diào)用方法。[指針名 方法名];
    先根據(jù)指針名找到對(duì)象,對(duì)象發(fā)現(xiàn)要調(diào)用方法,在根據(jù)對(duì)象的isa指針找到類。然后調(diào)用類里的方法。
    4). 為什么不把方法存儲(chǔ)到對(duì)象之中。
    因?yàn)槊恳粋€(gè)對(duì)象的方法的代碼實(shí)現(xiàn)都是一模一樣的,沒有必要為每一個(gè)對(duì)象都保存一個(gè)方法,這樣的話就太浪費(fèi)空間了,既然都一樣,那么就只保存一份在代碼段中。
    5). 對(duì)象屬性是有默認(rèn)值的。

nil與NULL的區(qū)別

NULL 可以作為指針變量的值,如果一個(gè)指針變量的值是NULL值代表這個(gè)指針不指向內(nèi)存中的任何一塊空間,其實(shí)等價(jià)于0。NULL其實(shí)是一個(gè)宏,就是0。

nil 只能作為指針變量的值,代表這個(gè)指針變量不指向內(nèi)存中任何空間。nil其實(shí)也等價(jià)于0,也是一個(gè)宏,就是0。

所以NULL和nil其實(shí)是一樣的,雖然使用NULL的地方可以使用nil,但是不建議隨意使用。C指針用NULL OC的類指針用nil。

Person *p1 = nil;表示p1指針不指向任何對(duì)象。
如果一個(gè)指針的值為nil代表這個(gè)指針不指向任何對(duì)象,此時(shí)如果通過p1指針去訪問p1指針指向的對(duì)象的屬性,運(yùn)行就會(huì)報(bào)錯(cuò)。如果通過p1指針去調(diào)用對(duì)象的方法,運(yùn)行不會(huì)報(bào)錯(cuò),但是方法不會(huì)執(zhí)行。

多個(gè)指針指向同一個(gè)對(duì)象

同類型的指針變量之間是可以相互賦值的。p1,p2指向同一個(gè)對(duì)象,無論誰修改對(duì)象的屬性都會(huì)修改。因?yàn)樗麄冎赶蛲粔K內(nèi)存空間。

對(duì)象和方法

對(duì)象可以作為方法的參數(shù)也可以作為方法的返回值。
類的本質(zhì)是我們自定義的一種數(shù)據(jù)類型,并且對(duì)象在內(nèi)存中的大小是由我們自己決定的,數(shù)據(jù)類型是在內(nèi)存中開辟空間的一個(gè)模板

當(dāng)對(duì)象作為方法的參數(shù)傳遞的時(shí)候,是地址傳遞。所以,在方法內(nèi)部通過形參去修改形參指向的對(duì)象的時(shí)候,會(huì)影響實(shí)參變量指向的對(duì)象的值。對(duì)象作為方法的返回值,返回的是對(duì)象的地址

對(duì)象作為類的屬性。

屬性的本質(zhì)是變量,在創(chuàng)建對(duì)象的時(shí)候,對(duì)象當(dāng)中的屬性是按照類模板中的規(guī)定逐個(gè)創(chuàng)建出來的。類模板中屬性是什么類型,那么對(duì)象中的屬性就是什么類型。
如果對(duì)象的屬性是另外一個(gè)類的對(duì)象,這個(gè)屬性僅僅是一個(gè)指針變量而已,并沒有對(duì)象產(chǎn)生。這個(gè)時(shí)候還要為這個(gè)屬性賦值一個(gè)對(duì)象的地址,才可以正常使用。
類模板中屬性是什么類型,對(duì)象當(dāng)中的屬性就是什么類型。

類方法的聲明和調(diào)用

類方法的調(diào)用不依賴對(duì)象,如果要調(diào)用類方法不需要去創(chuàng)建對(duì)象。而是直接使用類名就可以調(diào)用類方法。

類方法和對(duì)象方法的調(diào)用過程。

類方法和對(duì)象方法的調(diào)用過程

類方法節(jié)約空間且效率高,因?yàn)檎{(diào)用類方法不需要?jiǎng)?chuàng)建對(duì)象。但是在類方法中不能直接訪問屬性。因?yàn)閷傩灾挥性趯?duì)象創(chuàng)建的時(shí)候才會(huì)創(chuàng)建在對(duì)象之中,而類方法在執(zhí)行的時(shí)候有可能還沒有類對(duì)象,所以不能訪問屬性。但是我們可以在類方法中創(chuàng)建類對(duì)象。

同理,在類方法中也不能通過self直接調(diào)用當(dāng)前類的其他的對(duì)象方法,因?yàn)閷?duì)象方法只能通過對(duì)象來調(diào)用,在對(duì)象方法中可以直接調(diào)用類方法。

因此如果方法不需要直接訪問屬性,也不需要直接調(diào)用其他的對(duì)象方法,那么我們就可以直接將這個(gè)方法定義為類方法。

繼承

  1. 子類從父類繼承,就意味著子類擁有了父類的所有成員,包括屬性和方法。
  2. 繼承是類在繼承,而不是對(duì)象在繼承,子類對(duì)象中擁有父類對(duì)象中的同樣的成員。

如果不是所有的子類都擁有的方法,那么這個(gè)方法就不應(yīng)該定義在父類之中,因?yàn)橐坏┒x在父類之中,那么所有的子類都擁有該方法

繼承的特點(diǎn)

  1. 一個(gè)類只能有一個(gè)父類,不能有多個(gè)父類。
  2. 傳遞性,A繼承B,B繼承C 那么A就同時(shí)擁有B和C的成員。

NSObject

NSObject類是所有類的父類,NSObject類中包含了創(chuàng)建對(duì)象的方法,所以我們自己創(chuàng)建的類必須直接或者間接的繼承自NSObject。
NSObject中有一個(gè)isa指針的屬性,所以每一個(gè)子類對(duì)象中都有一個(gè)叫做isa的指針。

Super關(guān)鍵字

  1. 子類中已經(jīng)有父類的屬性,相當(dāng)于子類中已經(jīng)定義過父類的屬性,因此子類當(dāng)中不能存在和父類同名的屬性,否則會(huì)出現(xiàn)沖突。
  2. 可以使用super關(guān)鍵字調(diào)用當(dāng)前對(duì)象從父類繼承過來的對(duì)象方法。可以使用self 也可以使用 super
  3. 類方法也可以被子類繼承。子類可以直接調(diào)用父類的類方法。
  4. super只能用來調(diào)用父類的對(duì)象方法或者類方法,不能用來訪問屬性。
  5. 子類從父類繼承,相當(dāng)于子類模板中擁有了父類模板中的所有成員。
  6. 創(chuàng)建一個(gè)子類對(duì)象,仍然是根據(jù)子類模板來創(chuàng)建對(duì)象,只不過子類模板中擁有父類的屬性和方法,也有子類自己的屬性和方法。
  7. 父類的方法用super 可讀性更高,我們很快就能知道這個(gè)方法是父類方法。

訪問修飾符:

用來修飾屬性,可以限定對(duì)象的屬性在那一段范圍之中訪問。

@private : 私有,被其修飾的屬性只能在本類的內(nèi)部訪問。
@protected: 受保護(hù)的 被其修飾的屬性只能在本類以及本類的子類中訪問。只能在本類和子類的方法實(shí)現(xiàn)中訪問。
@package: 被其修飾的屬性,可以在當(dāng)前框架中訪問。
@public: 公共的,被其修飾的屬性可以在任意地方訪問。

如果不為屬性指定訪問修飾符 默認(rèn):protected
子類仍然可以繼承父類的私有屬性。就算父類的屬性是private,只不過在子類當(dāng)中無法直接訪問從父類繼承過來的私有屬性,可以通過set get方法來訪問。

訪問修飾符的作用域
從寫訪問修飾符的地方開始往下,直到遇到另外一個(gè)訪問修飾符的或者結(jié)束大括弧為止,中間的所有的屬性都應(yīng)用這個(gè)訪問修飾符。

使用建議
@public 無論什么情況下都不要使用,屬性不要直接暴漏給外界。
@private 如果屬性只想在本類中使用,不想再子類中使用。
@protected 如果你希望屬性只在本類和本類的子類中使用。

訪問修飾符只能用來修飾屬性,不能用來修飾方法。

里氏替換原則

子類可以替換父類的位置,并且程序的功能不受影響。
即一個(gè)父類指針指向一個(gè)子類對(duì)象,可正常調(diào)用子類的方法和屬性。

LSP 里氏替換原則:
一個(gè)指針中不僅可以存儲(chǔ)本類對(duì)象的地址,還可以存儲(chǔ)子類對(duì)象的地址
如果一個(gè)指針的類型是NSObject類型的,那么這個(gè)指針中可以存儲(chǔ)任意的OC對(duì)象的地址。
如果一個(gè)數(shù)組的元素的類型是一個(gè)OC指針類型的,那么這個(gè)數(shù)組中不僅可以存儲(chǔ)本類對(duì)象還可以存儲(chǔ)子類對(duì)象。
如果一個(gè)數(shù)組元素是NSObject指針類型,那就意味著任意類型的對(duì)象都可以存在數(shù)組中。
如果一個(gè)方法的參數(shù)是一個(gè)對(duì)象,我們可以傳本類對(duì)象也可以傳子類對(duì)象
當(dāng)一個(gè)父類指針指向1個(gè)子類對(duì)象的時(shí)候,通過父類指針就只能去調(diào)用子類對(duì)象中的父類成員。

方法重寫

當(dāng)子類擁有父類的行為,但是子類的行為與父類不同。這個(gè)時(shí)候就可以通過重寫父類的方法來實(shí)現(xiàn)。

當(dāng)一個(gè)父類指針指向一個(gè)子類對(duì)象的時(shí)候,通過這個(gè)父類指針調(diào)用的方法,如果子類對(duì)象中重寫了這個(gè)方法,調(diào)用的就是子類重寫的方法。

多態(tài)

指的是同一個(gè)行為,對(duì)于不同的事物具有完全不同的表現(xiàn)形式。同一個(gè)行為具備多種形態(tài)。子類重寫父類的方法就是多態(tài)。

description 方法

description方法是定義在NSObject之中的。我們通過重寫description方法來修改NSLog的輸出形式。NSLog的底層就是description方法。

結(jié)構(gòu)體與類的異同點(diǎn)

相同點(diǎn):
都可以將多個(gè)數(shù)據(jù)封裝為一個(gè)數(shù)據(jù)

不同點(diǎn):

  1. 結(jié)構(gòu)體只能封裝數(shù)據(jù),而類不僅可以封裝數(shù)據(jù)還可以封裝行為。
  2. 結(jié)構(gòu)體變量分配在棧空間 (局部)
  3. 對(duì)象變量分配在堆空間
  4. 棧的特點(diǎn):空間相對(duì)較小,但是存儲(chǔ)在棧中的數(shù)據(jù)訪問的效率更高一些
  5. 堆的特點(diǎn):空間相對(duì)較大,但數(shù)據(jù)訪問的效率相對(duì)要低。

如果表示的實(shí)體沒有行為,只有屬性。
那么如果屬性比較少,只有幾個(gè),那么這個(gè)時(shí)候就定義為結(jié)構(gòu)體,分配在棧,提高效率。如果屬性比較多,不要定義成結(jié)構(gòu)體,因?yàn)檫@樣結(jié)構(gòu)體變量會(huì)在棧中占據(jù)比較大的空間,導(dǎo)致訪問效率降低。

類的本質(zhì)

類是以Class對(duì)象存儲(chǔ)在代碼段中的

內(nèi)存中的五大區(qū)域
棧 存儲(chǔ)局部變量
堆 允許程序員自己申請(qǐng)的空間,需要程序員自己控制
BSS段 存儲(chǔ)沒有初始化的全局變量和靜態(tài)變量
數(shù)據(jù)段 用來存儲(chǔ)已經(jīng)初始化的全局變量,靜態(tài)變量還有常量
代碼段 用來存儲(chǔ)程序的代碼。

類加載:當(dāng)類第一次被訪問的時(shí)候,這個(gè)類就會(huì)被加載到代碼段存儲(chǔ)起來。

  1. 類什么時(shí)候加載到代碼段
    類第一次被訪問的時(shí)候,類就會(huì)被加載到代碼段存儲(chǔ),即類加載時(shí)。

  2. 類以什么樣的形式存儲(chǔ)在代碼段。
    任何存儲(chǔ)在內(nèi)存中的數(shù)據(jù)都有一個(gè)數(shù)據(jù)類型,任何在內(nèi)存中申請(qǐng)的空間也有自己的類型。那么在代碼段存儲(chǔ)類的那塊空間是什么類型的?
    在代碼段中存儲(chǔ)類的步驟
    1). 先在代碼段中創(chuàng)建一個(gè)Class對(duì)象,Class是Foundation框架中的一個(gè)類,這個(gè)Class對(duì)象就是用來存儲(chǔ)類的信息的。
    2). 將類的信息存儲(chǔ)在這個(gè)Class對(duì)象中
    所以類是以Class對(duì)象的形式存儲(chǔ)在代碼段的,存儲(chǔ)類的這個(gè)Class對(duì)象也叫作類對(duì)象,所以存儲(chǔ)類的類對(duì)象也有一個(gè)isa指針,指向存儲(chǔ)父類對(duì)象。

  3. 類一旦被加載到代碼段之后,什么時(shí)候會(huì)被釋放。
    類一旦被加載到代碼段之后是不會(huì)被回收的,除非程序結(jié)束。

  4. 如何拿到存儲(chǔ)在代碼段中的類對(duì)象?
    1). 調(diào)用類的類方法class就可以得到存儲(chǔ)類的類對(duì)象的地址。
    2). 調(diào)用對(duì)象的對(duì)象方法 class就可以得到存儲(chǔ)這個(gè)對(duì)象所屬的類的class對(duì)象的地址。
    3). 對(duì)象中的isa指針的值其實(shí)就是代碼段中存儲(chǔ)類的類對(duì)象的地址。
    4). 拿到存儲(chǔ)類的類對(duì)象以后,完全等價(jià)于類
    Class c1 = [Person class];c1對(duì)象就是Person類,c1完全等價(jià)于Person,可以使用類對(duì)象來調(diào)用類的類方法。
    注意:聲明Class指針的時(shí)候,不需要加*因?yàn)樵趖ypedef的時(shí)候已經(jīng)加了*

  5. 如何使用類對(duì)象
    1). 拿到存儲(chǔ)類的類對(duì)象以后, Class c1 = [Person class]; c1對(duì)象就是Person類,c1對(duì)象完全等價(jià)于Person
    2). 使用類對(duì)象來調(diào)用類的類方法。
    3). 可以使用類對(duì)象來調(diào)用new方法,創(chuàng)建存儲(chǔ)在類對(duì)象中的類的對(duì)象。
    4). 使用類對(duì)象,只能調(diào)用類的類方法,因?yàn)轭悓?duì)象就等價(jià)于存在其中的類

  6. 總結(jié)
    1). 類是以Class對(duì)象的形式存儲(chǔ)在代碼段之中的。
    2). 可以使用類對(duì)象來調(diào)用類的類方法。
    3). 通過class方法拿到存儲(chǔ)類的類對(duì)象。

SEL選擇器

SEL其實(shí)是一個(gè)類,要在內(nèi)存中申請(qǐng)空間存儲(chǔ)數(shù)據(jù),SEL對(duì)象是用來存儲(chǔ)一個(gè)方法的。
類是以Class對(duì)象的形式存儲(chǔ)在代碼段之中。那么如何將方法存儲(chǔ)在類對(duì)象之中?

  1. 先創(chuàng)建一個(gè)SEL對(duì)象
  2. 將方法的信息存儲(chǔ)在這個(gè)SEL對(duì)象之中
  3. SEL對(duì)象作為Class對(duì)象的一個(gè)屬性來存儲(chǔ)。
  4. 類似一個(gè)數(shù)組的形式將所有的SEL對(duì)象存儲(chǔ),即方法列表。SEL對(duì)象中存儲(chǔ)方法的信息。

如何拿到存儲(chǔ)方法的SEL對(duì)象

  1. 因?yàn)镾EL是一個(gè)typedef類型的,在自定義的時(shí)候已經(jīng)加了*所以我們聲明SEL指針的時(shí)候不需要加*
  2. 取到存儲(chǔ)方法的SEL對(duì)象 SEL sel = @selector(sayHi);
  3. 調(diào)用方法的本質(zhì):[p1 sayHi];
    1). 先拿到存儲(chǔ)sayHi方法的SEL對(duì)象,也就是拿到存儲(chǔ)sayHi方法的SEL數(shù)據(jù),SEL消息。
    2). 將SEL消息發(fā)送給p1對(duì)象。
    3). p1對(duì)象接收到SEL消息以后,就知道要調(diào)用方法
    4). 根據(jù)對(duì)象的isa指針找到存儲(chǔ)類的類對(duì)象。
    5). 找到這個(gè)類對(duì)象以后,在這個(gè)類對(duì)象中去搜尋是否有和傳入的SEL數(shù)據(jù)相匹配的方法。如果有就執(zhí)行,如果沒有再找父類,直到NSObject。

OC最重要的1個(gè)機(jī)制:消息機(jī)制,調(diào)用方法的本質(zhì)其實(shí)就是為對(duì)象發(fā)送SEL消息,[p1 sayHi];表示為p1對(duì)象發(fā)送1條sayHi消息。

手動(dòng)的為對(duì)象發(fā)送SEL消息

  1. 先得到方法的SEL數(shù)據(jù)。
  2. 將這個(gè)SEL消息發(fā)送給p1對(duì)象。
    通過方法- (id)performSelector:(SEL)aSelector;手動(dòng)發(fā)送消息
    Person *p1 = [Person new];
    SEL s1 = @selector(sayHi);
    [p1 performSelector:s1]; 與 [p1 sayHi]效果是完全一樣的.
// 帶一個(gè)參數(shù)和兩個(gè)參數(shù)的方法
// 如果有多個(gè)參數(shù)可以把參數(shù)封裝在一個(gè)對(duì)象里面,傳遞對(duì)象
 - (id)performSelector:(SEL)aSelector withObject:(id)object;
 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

點(diǎn)語法

使用點(diǎn)語法訪問對(duì)象的屬性。

語法:對(duì)象名.去掉下劃線的屬性名
p.name = @“jack”;
這個(gè)時(shí)候就會(huì)將@“jack”賦值給p對(duì)象的_name屬性。

原理:
本質(zhì)并不是把@"jack"直接賦值給p對(duì)象的_name屬性,實(shí)質(zhì)上是調(diào)用set方法。

當(dāng)使用點(diǎn)語法賦值的時(shí)候,編譯器會(huì)將點(diǎn)語法轉(zhuǎn)換為調(diào)用setter方法的代碼。
當(dāng)使用點(diǎn)語法取值的時(shí)候,編譯器會(huì)將點(diǎn)語法轉(zhuǎn)換為調(diào)用getter方法的代碼。

在getter setter方法中慎用點(diǎn)語法,可能會(huì)造成無限遞歸而程序崩潰。
主要是看情況,get方法中如果點(diǎn)語法是調(diào)用set方法是可以使用的。
例如懶加載中我們是可以使用點(diǎn)語法為賦值的,因?yàn)閼屑虞d是get方法,而賦值是調(diào)用set方法,所部不會(huì)遞歸調(diào)用。
如果屬性沒有封裝setter getter 是無法使用點(diǎn)語法的。

@property

@property 自動(dòng)生成getter setter 方法的聲明。
原理:由編譯器在編譯的時(shí)候自動(dòng)生成。

@synthesize
自動(dòng)生成getter setter 方法的實(shí)現(xiàn)。
@synthesize age // age一定要是前面@property聲明過的。

  1. 生成一個(gè)真私有屬性,屬性的類型和@synthesize對(duì)應(yīng)的@property類型一致,屬性的名字和@synthesize對(duì)應(yīng)的@property名字一致。
  2. 自動(dòng)生成setter方法的實(shí)現(xiàn)。實(shí)現(xiàn)的方式,將參數(shù)直接賦值給自動(dòng)生成的那個(gè)私有屬性。 self->age = age;
  3. 自動(dòng)生成getter方法的實(shí)現(xiàn)。將生成的私有屬性的值返回

希望@synthesize 不要生成私有屬性,setter getter 的實(shí)現(xiàn)中操作我們已經(jīng)寫好的屬性就可以了。

@synthesize @property名稱 = 已經(jīng)存在的屬性名;
@synthesize age = _age;
  1. 不會(huì)再去生成私有屬性
  2. 直接生成setter getter的實(shí)現(xiàn) setter的實(shí)現(xiàn):把參數(shù)的值直接賦值給指定的屬性。getter實(shí)現(xiàn):直接返回指定的屬性的值。

@property增強(qiáng)。

Xcode 4.4之后,只要寫一個(gè)@property 編譯器會(huì)自動(dòng)生成私有屬性,并且自動(dòng)生成getter setter 聲明和實(shí)現(xiàn)。

@property NSString *name;

  1. 自動(dòng)的生成一個(gè)私有屬性,屬性的類型和@property類型一致,屬性的名稱和@property的名稱一致,屬性的名稱自動(dòng)的加下劃線。
  2. 自動(dòng)生成這個(gè)屬性的 setter getter方法的聲明和實(shí)現(xiàn)。直接將參數(shù)的值賦值給自動(dòng)生成的私有屬性,直接返回生成的私有屬性的值。

@property生成set get方法和成員屬性,但是如果同時(shí)重寫了setter getter方法,那么就不會(huì)自動(dòng)生成私有屬性了。需要自己寫。
父類的property一樣可以被子類繼承,但是生成的屬性是私有的,可以通過setter getter方法來訪問

動(dòng)態(tài)類型和靜態(tài)類型

OC是一門弱語言,編譯器在編譯的時(shí)候,語法檢查的時(shí)候沒有那么嚴(yán)格。
強(qiáng)類型的語言:編譯器在編譯的時(shí)候,做語法檢查的時(shí)候,就非常嚴(yán)格,行就是行,不行就是不行。

靜態(tài)類型
指的是一個(gè)指針指向的對(duì)象是一個(gè)本類對(duì)象。
動(dòng)態(tài)類型
一個(gè)指針指向的對(duì)象不是本類對(duì)象。

編譯檢查

編譯器在編譯的時(shí)候,檢查能否通過一個(gè)指針去調(diào)用指針指向的對(duì)象的方法。

判斷原則:看指針?biāo)鶎俚念愋椭杏袥]有這個(gè)方法,如果有就認(rèn)為可以調(diào)用,編譯通過,如果這個(gè)類中沒有,那么編譯報(bào)錯(cuò)。這就叫做編譯檢查,在編譯的時(shí)候,能不能調(diào)用對(duì)象的方法主要是看指針的類型,我們可以將指針的類型做轉(zhuǎn)換,來達(dá)到騙過編譯器的目的。

運(yùn)行檢查

編譯檢查只是騙過了編譯器,但是這個(gè)方法究竟能不能執(zhí)行,所以在運(yùn)行的時(shí)候運(yùn)行檢查會(huì)去檢查對(duì)象中是否真的有這個(gè)方法,如果有就執(zhí)行,如果沒有就報(bào)錯(cuò)

編譯器,用編譯器將C代碼OC代碼轉(zhuǎn)化成二進(jìn)制,編譯器是個(gè)軟件,蘋果自己寫的叫做LLVM,可以編譯C OC Swift語言。

我們可以通過以下方法先來先判斷以下對(duì)象中是否有這個(gè)方法,如果有再去執(zhí)行,如果沒有就別去執(zhí)行,避免程序在沒有方法的時(shí)候報(bào)錯(cuò)。

 1). 判斷對(duì)象中是否有這個(gè)方法可以執(zhí)行.
     - (BOOL)respondsToSelector:(SEL)aSelector; (最常用)     
 2). 判斷類中是否有指定的類方法.
     + (BOOL)instancesRespondToSelector:(SEL)aSelector;
 3). 判斷指定的對(duì)象是否為 指定類的對(duì)象或者子類對(duì)象.
     - (BOOL)isKindOfClass:(Class)aClass;
 4). 判斷對(duì)象是否為指定類的對(duì)象 不包括子類.
     - (BOOL)isMemberOfClass:(Class)aClass;
 5). 判斷類是否為另外1個(gè)類的子類.
    + (BOOL)isSubclassOfClass:(Class)aClass;

NSObject

OC中所有類的基類,根據(jù)LSP NSObject指針就可以指向任意的OC對(duì)象,所有NSObject指針是一個(gè)萬能指針,可以指向任意的OC對(duì)象
缺點(diǎn):如果要調(diào)用指向的子類對(duì)象的獨(dú)有的方法,就必須要做類型轉(zhuǎn)換。

id指針

是一個(gè)萬能指針,可以指向任意的OC對(duì)象

  1. id是一個(gè)typedef自定義類型
  2. id指針,是1個(gè)萬能指針,可以指向任意的OC對(duì)象。
    1). id是1個(gè)typedef自定義類型,在定義的時(shí)候已經(jīng)加了*所以,聲明id指針的時(shí)候不需要再加*了。
    2). id指針是1個(gè)萬能指針,任意的OC對(duì)象都可以指.
  3. NSObject和id的異同.
    相同點(diǎn): 萬能指針,都可以執(zhí)行任意的OC對(duì)象。
    不同點(diǎn): 通過NSObject指針去調(diào)用對(duì)象的方法的時(shí)候,編譯器會(huì)做編譯檢查,
    通過id類型的指針去調(diào)用對(duì)象的方法的時(shí)候,編譯器直接通過,無論調(diào)用什么方法。
    注意: id指針只能調(diào)用對(duì)象的方法,不能使用點(diǎn)語法,如果使用點(diǎn)語法就會(huì)直接報(bào)編譯錯(cuò)誤 。如果要聲明1個(gè)萬能指針 千萬不要使用NSObject 而是使用id

instancetype --- id

id和instancetype的區(qū)別.

  1. instancetype只能作為方法的返回值,不能在別的地方使用。
    id既可以聲明指針變量,也可以作為參數(shù),也可以作為返回值。
  2. instancetype是1個(gè)有類型的代表當(dāng)前類的對(duì)象。
    id是1個(gè)無類型的指針,僅僅是1個(gè)地址,沒有類型的指針。

new方法

創(chuàng)建對(duì)象,我們之前通過new方法
類名 *指針名 = [類名 new];
new實(shí)際上是1個(gè)類方法,其作用為:

  1. 創(chuàng)建對(duì)象。
  2. 初始化對(duì)象。
  3. 把對(duì)象的地址返回。

new方法的內(nèi)部,其實(shí)是先調(diào)用的alloc方法,再調(diào)用的init方法。
alloc方法是1個(gè)類方法。作用: 那1個(gè)類調(diào)用這個(gè)方法就創(chuàng)建那個(gè)類的對(duì)象,并把對(duì)象返回,分配內(nèi)存空間。
init方法是1個(gè)對(duì)象方法。作用: 初始化對(duì)象。

init方法
作用: 初始化對(duì)象,為對(duì)象的屬性賦初始值,這個(gè)init方法我們叫做構(gòu)造方法。
init方法做的事情:初始化對(duì)象,并為對(duì)象的屬性賦默認(rèn)值。
如果屬性的類型是基本數(shù)據(jù)類型就賦值為0,C指針賦值NULL,OC指針賦值nil。
所以,我們創(chuàng)建1個(gè)對(duì)象如果沒有為這個(gè)對(duì)象的屬性賦值這個(gè)對(duì)象的屬性是有默認(rèn)值的。

重寫init方法的規(guī)范:
1). 必須要先調(diào)用父類的init方法,然后將方法的返回值賦值給self。
2). 調(diào)用init方法初始化對(duì)象有可能會(huì)失敗,如果初始化失敗,返回的就是nil。
3). 判斷父類是否初始化成功,判斷self的值是否為nil,如果不為nil說明初始化成功。
4). 如果初始化成功就初始化當(dāng)前對(duì)象的屬性。
5). 最后 返回self的值。

自定義構(gòu)造方法:
1). 自定義構(gòu)造方法的返回值必須是instancetype。
2). 自定義構(gòu)造方法的名稱必須以initWith開頭。
3). 方法的實(shí)現(xiàn)和init的要求一樣。

文中如果有不對(duì)的地方歡迎指出。我是xx_cc,一只長(zhǎng)大很久但還沒有二夠的家伙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,179評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,444評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,948評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,185評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,717評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,794評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,414評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,750評(píng)論 2 370

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