1, Block語法
定義:Block就是把一個匿名函數定義成一個變量,
語法格式: int (^)(int, int) Block類型
等號右邊給變量賦值,賦值是一個匿名函數
int (^myBlock)(int , int ) = ^int (int a, int b)
{
return a > b ? a : b;
};
int result = myBlock(10, 15);
NSLog(@”%d”, result);
//賦值的匿名函數返回值類型可以去掉 ^/*int*/(int a, int b)
//無參無返回值賦值匿名函數的時候,參數,返回值可以省略
void (^helloBlock)() = ^
{
NSLog(@”hello world”);
};
helloBlock();
API知識
//將字符串按某節點分割,取第一塊
NSString * (^splitString)(NSString *, NSString *) = ^(NSString * targetString, NSString * sepatorString)
{
return [[targetString componentsSeparatedByString: sepatorString] firstObject];
};
NSString * string = splitString(@www.baidu.com, @”.”);
NSLog(@”%@”, string);
//逆序輸出數組
API: exchangeObjectAtIndex: (nsinteger)withObjectAtIndex: (nsinteger)
//將字符串數組拼接成字符串輸出
API: (NSString * targetstring) stringByAppendingString: (NSString * appendingstring);
//Block回調,
//Block用於排序
案例:在定義多個person對象后,對person對象進行年齡排序,定義一個不可變數組存放每個person對象,
Block語法: NSArray * newArray = [Array SortedArrayUsingComparator: ^ NSComparisionResult(id obj1, id obj2)]
{
//強轉類型,在輸出的時候能快速定位到年齡
Person * person1 = (Person *)obj1;
Person * person2 = (Person *)obj2;
If ([person1 age] < [person2 age])
{
Return NSOrderedAscending;
}else if ([person1 age] > [person2 age])
{
return NSOrderedDescending;
}
return NSOrderedSame;
} ];
//默認情況下,Block中使用Block之外的變量,默認是只讀的,不可修改
//使用__block告訴編譯器,此變量在block中可以使用
//block類型的參數是用於回調時從里向外傳值(傳遞信息出去)
//block類型種的類型返回值用於從外向里傳值,(就是block回調完得到的結果)
多態:
//允許父類指針指向子類型對象
//屏蔽子類之間的差異,寫出更通用的代碼
//常見形式:
//參數多態和返回值多態
屬性
屬性的聲明: 屬性的類型 屬性名
@property NSString * name;
//等價於聲明了一對方法,一個setter, 一個getter
//屬性的類型決定生成的setter方法的參數類型,getter方法的返回值類型
//屬性名決定生成的方法名是什么
屬性的特性:
第一大特性:
//readwrite 既生成setter, 也生成getter
//readonly 只生成 getter
//setter = , getter = , 用於控制生成setter方法和方法名
原子性特性:
//nonatomic 非原子性特性,不保證在多線程環境下訪問實例變量的安全性
//atomic 原子性特性(默認), 保證在多線程環境下訪問實例變量是安全的, 因為會加一把線程鎖
setter語義特性,控制生成的setter方法的內部實現細節
//assign (默認), 通常適用基本類型,setter方法中就是直接賦值
//retain, 適用於所有的對象類型,setter方法中會自動生成內存優化的代碼
//copy, 僅適用於接受過NSCoping協議的類的對象才適用
如果屬性的setter方法和getter方法同時重寫
//那么默認就不會幫你生成實例變量
//解決方案1:自己定義實例變量
//解決方案2:使用@synthesize
//@synthesize array = _array;
屬性的實現
//name = _name的含義,屬性name生成的setter和getter的實現中操作_name這個實例變量
//會先檢查有沒有該實例變量,如果沒有,會自動生成
//從iOS6.0之后@synthesize也可以不用寫了,編譯器自動生成
//但默認生成的屬性實現中是操作與屬性名同名加下划線的實例變量
//實例變量也可以不寫,不寫會自動生成,但生成的是私有的,子類不可以直接訪問
//父類里私有的實例變量,僅僅是不可以在子類中直接訪問
//子類創建對象的時候,這些父類私有實例變量也會被分配內存存儲,可以通過同父類繼承的setter或getter訪問
點語法
//點出現在等號左邊,等價於調用了setter方法
//點出現在等號右邊,等價於調用了getter方法
//沒有等號出現點,等價於getter
KVC(鍵值編碼)
時間類API使用
NSDate (date) 獲取當前時間
NSDateFormatter 把日期和字符串之間互轉
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
//設置轉換格式
formatter.dateFormat = @”yyyy-MM-dd EEEE hh:mm:ss a”;
//把日期對象轉成一個字符串
NSString * dateString = [formatter stringFromDate:date];
NSLog(@”%@”, dateString);
//假設這個是服務器端給我們返回的一個時間戳
//是一個表示時間的字符串
NSString * dateString = @”20150814061022”;
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
//字符串格式要跟返回的字符串格式一樣才能正確輸出
formatter.dateFormat = @”yyyyMMddhhmmss”;
//把日期字符串轉換成日期對象
NSDate * messageDate = [formatter dateFormString: dateString];
//獲取當前時間
NSDate * currentDate = [NSDate date];
//得到兩個時間之間相差的描述
NSTimeInterval = seconds = [currentDate timeIntervalSinceDate:messageDate];
NSLog(@”%.1f”, seconds);
后邊可以接跟時間長短的判斷,分成剛剛,幾分鍾前,幾小時前,幾天前,幾月幾號幾時幾分幾秒
得到一個從現在開始多少秒后的一個時間
NSDate * date = [NSDate dateWithTimeIntervalSinceNow:120];
NSLog(@”%@”, date);
得到從1970年到當前時間流逝的秒數
[date timeIntervalSince1970];
根據一個從1970年流逝的秒數得到一個時間對象
[NSDate dateWithTimeIntervalSince1970:seconds];
類目
//類目(分類, Categary): 給一個沒有原碼的類擴展方法
//類目只能擴展方法,不能擴展實例變量
//擴展的方法會成為原始類的一部分,和原始類中的方法一樣,級別相同,會被子類繼承
// 目標類 類目名
@interface NSString (SayHIMethod)
延展
//延展Extension, 幫一個類管理私有方法和私有變量
//OC中沒有絕對的”私有”方法,所謂私有方法就是在.m里有實現, .h里面沒有聲明
//延展就是一種特殊形式的類目,就是把類目的聲明寫到.m中,並且()里不加類目名
協議
//在 .h文件里創建
//協議中方法的參數的作用:用於讓代理調用時給它信息,供代理使用
//協議中方法返回值的作用:用於得到代理調用完方法的結果,讓委托方作出處理
//協議中定義的是一堆方法聲明,只有聲明,沒有實現
//一個類可以接受一到多個協議,接受了協議就必須實現協議里面的@required方法
//@required修飾的方法代表必須實現,@optional代表的方法是可選實現
//在父類后面加<協議名>表示遵守協議
內存管理
內存管理原則一:
//凡是出現alloc , retain, copy的地方,都要有對應的release或者autorelease與之對應,保證對象用完的時候可以被及時的銷毀
內存管理原則二:
//建類必備dealloc, 凡是有屬性被修飾成retain或copy的,都要dealloc里release, 防止外界使用屬性賦值之后最后一份釋放不掉
內存管理原則三:
//便利構造器內自帶autorelease
//問題1: 一個對象通過屬性賦完值之后,對象提前銷毀了,導致賦值完的屬性也用不了
//解決方案:賦值時加一個retain,那么會帶來問題2;
//問題2:每一次賦新值得時候,上次舊值留到內存里
//解決方案,每次賦新值前,先release一次舊值
//但是會產生問題3
//問題3: 多次給一個屬性賦同一個值,第二次賦值時對對象提前釋放
//解決方案:setter中加一個判斷,如果是同一個值,不做任何處理
//問題4: 最后一份創建的對象無法釋放
//解決方案:當班級對象被銷毀的時候,釋放學生的所有權,即重寫dealloc, release對象之后加[super dealloc]
自動釋放池
//工作原理:當對一個對象發送autorelease消息,就會把這個對象扔到離它最近的釋放池中,當這個池銷毀的時候會把池中所有管理的對象逐一發送一次release,進池出池的過程和棧一樣,遵循先進后出的原則,先進池的對象,池銷毀后release
copy
//當對一個對象發送copy消息,會自動調用copyWithZone:方法
//在copyWithZone:方法中,NSZone類型的參數記錄的原對象的內存結構信息,根據原對象內存結構信息,復制出一個副本
//再把原對象實例變量里面的內容賦值給拷貝出新對象的實例變量
//會讓拷貝出得新對象引用計數從0到1,原對象引用計數不變
字符串對象的內存管理
//常量區的字符串引用計數是一個無符號整形數的最大值,正常應使用%lu輸出,使用%d輸出會溢出,顯示-1
//無論對它release,還是retain,都無任何影響
dealloc
//對象引用計數變為0時,對象要被銷毀(內存回收), 這時會自動調用對象的dealloc方法
//dealloc方法永遠不要手動調用
數組字典的內存管理
//數組,字典,集合會對管理的對象引用計數加1
內存管理原則四:
//誰污染誰處理,凡是你自己alloc, retain, copy的,你就得有對應的,release或者autorelease, 不是干的,不要你管
//每次創建一個新字符串,產生的舊字符串會被存放在釋放池中,過多累積
//解決方案:添加自動釋放池
//防止對象被提前釋放,可以采用建空指針的方法避免
對象類型屬性兩個作用:
//1,方便在類的外部訪問類的實例變量
//2,幫你優化一份內存,在對象的整個生命周期中一直可以使用該實例變量
//在方法里創建對象,如果對象的地址保存在一個棧區指針里邊,那么出方法前,一定要release或者autorelease掉
//一旦有被retain, copy修飾的對象,就要重寫dealloc
//為了保證數組在一個方法中創建完,到另外一個方法中也能用
//通常把數組,定義為屬性,使用self.創建對象,因為此時相當於調用了setter方法, setter方法內部會retain一次,保證數組對象在所屬類的整個生命周期中都可以使用,這次retain, 在所屬類的dealloc中release一次
//使用數組是可以使用_array, 和使用self.array沒有區別, 因為是getter
//getter方法更安全的 寫法
return [[_array retain] autorelease];
//作用:延長對象的聲明周期