天天看點

ios OC初學字元串編輯、編譯、連結面向對象分組導航标記繼承多态id指針記憶體中的五大區域block協定(protocol)異常處理自動釋放池@autoreleasepool多線程Swift約定俗成小技巧

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;
}