ios OC初學

liushaozhuanyong發表於2017-07-25

OC原始檔字尾名為m,代表OC中最重要的一個機制:訊息機制。
OC程式的入口與出口仍然是main函式
OC支援C中的所有關鍵字、運算子、控制語句、函式
OC語言完全相容C語言

import即#include的增強版

同一個檔案無論#import多少次,始終匯入一次

NSLog是一個函式:

printf的增強版,想控制檯輸出資訊;
NSLog(@”hello world”);
執行結果包括:
當前執行時間、程式名、程式編號、執行緒編號、程式執行資訊
用法和printf相同、只不過前面要加@
NSLog的輸出是自動換行的,如果加上了\n,那麼NSLog的自動換行就會失效

字串

OC中設計了一個更為好用的用來儲存字串的NSString型別
NSString型別的指標變數 專門用來儲存OC字串的地址
使用NSLog輸出OC字串的佔位符為 %@

編輯、編譯、連結

cc -c xx.m

連結
cc xx.o
如果用到了框架
cc xx.0 - [framework framework_name]

新增的布林型變數

BOOL只有兩個值:YES/NO
Boolean的值為true/false

物件導向

類的宣告

@interface className : NSObject
{
  變數
}
@end

為類定位屬性時,屬性的名詞必須以下劃線開頭
類的方法的宣告應寫在interface中
屬性不允許在宣告的時候初始化

類的實現

@implementation className
@end

類名的每一個單詞的開頭必須以大寫開頭
類方法的實現應寫在implementation中

類的例項化

物件中除了成員變數外,還有一個isa指標,該指標指向程式碼段中該類所屬的類
當呼叫函式時,指標名先找到物件,當發現要呼叫函式時,就根據isa指標尋找該物件所屬的類

物件屬性的預設值

基本資料型別 0
C指標型別 null,可以作為指標變數的值,不指向任何一個區域,NULL其實等價於0,就是一個巨集
OC指標型別 nil 可以作為指標變數的值,不指向任何一個區域,NULL其實等價於0,就是一個巨集

nil == null 但是一般建議C指標用null,OC的類指標用nil

函式除了在函式的內部和和interface的大括弧中,其他地方都可以寫

類的實現可以放在使用類的後面

類方法宣告和實現時除了格式上

+ (return型別) functionName:[(資料型別) 形參名稱]

其他與普通方法無異

self相當於C/C++中的this指標,self指向該物件/類在程式碼段中的地址

載入類

第一次訪問類時
第一次使用類時

類中繼承自NSObject的方法 - (NSString *) description{} 就相當於java中的toString方法

訪問許可權問題

@private 只能在本類內部以及本類的方法實現中訪問
@public 只能在本類和本類的子類中訪問
@package 只能在當前的框架中訪問

點語法

OC中的點語法與Java、C#中的不同,OC中點語法預設呼叫程式設計師自己封裝好的setter和getter函式,那麼我們再setter、getter方法中就不能用點語法對類屬性進行賦值、防止無限遞迴

getter和setter方法的自動生成

@property 資料型別 屬性名

在interface中書寫左側語句則由編譯器自動生成對應屬性的getter和setter方法的宣告,但是此處屬性名為真實屬性名去掉下劃線,否則自動生成的方法宣告是不符合規範的
@synthesize 屬性名
同樣的,在implementation中書寫上述程式碼,則自動生成對應的getter和setter方法的實現

但是他們的實現都是預設自動生成一個私有的具有上述屬性名的屬性,如果需要生成對應的已經宣告的屬性的getter和setter方法,只需要書寫如下

@property 資料型別 屬性名 = _屬性名
@synthesize 屬性名 = _屬性名
@property(nonatomic/atomic,retain/assign,readwrite/readonly)
//nonatomic不會自動加執行緒安全鎖
//retain生成setter方法的時候先判斷新的是否等於舊的,如果不等於則先進行release再進行retain
//readwrite同時生成setter和getter
//readonly只生成getter
@property(nonatomic,retain,setter = xxx,getter = xxx)
//指定setter和getter方法的名字

測試指向物件的指標是否有某方法

responseToSelector:@selector(SEL)

判斷某指標指向的物件是否為某類的物件或其子類的物件

isKindOfClass: [className class]
isMemberOfClass: [] 判斷是否為物件
isSubclassOfClass: [] 是否為子類物件

分組導航標記

pragma mark 分組名 就會在導航條對應位置顯示一個標題
pragma mark - [分組名] 就會在導航條對應的位置顯示一條水平分隔線

繼承

OC中只有單根繼承,沒有多繼承

類方法也能被子類繼承,被繼承的類方法可以用子類名繼承,也可以用父類名繼承

super只能用來呼叫父類方法,不能用來呼叫屬性

里氏替換原則(LSP):子類可以替換父類的位置,程式功能不受影響,但是指向子類物件的父類指標無法呼叫子類特有的方法和屬性

多型

指向重寫了父類方法的子類物件的父類指標,被呼叫時,執行的是子類重寫了的方法

id指標

id指標是一個萬能指標,可以指向任意OC物件
NSObject *也是一個萬能指標
但是使用id呼叫方法時,編譯器直接同構,使用NSObject指標時,編譯器會做編譯檢查
id指標只能呼叫物件的方法,不能使用點語法,如果使用點語法就會直接報錯。

記憶體中的五大區域

儲存區域性變數

