GeekBand~iOS~Objective-C~第一周

1.Objective-C簡介

1.1 簡介

1.基于C語言,在C語言基礎上,做了面向對象擴展。
2.1980年代初由 Brad Cox 和 Tom Love 發明,后來稱為NeXT的主力語言,后被蘋果收購,成為蘋果開發平臺的主力語言。
3.與Cocoa 和Cocoa Touch框架高度集成,支持開發Mac OS X、iOS應用。
-Mac OS X是蘋果公司為Mac系列產品開發的專屬操作系統。
-iOS是由蘋果公司開發的手持設備操作系統。
4.在蘋果開發平臺上,通過LLVM編譯器架構,支持與Swift語言雙向互操作。

1.2 iOS開發平臺
iOS開發平臺.png
1.3開發方式

-Clang 或 GCC 命令行
a.clang -fobjc-arc Hello.m
b.-fobjc-arc 支持ARC內存管理
c.適合調試、研究
-Xcode項目
a.構建正規工程項目
b.使用大型框架,追求設計質量與代碼組織
-Demo

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]){
    @autoreleasepool {
        NSLog(@"Hello, World!");
    }
    return 0;
}

1>NSLog是一個日志輸出函數,可以將傳入的字符串參數輸出到控制臺。
2>@"Hello,World!"是OC字符串,前面有@。

輸出結果.png

3>#import,包含某個文件的內容到 處理指令所在位置。
#import <Foundation/Foundation.h>
表示包含Foundation框架中的Foundation.h文件。
OC使用#import包含頭文件,可以自動防止同一個頭文件被包含多次。

1.4 ObjC編譯過程
編譯過程.png

2.類與對象

類(class)是一種表示對象類型的結構體。類有屬性和方法。
對象(object)是類的具體化的東西,從抽象中到具體化出的特定個體。
OC一般用2個文件描述一個類(.h和.m)。
1> .h:類聲明文件,用于聲明成員變量、方法。類聲明關鍵字@interface 和 @end。
RPoint.h
@interface RPoint: NSObject @property int x; @property int x; -(void) print; @end
2> .m:類的實現文件,用于實現.h中聲明的方法。類實現關鍵字@implementation和@end。
RPoint.m

#import <Foundation/Foundation.h>
#import "rpoint.h"
@implementation RPoint
-(void) print{
    NSLog(@"[%d, %d]", self.x,self.y);
}
對象

創建對象

#import <Foundation/Foundation.h>
#import "rpoint.h"
int main(int argc, const char * argv[]) {
     @autoreleasepool {
        RPoint* rp1=[[RPoint alloc] init];
      }
        return 0;
}

-->要用到Rpoint這個類,所以包含它的頭文件#import "rpoint.h"
-->(1)調用Rpoint類的靜態方法alloc分配存儲空間,
RPoint* rp1=[[RPoint alloc] init];
返回Rpoint對象,用一個指向Rpoint類型的指針變量rp1來接收這個對象。用類名定義一個變量時,類名后面一定要帶個*號。
alloc方法聲明:+(id)alloc;,返回值類型時id,id代表任何指針類型,可以代表任何OC對象。
-->(2)調用RPoint對象的構造方法init進行初始化
rp1 = [rp1 init];
類——引用類型
1>位于棧上的指針(引用)
2>位于堆上的實體對象
對象:棧上存儲指針(引用),堆上存儲真正的對象。

對象存儲.png

結構——值類型
實例直接位于棧中。

值的存儲.png

棧(stack)
1>無ARC負擔,由系統自動管理,以執行函數為單位。
2>空間大小編譯時確定(參數+局部變量)。
3>函數執行時,系統自動分配一個stack。
4>函數執行結束,系統立即自動回收stack。
5>函數之間通過拷貝值傳遞。
6>具有局部性,大小有限額,超出會stack overflow。
堆(heap)
1>分配由程序員手動請求(創建對象時)。
2>釋放由運行時ARC機制自動釋放(確定時)。
3>函數之間通過拷貝引用(指針)傳遞。
4>具有全局性,總體無大小限制(受制于系統內存整體大小)。
拷貝行為

