1.
clipsToBounds:是指視圖上的子視圖,如果超出父視圖的部分就截取掉,
masksToBounds:是指視圖的圖層上的子圖層,如果超出父圖層的部分就截取掉
2.
// NSArray --> NSMutableArray
NSMutableArray *myMutableArray = [myArray mutableCopy];
// NSMutableArray --> NSArray
NSArray *myArray = [myMutableArray copy];
3.
1.自定義cell時籍滴,
若使用nib筝蚕,使用 registerNib: 注冊哑了,dequeue時會調(diào)用 cell 的 -
(void)awakeFromNib
不使用nib扔茅,使用 registerClass: 注冊, dequeue時會調(diào)用 cell 的 - (id)initWithStyle:withReuseableCellIdentifier:
2.需不需要注冊奸焙?
使用dequeueReuseableCellWithIdentifier:可不注冊斑司,但是必須對獲取回來的cell進行判斷是否為空累舷,若空則手動創(chuàng)建新的cell蝇摸;
使用dequeueReuseableCellWithIdentifier:forIndexPath:必須注冊,但返回的cell可省略空值判斷的步驟捌袜。
4.
如果該類沒有ViewController
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
5.字典和實體類的轉(zhuǎn)換
[self setValuesForKeysWithDictionary:dict];
6.delegate block屬性的關(guān)鍵字
- 為了防止循環(huán)引用说搅,delegate的關(guān)鍵字使用weak
- block作為類的屬性時用copy
Block屬性的聲明,首先需要用copy修飾符虏等,因為只有copy后的Block才會在堆中弄唧,棧中的Block的生命周期是和棧綁定的
<棧 :由系統(tǒng)維護的局部變量 是存在棧上的,其生命周期隨函數(shù)的生命周期>
<堆 :由程序員申請空間地址霍衫,由程序員手動釋放套才,生命周期受到程序員控制>
使用retain也可以,因為block的retain行為默認是用copy的行為實現(xiàn)的慕淡,block變量默認是聲明為棧變量的,為了能夠在block的聲明域外使用沸毁,所以要把block拷貝(copy)到堆峰髓,所以說為了block屬性聲明和實際的操作一致,最好聲明為copy息尺。
另一個需要注意的問題是關(guān)于線程安全携兵,在聲明Block屬性時需要確認“在調(diào)用Block時另一個線程有沒有可能去修改Block?”這個問題搂誉,如果確定不會有這種情況發(fā)生的話徐紧,那么Block屬性聲明可以用nonatomic。如果不肯定的話(通常情況是這樣的)炭懊,那么你首先需要聲明Block屬性為atomic并级,也就是先保證變量的原子性(Objective-C并沒有強制規(guī)定指針讀寫的原子性)。
參考
7.隱藏UITableBar
當頁面使用 UITabBarController + UINavigationController 框架的時候侮腹,當跳轉(zhuǎn)到詳情頁面的時候嘲碧,如果 UITabBar 仍然存在的話就會造成邏輯混亂,用戶體驗也會下降父阻,因此我們就有一個在詳情頁將 UITabBar 隱藏的需求愈涩,參考鏈接
self.hidesBottomBarWhenPushed = YES;
self.tabBarController.tabBar.hidden = NO;
修改 TabBar 的 subview 的 frame
8. id的使用
id <SDWebImageOperation> operation
9. runtime動態(tài)添加屬性
10. 自定義NSOperation
11.NSURLSession
12.KVO KVC
kvo的用法非常簡單。
1加矛,添加觀察者
2履婉,在觀察者中實現(xiàn)監(jiān)聽方法,observeValueForKeyPath: ofObject: change: context:(通過查閱文檔可以知道斟览,絕大多數(shù)對象都有這個方法毁腿,因為這個方法屬于NSObject)
3,移除觀察者修改成員變量不會觸發(fā)監(jiān)聽器,只有修改屬性值才行。
例如
self.changeHeight = self.frame.size.height;//能觸發(fā)
_changeHeight = self.frame.size.height;//不能觸發(fā)
參考鏈接手動KVO
[self willChangeValueForKey:@"changeHeight"];
_changeHeight = self.frame.size.height;
[self didChangeValueForKey:@"changeHeight"];
- 禁用自動KVO
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
if ([theKey isEqualToString:@"changeHeight"]) {
return NO;
} else {
return [super automaticallyNotifiesObserversForKey:theKey];
}
}
13.HTTPS 驗證
14.網(wǎng)絡(luò)緩存
15.NSURLCache
16.extern const static
- extern 用法
- a.m 文件中定義
#import "a.h"
NSString * const strExtern = @"strExtern";
a.h文件中聲明
extern NSString * const strExtern;
b.m 文件對外部變量進行引用
#import "a.h"
NSLog(@"strExtern : %@", strExtern);
- const 用法
- 聲明字符串常量
NSString * const strExtern = @"strExtern";
- 以下聲明方式的區(qū)別
- 聲明字符串常量
NSString * const strExtern = @"strExtern";//指針指向的地址(strExtern)不可變
const NSString *strExtern = @"strExtern";//字符串內(nèi)容(*strExtern)不可變
- static 用法
如果定義在.m文件中則不能對外使用狸棍,只能本文件使用
static NSString * const strExtern = @"strExtern";
16. __nullable和 __nonnull
蘋果在Xcode 6.3引入了一個Objective-C的新特性:nullability annotations身害。這一新特性的核心是兩個新的類型注釋:__nullable和__nonnull。從字面上我們可以猜到草戈,__nullable表示對象可以是NULL或nil塌鸯,而__nonnull表示對象不應(yīng)該為空。當我們不遵循這一規(guī)則時唐片,編譯器就會給出警告丙猬。
17. delegate block 的修飾符
18. block 引起的循環(huán)引用
某個類將block作為自己的屬性變量,然后該類在block的方法體里面又使用了該類本身费韭,即使在你的block代碼中沒有顯式地出現(xiàn)"self",也會出現(xiàn)循環(huán)引用星持!只要你在block里用到了self所擁有的東西!簡單說就是
self.someBlock = ^(Type var){
[self dosomething];
或者self.otherVar = XXX;
或者_otherVar = ...
}
- 解決方法
__weak typeof(self) weakSelf = self;
self.blkA = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;//加一下強引用,避免weakSelf被釋放掉
NSLog(@"%@", strongSelf->_xxView); //不會導(dǎo)致循環(huán)引用.
};
- 總結(jié)
分兩種環(huán)境去解決:
1)ARC環(huán)境下:ARC環(huán)境下可以通過使用_weak聲明一個代替self的新變量代替原先的self,我們可以命名為weakSelf。通過這種方式告訴block戳葵,不要在block內(nèi)部對self進行強制strong引用:(如果要兼容ios4.3,則用__unsafe_unretained代替__weak,不過目前基本不需考慮這么low的版本)
self.arr = @[@111, @222, @333];
__weak typeof(self) weakSelf=self;
self.block = ^(NSString *name){
NSLog(@"arr:%@", weakSelf.arr);
};
2)MRC環(huán)境下:解決方式與上述基本一致,只不過將__weak關(guān)鍵字換成__block即可念脯,這樣的意思是告訴block:小子,不要在內(nèi)部對self進行retain了!
19.id數(shù)據(jù)類型與靜態(tài)類型
- 雖然說id數(shù)據(jù)類型可以存儲任何類型的對象,但是不要養(yǎng)成濫用這種通用類型
- 如沒有使用到多態(tài)盡量使用靜態(tài)類型
- 靜態(tài)類型可以更早的發(fā)現(xiàn)錯誤(在編譯階段而不是運行階段)
- 靜態(tài)類型能夠提高程序的可讀性
- 使用動態(tài)類型前最好判斷其真實類型
- 動態(tài)類型判斷類型
- - (BOOL)isKindOfClass:classObj 判斷實例對象是否是這個類或者這個類的子類的實例
20.分類(category)和類擴展(extension)
- 分類中只能添加“方法”邦泄,不能增加成員變量。
- 分類中可以訪問原來類中的成員變量包蓝,但是只能訪問@protect和@public形式的變量届巩。如果想要訪問本類中的私有變量腕唧,分類和子類一樣,只能通過方法來訪問。
- 雖說category中無法直接添加屬性膀曾,但是我們在Category中可以利用運行時添加屬性:
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self,
"name",
name,
OBJC_ASSOCIATION_COPY);
}
- (NSString*)name
{
NSString *nameObject = objc_getAssociatedObject(self, "name");
return nameObject;
}
-
分類的執(zhí)行優(yōu)先級
- 在本類和分類有相同的方法時,優(yōu)先調(diào)用分類的方法再調(diào)用本類的方法。
- 如果有兩個分類,他們都實現(xiàn)了相同的方法,如何判斷誰先執(zhí)行?分類執(zhí)行順序可以通過targets,Build Phases,Complie Source進行調(diào)節(jié),注意執(zhí)行順序是從上到下的。(只有兩個相同方法名的分類)
-
分類(category)和類擴展(extension)的關(guān)系
- 類擴展(extension)是category的一個特例壶冒,有時候也被稱為匿名分類瘪松。他的作用是為一個類添加一些私有的成員變量和方法毫胜。
- 類擴展能寫點啥?和分類不同口渔,類擴展即可以聲明成員變量又可以聲明方法样屠。
21.協(xié)議
協(xié)議中能夠聲明方法,以及屬性缺脉。然后問題就來了痪欲,不是不能定義成員變量的嗎?
對攻礼,的確不能定義成員變量业踢,但是屬性是什么?屬性包含了三個東西:成員變量礁扮、setter方法知举、getter方法。在類中定義的屬性太伊,當然三者都有雇锡,然而協(xié)議中定義的屬性只有獲取和設(shè)置方法,沒有成員變量僚焦,這就要求該協(xié)議的遵守者必須自己寫出setter和getter方法的實現(xiàn)锰提。但是有一種情況是不需要的,那就是遵守者本來就有這個屬性芳悲,此時系統(tǒng)會為這個屬性自動生成設(shè)置獲取方法立肘,既然已經(jīng)實現(xiàn)了,那么遵守者就沒必要去實現(xiàn)協(xié)議中的這個屬性了芭概。
盡管可以實現(xiàn)“偽屬性”赛不,但是惩嘉,我們還是應(yīng)該盡量把屬性定義在主接口中罢洲,而不應(yīng)該定義在協(xié)議中。
22.斷言
- (void)printMyName:(NSString *)myName
{
NSAssert(myName != nil, @"名字不能為空文黎!");
NSLog(@"My name is %@.",myName);
}
當傳給函數(shù)的參數(shù)(myName)為空時惹苗,斷言將被執(zhí)行,程序Crash耸峭,并打印出斷言中的描述信息桩蓉。本例中,在控制臺打印出了如下的日志:
NSAssert[1268:a0b] *** Assertion failure in -[ViewController printMyName:]
NSAssert/NSAssert/ViewController.m:38
2013-11-21 13:56:01.927 NSAssert[1268:a0b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '名字不能為空劳闹!'
開發(fā)者沒有必要在應(yīng)用程序的每個版本中都進行斷言檢查院究,這是因為大多數(shù)項目都是有兩個版本:Debug版和Release版洽瞬。在Debug版中,開發(fā)者希望所有的斷言都檢查到业汰,而在Release版中伙窃,往往都是禁用斷言檢查的。設(shè)置Release版本中禁用斷言的方法如下:
在Build Settings菜單样漆,找到Preprocessor Macros項为障,Preprocessor Macros項下面有一個選擇,用于程序生成配置:Debug版和Release版放祟。選擇 Release項鳍怨,設(shè)置NS_BLOCK_ASSERTIONS,不進行斷言檢查跪妥。
23.dispatch_barrier_sync和dispatch_barrier_async
共同點:
1鞋喇、等待在它前面插入隊列的任務(wù)先執(zhí)行完
2、等待他們自己的任務(wù)執(zhí)行完再執(zhí)行后面的任務(wù)
不同點:
1骗奖、dispatch_barrier_sync將自己的任務(wù)插入到隊列的時候确徙,需要等待自己的任務(wù)結(jié)束之后才會繼續(xù)插入被寫在它后面的任務(wù),然后執(zhí)行它們
2执桌、dispatch_barrier_async將自己的任務(wù)插入到隊列之后鄙皇,不會等待自己的任務(wù)結(jié)束,它會繼續(xù)把后面的任務(wù)插入到隊列仰挣,然后等待自己的任務(wù)結(jié)束后才執(zhí)行后面任務(wù)伴逸。
24.NSObject + (void)load
25.__attribute__
26.__IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_OS_VERSION_MIN_REQUIRED
這些編譯期常量, 對運行時的環(huán)境判斷完全無效, 它告訴編譯器用哪一段代碼來進行編譯, 那那段代碼里, 你仍然可以寫運行到目標機器里會崩潰的代碼
怎么解決? 組合!
- 我先判斷編譯環(huán)境, 以避免低版本SDK不認識高版本SDK的api, 造成編譯錯誤(片段1)
- 在高版本SDK的條件內(nèi), 自行開始判斷SDK版本, 或responedToSelector都可以,來判斷是否使用高版本的api
- 在低版本條件內(nèi), 直接用低版本的api
27. NSRunLoop
28. get 請求重定向
- NSURLConnetion方法
使用NSURLConnetion類的NSURLConnectionDataDelegate中的代理方法
(nullable NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(nullable NSURLResponse *)response
- NSURLSession方法
(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest * __nullable))
29.接口函數(shù)過期提醒
使用時xcode會提示‘showWithMaskType’ is deprecated:Use show and setDefaultMaskType: instead.
+ (void)showWithMaskType:(SVProgressHUDMaskType)maskType __attribute__((deprecated("Use show and setDefaultMaskType: instead.")));
30 +load,constructor,main的執(zhí)行順序
+ (void)load{
NSLog(@"load");
}
__attribute__((constructor))
void constr(){
NSLog(@"before main");
}
輸出結(jié)果如下:
2016-07-21 22:13:58.591 Study[14185:5421811] load
2016-07-21 22:13:58.592 Study[14185:5421811] before main
2016-07-21 22:13:58.592 Study[14185:5421811] main
31. NSURLProtocol
@interface CustomURLProtocol : NSURLProtocol
@end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//注冊protocol
[NSURLProtocol registerClass:[CustomURLProtocol class]];
return YES;
}
32. NSURLSessionConfiguration
33.FOUNDATION_EXPORT 與#define
34. Keychain
35. CoreText
36. NSUserDefaults
37. WindowLevel
- windowLevel有以下三種:
- UIWindowLevelNormal;// 0.000000
- UIWindowLevelStatusBar;// 1000.000000
- UIWindowLevelAlert;// 2000.000000
1)當Level層級相同的時候,只有第一個設(shè)置為KeyWindow的顯示出來膘壶,后面同級的再設(shè)置KeyWindow也不會顯示错蝴。
2)statusLevelWindow在alertLevelWindow之后調(diào)用makeKeyAndVisible,仍然只是顯示在alertLevelWindow的下方颓芭。這說明UIWindow在顯示的時候是不管KeyWindow是誰顷锰,都是Level優(yōu)先的,即Level最高的始終顯示在最前面亡问。
38.@synchronized
39.UIView setFrame方法
40.UIView的生命周期
41.delegate 作為屬性需要使用weak
delegate作為屬性需要是weak?
防止retain cycle循環(huán)引用...
比如tableview....UIViewCotroller通過self.view addsubview.已經(jīng)指向tableview了......所以tableview.delegate = self 和tableview.datasource又指向了viewcontroller,如果此時delegate是strong,就會發(fā)生循環(huán)引用無法釋放,所以這里應(yīng)該是weak.....
42.readonly
43.__unsafe_unretained
44.UIScrollView下沉64像素
在ViewController中
self.edgesForExtendedLayout = UIRectEdgeNone;
或
self.automaticallyAdjustsScrollViewInsets = NO;
45.bounds與frame的區(qū)別
46.獲取字符串寬度
[self.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]}].width]
47.約束
mas_makeConstraints && mas_remakeConstraints && mas_updateConstraints
48.謂詞(NSPredicate)
49.ViewController 和 xib關(guān)聯(lián)
1官紫、新建xxViewController 和 xib(xib 文件名與vc相同) ,并且設(shè)置xib 的 file’s owner 為xxViewController州藕,
2束世、Outlets中的view 跟xib中的view做關(guān)聯(lián),如果沒有這一步會報“l(fā)oaded the "xxxView" nib but the view outlet was not set.”
第一種方法:
CustomViewController* customViewController = [[CustomViewController alloc] initWithNibName:nil bundle:nil];
你可以看現(xiàn)第一個傳數(shù)是nil床玻, 對沒錯毁涉,傳nil也是可以的。因為如果系統(tǒng)發(fā)現(xiàn)是nil的話锈死,會在工程的bundle里找與CustomViewController同名的xib文件贫堰,因為模版生成的正好名字相同穆壕,所以能夠正確加載xib文件。
第二種方法:
CustomViewController* customViewController = [[CustomViewController alloc] init];
在這兒我們只是簡單的初始化其屏,也能正解加載相應(yīng)的xib文件粱檀,因為他們名字是相同的。
如果xib的名了與類的名字不同呢漫玄?
如果不同那么我們就不能用上面的兩種方法茄蚯,必須顯示指明xib的名字,如:
CustomViewController* customViewController = [[CustomViewController alloc] initWithNibName:"firstView" bundle:nil]
在這兒我們顯示指明是firstView.xib這個文件睦优。
50.枚舉
NS_ENUM定義通用枚舉渗常,NS_ENUM定義的枚舉不能幾個枚舉項同時存在,只能選擇其中一項汗盘,
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
SDWebImageDownloaderFIFOExecutionOrder,
SDWebImageDownloaderLIFOExecutionOrder
};
NS_OPTIONS定義位移枚舉
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
SDWebImageDownloaderLowPriority = 1 << 0,
SDWebImageDownloaderProgressiveDownload = 1 << 1,
SDWebImageDownloaderUseNSURLCache = 1 << 2,
SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
};
位移枚舉即是在你需要的地方可以同時存在多個枚舉值如這樣:
SDWebImageDownloaderOptions opt = SDWebImageDownloaderLowPriority | SDWebImageDownloaderIgnoreCachedResponse;
判斷的時候是這樣
if (options & SDWebImageDownloaderUseNSURLCache){}
51.多線程中的數(shù)據(jù)同步
dispatch_semaphore
GCD中信號量是dispatch_semaphore_t類型皱碘,支持信號通知和信號等待。每當發(fā)送一個信號通知隐孽,則信號量+1癌椿;每當發(fā)送一個等待信號時信號量-1,;如果信號量為0則信號會處于等待狀態(tài)菱阵,直到信號量大于0開始執(zhí)行踢俄。根據(jù)這個原理我們可以初始化一個信號量變量,默認信號量設(shè)置為1晴及,每當有線程進入“加鎖代碼”之后就調(diào)用信號等待命令(此時信號量為0)開始等待都办,此時其他線程無法進入,執(zhí)行完后發(fā)送信號通知(此時信號量為1)虑稼,其他線程開始進入執(zhí)行琳钉,如此一來就達到了線程同步目的。@synchronized
NSLock
52. initialize load
+(void)load 在程序運行后立即執(zhí)行
+(void)initialize 在類的方法第一次被調(diào)時執(zhí)行
53.__block與__weak區(qū)別
54. performSelector調(diào)用和直接調(diào)用區(qū)別
performSelector是運行時系統(tǒng)負責去找方法的蛛倦,在編譯時候不做任何校驗歌懒;如果直接調(diào)用編譯是會自動校驗。如果方法不存在溯壶,那么直接調(diào)用 在編譯時候就能夠發(fā)現(xiàn)(借助Xcode可以寫完就發(fā)現(xiàn))及皂,但是使用performSelector的話一定是在運行時候才能發(fā)現(xiàn)(此時程序崩潰);Cocoa支持在運行時向某個類添加方法茸塞,即方法編譯時不存在躲庄,但是運行時候存在查剖,這時候必然需要使用performSelector去調(diào)用钾虐。所以有時候如果使用了performSelector,為了程序的健壯性笋庄,會使用檢查方法
直接調(diào)用方法時候效扫,一定要在頭文件中聲明該方法的使用倔监,也要將頭文件import進來。而使用performSelector時候菌仁, 可以不用import頭文件包含方法的對象浩习,直接用performSelector調(diào)用即可。
55.@autoreleasepool
當需要在程序中創(chuàng)建大量的臨時變量時(大量也可指數(shù)量多济丘,不確定谱秽,比如從數(shù)據(jù)庫中讀取數(shù)據(jù)時),很容易使內(nèi)存產(chǎn)生峰值又回到內(nèi)存低谷,這樣對程序的性能會產(chǎn)生很大影響摹迷,而使用自動釋放池后疟赊,峰值明顯有所下降。
官方提出的解決方案是峡碉,在大量產(chǎn)生局部變量的位置用autoreleasepool代碼塊進行包裝近哟。比如for循環(huán)中要執(zhí)行的語句,這樣每次for循環(huán)結(jié)束后就會及時收回臨時變量占用的內(nèi)存空間鲫寄。
for (int i = 0; i < 10e6; ++i) {
@autoreleasepool {
NSString *str = [NSString stringWithFormat:@"hi + %d", i];
[collection addObject:str];
}
}
56.加載圖片的兩種方式
-imageNamed: 是讀取到內(nèi)存后會緩存下來吉执,下次再讀取時直接從緩存中獲取,因此訪問效率要比較高地来。對于圖片資源比較小戳玫,使用比較頻繁的圖片,通常會選擇使用此種方式來加載未斑。當然量九,若不需要考慮性能時,直接使用此種方式也是可以的颂碧。
-initWithContentsOfFile: 當圖片資源比較大荠列,或者圖片資源只使用一次就不再使用了,那么使用此種方式是最佳方式载城。當應(yīng)用程序需要加載一張比較大的圖片并且是一次性使用的肌似,那么是沒有必要去緩存這個圖片的,用-imageWithContentsOfFile:是最為經(jīng)濟的方式诉瓦,這樣不會因為UIImage元素較多情況下川队,CPU會被逐個分散在不必要的緩存上而浪費過多CPU時間。另外睬澡,當我們的圖片不是PNG圖片時固额,我們通常會選擇此種方式來加載。
SDWebImageDecoder引發(fā)的思考
57.NSData
58.NSCoding
59.屬性修飾符
- nullable
- @property(nonatomic,getter=isOn) BOOL on;
60.導(dǎo)航欄遮擋view問題
if (kCurrentFloatDevice > 7.0) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}