程式設計師手動申請的位元組空間 malloc、calloc、realloc函式

BSS段

儲存未被初始化的全域性變數、靜態變數

資料段

儲存已被初始化的全域性、靜態變數、常量資料

程式碼段

儲存程式碼

retainCount

每個物件都有一個retainCount引用計數器
retain訊號 即retainCount++
release訊號 即retainCount–

記憶體洩漏

在方法中為傳入的物件進行不適當的retain,就造成沒有適當的release

setter方法內:
- (void) setCar:(Car *car)
{
  if(_car != car)
  {
    [_car release];
    _car = car;
  }
}
//

野指標、殭屍物件

野指標:指標指向的物件已經被分配給別人
殭屍物件:物件已被釋放、但是這個物件佔有的空間還沒被分配給別人,殭屍物件無法被複活

殭屍物件檢查機制

Enable Zombie Objects 但是每當用到指標的時候,都會進行殭屍物件檢查,所以這非常消耗效能,那麼該如何避免殭屍物件錯誤呢,當一個指標成為野指標以後,將這個指標的值設定為nil

強指標

平常情況下宣告的一個指標就是強指標
在ARC的機制下,如果一個物件沒有任何一個強指標指向他,就會被立即釋放
也可以用_ strong、 _weak分別宣告強指標和弱指標

ARC機制下

某物件被釋放後、原來指向這個物件的弱指標自動被設定為nil
@property中的retain引數不能用
####ARC機制下的使用建議
如果是OC物件型別,就用strong,不是OC物件型別就用assign
存在類間屬性互相引用的情況下,一端使用weak,一端使用strong

將整個程式從MRC轉換為ARC: Edit—Convert

分類

    @interface 類名 (分類名) : 父類
    @end
@implementation 類名 (分類名)
@end

但是在分類中只能增加方法,不能增加屬性
如果分類中有和本類同名的方法,則優先呼叫分類中的方法,哪怕沒有呼叫分類的同檔案
如果多個分類有同名的方法,則呼叫最後編譯的那個分類中的方法
###分類高階(非正式協議)
既然優先呼叫分類的方法、那我們就可以在某些層面上“篡改”apple公司已經編好的、令人不爽的方法,只需要為該類建立一個分類,並在分類中“篡改”或新增自己想要該類擁有的方法即可

延展

延展是一個特殊的分類,只有宣告、沒有實現,和本類共享一個實現
延展可以新增任意的成員屬性,也可以寫@property,既生成私有屬性,也生成setter、getter方法的宣告和實現
用延展來為類寫真私有屬性
也可以將私有方法的宣告寫在延展中,實現寫在本類的實現當中,提高程式碼的可讀性
延展天生就是用來私有化成員的

block

與C中的函式類似
##block高階
將block作為引數傳入
將block做返回值返回

協議(protocol)

協議專門用來宣告一大堆方法,只要某類遵循某個協議,那麼這個類就擁有該協議的所有方法
某類遵循某協議的語法:
@interface className : 父類名

@required和@optional

@required表示如果遵守該協議的類沒有實現,編譯器就會報警告
@optional表示如果未遵守該協議的類沒有實現,編譯器不會報警告
但是沒有關係,”反正只是警告而已”

協議之間可以繼承、並且可以多繼承

繼承語法

@protocol protocolName <父協議名>
@end

類的名稱可以和協議的名稱一致

異常處理

@try
{
  可能出現異常的程式碼段
}
@catch(NSException *exc)
{
  對異常的處理
}
@finally
{
  此處無論是否發生異常都會被執行到
}

自動釋放池@autoreleasepool

最高法則:唯一的作用就是省略建立物件匹配的那個release

如果A類是B類的引數,那麼稱B類依賴於A類

多執行緒

NSThread

Swift

常量&變數

let定義常量,var定義變數

自動推導

會根據設定數值的右側程式碼,推斷變數/常量的型別

永遠不會對變數/常量做隱式轉換,所以兩個不同型別的變數計算的時候,必須全權由程式設計師來做型別管理(強制轉換)

可選項

一個變數可以是本身的型別,也可以是nil
var y: Int ?= 10
可選項不能直接參與計算,但是可以“強行解包”
print( y! + 20)
就是新增驚歎號,表示:程式設計師承諾y一定是有值的,如果沒有,就在執行時候崩潰給我看

控制流

條件

if 條件 {
  expression;
}

if後沒有圓括號,但是語句必須有花括弧
switch可以判斷任意型別的數值,而且不需要break,各個case之間不會穿透,如果相對多個case執行同一個決定,只需要在case後面的值加逗號即可,不需要使用花括弧分隔作用域

字串

substringWithRange(Range型別)
[int]..<[int] 用來定義一個範圍

陣列


array.append()

array.removeFirst()
array.removeLast()
array.removeAll()

array[i] = sth

約定俗成

單引數的函式名稱最好寫成xxxWith
一個類寫在一個模組中,一個模組至少包含兩個檔案.h寫類的宣告 .m寫類的實現
如果建立了一個類,就要為該類寫一個與類同名的類方法,方法實現建立一個最純潔的類並返回
屬性名要求以下劃線開頭,區域性變數不要求。故一般不會產生區域性變數與類屬性重名的情況
所有協議都必須直接或間接地從NSObject基協議繼承

小技巧

  • 隱藏頂部狀態列
- (BOOL)prefersStatusBarHidden
{
    return true;
}

相關文章