RPoint* rp2 = rp1;
SPoint sp2 = sp1;
拷貝后.png
rp2.x++;  rp2.y++;
sp2.x++;  sp2.y++;
更改后.png

傳參行為

process(rp1,sp1);
void process(RPoint* rp3, SPoint SP3){
    rp3.x++;
    rp3.y++;
    sp3.x++;
    sp3.y++;
}
傳參后.png
傳參改變后.png

3.數據成員:屬性與實例變量

3.1 屬性

屬性表達實例狀態,描述類型對外接口。相比較直接訪問實例變量,屬性可以做更多控制。
默認情況下,編譯器會為屬性定義propertyName自動合成:
1>一個getter訪問器方法:propertyName
2>一個setter訪問器方法:setPropertyName
3>一個實例變量 _propertyName
可以自定義訪問器方法,也可以更改訪問器方法名、或實例變量名。
可以使用靜態全局變量(C語言)+類方法,模擬類型屬性。
屬性聲明由@property 指令以及緊跟其后的特性組成。

@property NSString* firstName;
@property NSString* lastName;
@property int age;
@property NSDate* birthday;
@property (readonly) NSString* fullName;
3.2 實例變量

可以定義實例變量,而不定義屬性。只有實例變量,沒有類變量。
如果同時自定義了getter和setter訪問器方法,或者針對只讀屬性定義了getter訪問器方法,編譯器將不再合成實例變量。
在類外一律使用屬性來訪問,類內大多也通過self使用屬性訪問。只有以下情況使用實例變量來訪問:
1>初始化器 init
2>析構器 dealloc
3>自定義訪問器方法

3.2 實例變量的生存周期

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

對象實例變量.png

值類型實例變量直接“內嵌”在對象實例中。跟隨對象實例內存釋放而被釋放。


值實例變量.png

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

3.3 屬性的描述特性(Attribute)

可以指定屬性不同環境下的不同功能。
->讀寫特性:
readwrite或者readonly
指定該屬性是否可寫。默認是可讀可寫
@property (readonly) NSString* fullName;
->多線程特性:
nonatomic指定生成的存取器函數是非原子性的,非線程安全;默認atomic原子性,線程安全。
->內存管理特性
-->ARC環境
強引用strong(默認)
弱引用weak阻止循環引用
拷貝屬性copy創建獨立拷貝
-->其它情況
assign、retain、unsafe_unretained
決定為該屬性生成的賦值函數的類型。
assign 簡單地為變量賦值。retain 賦值到變量時會保留傳入的參數。默認值是 assign

強引用.png

--循環引用(強引用)

WorkItem* workItem=[[WorkItem alloc] init];
workItem.content=@"CRM";
循環引用.png

--弱引用

employee.workItem=workItem;
workItem.owner=employee;
弱引用.png

--拷貝

a.賦值前

NSLog(@"Work Content: %@",workItem.content);

結果:Work Content: CRM

賦值前結果.png

賦值前.png

b.賦值后

NSMutableString *workContent = [NSMutableString stringWithString:@"ERP"];
workItem.content=workContent;
NSLog(@"Work Content: %@",workItem.content);

結果:Work Content: ERP

賦值后結果.png

賦值后.png

4.函數成員:方法

方法 Method

函數:代碼段上的可執行指令序列
->全局函數(C語言函數)
->成員函數(ObjC方法)
方法是類的成員函數,表達實例行為或類型行為。
所有方法默認為公有方法。沒有private或protected方法。
動態消息分發:方法調用通過運行時動態消息分發實現,在對象上調用方法又稱“向對象發送消息”。

-(void) print;
-(BOOL) isEqualToPoint: (BLNPoint*) point;
+(BLNPoint*) getOriginPoint;

1.'-'表示動態方法(實例方法);'+'表示靜態方法(類型方法)。
2.print前面的(void)表示方法無返回值,方法的返回值和參數類型都需要用小括號()包住。
3.OC方法中,一個冒號:對應一個參數。冒號 : 也是方法名的一部分。例如:isEqualToPoint:
4.方法調用:

BLNPoint* p1=[[BLNPoint alloc] init];
[p1 print];
實例方法或類型方法

1>實例方法——表達實例行為,可以訪問
-->實例成員(實例屬性、實例變量、實例方法)
-->類型方法、靜態變量
2>類方法——表達類型行為,訪問權限:
-->可以訪問:類型方法、靜態變量
-->不能訪問:實例成員(實例屬性、實例變量、實例方法)
3>了解編譯器背后對實例方法和類方法的不同處理:self指針
對實例方法:實例對象的指針
對類方法:當前類的表示

方法參數

->如果參數類型為值類型,則為傳值方式
-(void) moveToX:(int)x toY:(int)y;
如果參數類型為引用類型,則為傳指針方式
-(BOOL) isEqualToPoint: (BLNPoint*) point;
->方法可以沒有參數,也可以沒有返回值
->如果方法有參數,方法名約定包含第一個參數名,從第二個參數開始需要顯式提供外部參數名。

-(void) moveToX:(int)x toY:(int)y;

moveToX包含第一個參數名,toY為第二個參數的外部參數名。
->調用時,第一個參數名忽略,但后面的參數名必須顯式標明。
[p1 moveToX:100 toY:200];

動態方法調用機制——消息分發
BLNPoint* origin=[BLNPoint getOriginPoint];
        [origin print];
id obj=[[BLNPoint alloc] init];
        [obj moveToX:50 toY:60];
        [obj print]; 

//JMP obj-> methodLists-> &print


消息分發表.png

5.初始化器與析構器

認識

1.初始化器用于初始化對象實例或者類型,是一個特殊的函數。
->對象初始化器:-(id) init可以重載多個

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

->類型初始化器:+(void)initialize只能有一個

+(void)initialize;

2.析構器用于釋放對象擁有的資源,無返回值的函數。
->對象析構器 -(void)dealloc 只有一個
->沒有類型析構器

對象初始化器

->初始化對象實例時,init通常和alloc搭配使用。
->alloc所做的事情——NSObject已實現:
-->1.在堆上分配合適大小的內存。
-->2.將屬性或者實例變量的內存置0。
->init所做的事情——可以自定義:
-->1.調用父類初始化器[super init](前置調用)。

-(id)init{
    self = [super init];
    if(self){
        NSLog(@"Book Object init");
    }
    return self;
}

-->2.初始化當前對象實例變量(使用實例變量,不使用屬性)。

-(id)initWithName:(NSString *)name WithPages:(int)pages WithCategory:(NSString*)category
{
    self = [super init];
    if (self) {
        NSLog(@"Book Object init");
        _name = [name copy];
        _pages = pages;
        _category = [category copy];
    }
    return self;
}

->new相當于調用alloc/init的無參數版本。

類初始化器

->類初始化器initialize負責類型級別的初始化。
->initialize在每個類使用之前被系統自動調用,且每個進程周期中,只被調用一次。
->子類的initialize會自動調用父類的initialize(前置調用)。

+(void)initialize
{
    if(self ==[Book class]){  
        NSLog(@"Book Class initialize");
    }
}
對象析構器

->對象析構器dealloc負責釋放對象擁有的動態資源:
-->自動實現:1. ARC 將對象屬性引用計數減持
-->手動實現:2.釋放不受ARC管理的動態內存,如malloc分配的內存
-->手動實現:3.關閉非內存資源,如文件句柄、網絡端口

-(void)dealloc
{
    //1. 自動調用:ARC 對對象屬性的引用技術減持
    //2. 手工實現
    NSLog(@"Book Object release");
    //3. 自動調用:父類dealloc
}
內存釋放.png

->dealloc由ARC根據對象引用計數規則,在釋放對象內存前自動調用,無法手工調用。
->子類的dealloc會自動調用父類的dealloc(后置調用)。
-->1.子類的某些對象實例繼承自父類。需要調用父類的dealloc方法,來釋放父類擁有的這些對象。
-->2.調用順序:當子類的對象釋放完時,再釋放父類所擁有的實例。

6.繼承

面向對象特性

->封裝 encapsulation
隱藏對象內部實現細節,對外僅提供公共接口訪問。
->繼承 inheritance
一個類型在另外類型基礎上進行的擴展實現。
->多態 polymorphism
不同類型針對同一行為接口的不同實現方式。

繼承 Inheritance

->繼承:每一個類只能有一個基類,子類自動繼承基類的:
-->實例變量
-->屬性
-->實例方法
-->類方法
Shape.h

#import <objc/runtime.h>
#import <Foundation/Foundation.h>
@interface Shape : NSObject  {
    @public int _data;
}
@property int no;
-(void)draw;
-(void)move;
-(void)print;
+(void)process;
@end

Circle.h

#import "Shape.h"
#import <Foundation/Foundation.h>
@interface Circle : Shape
@property int radius;
@end

子類 Circle繼承基類Shape

Circle* circle = [[Circle alloc]init];
        circle.no=200;//訪問屬性
        circle->_data++;//訪問實例變量
        [circle draw];//訪問實例方法
        [circle print];//訪問實例方法
        [Circle process];//訪問類方法

->所有類的根類:NSObject

NSObject.png

->繼承的兩層含義:
-->成員復用:子類復用基類成員
*私有成員也被繼承,子類訪問不到。

-->類型抽象:將子類當作父類來使用(IS-A關系準則)
Circle is a Shape.

void process(Shape *shape){
    shape.no++;
    [shape draw]; 
}
process(circle);
繼承的內存模型.png

7.多態

多態 Polymorphism

->多態:子類在父類統一行為接口下,表現不同的實現方式。
->對比重寫與重載
-->子類重寫父類同名同參數方法:子類只可以重寫父類方法。
Rectangle繼承Shape
@interface Rectangle : Shape
Rectangle重寫Shape的方法:

#import "Rectangle.h"
@implementation Rectangle
//override 重寫
-(id)init
{
    self = [super init];    
    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");
}
@end

使用:

Rectangle *rect = [[Rectangle alloc]init];
        rect.no=200;
        rect->_data++;
        [rect draw]; 
        [rect print];
        [Rectangle process];
        [rect move];
運行結果1.png

----Shape是聲明類型,Rectangle實際類型

Shape *rect = [[Rectangle alloc]init];
        rect.no=200;
        rect->_data++;
        [rect draw]; 
        [rect print];
        [Rectangle process];
        [rect move];
運行結果2.png

-->方法名相同、參數不同:OC不支持方法的重載。

重載.png

->在子類的代碼中,可以使用super來調用基類的實現。
-->self具有多態性,可以指向不同子類。
-->super沒有多態性,僅指向當前父類。
Rectangle.m

-(int)no{
    return super.no;
}
-(void)setNo:(int)no{
    super.no=no;
}

Shape.m

{
    [self draw];
}
methodList的內存模型.png
繼承中的init和dealloc

->初始化器 init
-->子類自動繼承基類的初始化器
-->子類也可以重寫基類初始化器,此時子類初始化器必須首先調用基類的一個初始化器(手工調用)。
->析構器 dealloc
-->子類可以選擇繼承基類析構器,或者重寫基類析構器。
-->子類析構器執行完畢后,會自動調用基類析構器(后置調用,且不支持手工調用)。
-->子類析構器自動具有多態性。
->盡量避免在父類 init 和 dealloc 中調用子類重寫的方法。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容