1.appearance
用appearance拿到對象,然后用拿到的對象設置被appearance注釋()的屬性,就會使整個項目的這種控件都變為設置的樣子,例如:
UISwitch *switch = [UISwitch appearance];
switch.onTintColor = [UIColor redColor];
這樣設置就會使整個項目的switch控件開啟顏色變為紅色
注意:如果該控件已經顯示出來,則設置無效,要想設置有效需要將整個父控件移除,然后再加回去.
2.隱藏宏
在Build Settings中搜索DEBUG,在Debug那一欄中添加宏,這樣就可以在項目中使用該宏,但無法找到宏的詳細內容
注意:宏命名的時候不能全是小寫字母,至少有一個大寫字母或至少有一個數字
3.只執行一次的操作
如果代碼塊想在程序中只執行一次,可以用dispatch_once或者懶加載
4.tabBar
需求:在tabBar中央加一個按鈕
解決思想:重寫tabBar,在layoutSubview方法中,重新布局系統自帶的按鈕(UITabBarButton,系統私有類),在中央空出一塊地方,然后添加按鈕
1.cell之間分割線(重寫setFrame方法)
思路:
在cell原有的高度下減1,這樣就可以實現不用添加View就有分割線,且分割線和背景色一樣
具體實現:
由于cell的重復利用機制,所以在設置的時候改是無法實現的,但是每次重用cell的時候都會調用cell的setFrame方法,所以在自定義cell中重寫setFrame方法,并且在調用[super setFrame]之前,將高度減1,這樣就可以實現不添加View就有分割線這一需求.不光如此,還可以設置左右邊距,將x加1,將width減2.
擴展:
我們自己封裝的控件,不想在外界被人修改size,可以在[super setFrame]之前設置一個固定的size,但是bounds也會修改size,所以也要重寫setBounds方法
2.網絡請求的成功和失敗
當域名錯誤時,請求就會失敗;當域名正確但參數錯誤時,請求返回的數據依然是成功的,只是返回一個空數據,所以在請求成功的block塊中也要進行一次判斷,判斷返回數據是否為空
3.網絡請求延時
在網絡請求時,為提高用戶體驗,在屏幕中央添加一個蒙版,提示用戶正在網絡請求.但有時網絡請求延時很高,以防引起用戶不耐,所以在請求時,用戶隨時可以點擊返回按鈕退出界面,并且在dealloc中移除蒙版.但是block中強引用控制器,造成控制器無法銷毀,造成在退出界面后,蒙版依然存在這種情況
解決方案:不要讓block強引用控制器(在block塊中不使用self),或者將self包裝成弱指針:
__weak typeof(self) weakSelf = self;
但是還有問題,以AFNetworking為例,由于網絡管理者在內部被強引用,所以在控制器銷毀的時候,依然在進行網絡請求.
解決方法1:用weak類型的屬性引用網絡管理者,在銷毀控制器的時候調用:
[self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];
這個方法的意思:取消所有正在網絡請求的任務,執行這個方法之后,管理者依然可用.
解決方法2:依然是用weak類型屬性醫用網絡管理者,在銷毀控制器的時候調用:
[self.manager invalidateSessionCancelingTasks:YES];
這個方法的意思:使session停止請求,執行這個方法之后,session銷毀,管理者和session是一對一的,導致管理者不能用.
但是還有問題!取消任務也被認為是請求失敗,會執行請求失敗的block代碼塊,所以在退出界面后彈出一個請求失敗的彈框,所以要在請求失敗的block代碼塊中判斷error的錯誤代碼,取消請求的錯誤代碼是:NSURLErrorCancelled(-999)
4.weak和IBOutlet
被weak引用的屬性,當沒有強指針指向屬性時,屬性會立即銷毀;如果被weak引用的屬性有IBOutlet修飾時,并不會被馬上銷毀,而是在代碼塊過后銷毀,因為在IBOutlet內部有個隱藏的強指針引用著.
5.layer(圖層)
layer是一個相對耗時的操作,會造成卡頓,盡量少使用layer
6.const和宏
宏相對比較消耗性能
const只是拿常量的值使用,性能較好,但是const只能修飾常量,不能修飾方法和編譯之前不確定的值.const修飾右邊的內容,例如:
NSString *const name = @"wbw"; 表示不能修改指針的指向
NSString const *name = @"wbw"; 表示不能修改指針指向的內容地址的值
7.常量書寫規范
僅限文本件使用的不可變全局變量,要加上:static和const,例如:
static NSString *const name = @"wbw";
整個項目都可以使用的不可變全局變量,創建一個.h和.m文件,在.m文件中創建被const修飾的變量(例如: NSString *const name = @"wbw";),在.h文件中聲明(例如: UIKIT_EXTERN NSString *const name;),在.pch文件中導入.h文件
注:UIKIT_EXTERN就是extern,蘋果內部包裝了一層,可能內部有所優化
8.控件不能響應點擊事件,原因可能有
1.userInteractionEnabled = NO;
2.enabled = NO;
3.父控件的userInteractionEnabled = NO;
4.父控件的enabled = NO;
5.控件已超出父控件的邊框范圍
9.自定義tableView的footerView
先將tableView的footerView替換成自定義的footerView,然后設置自定義footerView的高度時,發現設置高度無效,而自定義footerView的高度又必須根據子控件而變化,解決方法:
1.在計算完子控件高度后,將自定義footerView重新設置為tableView的footerView:
UITableView *tableView = (UITableView *)self.superView;
tableView.tableFooterView = self;
2.根據公式計算出行數,行數*子控件的高度,設置tableView的contentSize
計算行數的公式: 總行數 = (總個數 + 每行的個數 - 1) / 每行的個數
10.webView加載網頁
加載網頁需要從模型中拿URL時,不能在set方法中加載網頁,因為此時的webView是空的,set方法先調用,viewDidLoad后調用,必須在viewDidLoad里面加載網頁
11.清除緩存
步驟1.拿到手機緩存的數據大小:
方法1:使用SDWebImage框架中的SDImageCache.h
[SDImageCache sharedImageCache].getSize
注意:只能計算用SDWebImage下載的圖片所在文件夾的大小
方法2:用文件管理者遍歷拿到所有子文件
//總大小
NSInteger size = 0;
//文件路徑
NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSString *file = [cache stringByAppendingPathComponent:@"default"];
//路徑管理者
NSFileManager *manager = [NSFileManager defaultManager];
//遍歷拿到所有的子路徑(包括子路徑的子路徑)
NSArray *subpaths = [manager subpathsAtPath:file];
//遍歷子路徑
for (NSString *subpath in subpaths) {
//根據子路徑拼接出全路徑
NSString *fullSubpath = [file stringByAppendingPathComponent:subpath];
//文件的所有屬性
NSDictionary *attrs = [manager attributesOfItemAtPath:fullSubpath error:nil];
//將文件的大小加到總大小上
size += [attrs[NSFileSize] integerValue];
}
方法3:NSDirectoryEnumerator(迭代器)遍歷路徑的所有子文件
方法3:
//總大小
NSInteger size = 0;
//文件路徑
NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSString *file = [cache stringByAppendingPathComponent:@"default"];
//路徑管理者
NSFileManager *manager = [NSFileManager defaultManager];
//遍歷路徑下的所有子文件
NSDirectoryEnumerator *enumerator = [manager enumeratorAtPath:file];
//遍歷enumerator(類似于數組)
for (NSString *subpath in enumerator) {
//根據子路徑拼接出全路徑
NSString *fullSubpath = [file stringByAppendingPathComponent:subpath];
//文件的所有屬性
NSDictionary *attrs = [manager attributesOfItemAtPath:fullSubpath error:nil];
//將文件的大小加到總大小上
size += [attrs[NSFileSize] integerValue];
}
步驟2:刪除文件夾
[[NSFileManager defaultManager] removeItemAtPath:@"路徑" error:nil];
*注意點
1.由于遍歷比較耗時,所以要開啟新的線程用來計算文件的大小
2.為嚴謹起見,要判斷路徑是否存在,而且要判斷路徑是否是文件夾
//判斷是否是文件夾
BOOL isDirectory = NO;
//判斷路徑是否存在
BOOL exists = [manager fileExistsAtPath:@"路徑" isDirectory:&isDirectory];
//如果是文件,就直接計算大小
if (isDirectory == NO) {
[manager attributesOfItemAtPath:@"路徑" error:nil].fileSize;
}
3.在計算的時候應該禁止用戶點擊cell,待計算完畢之后,恢復點擊
cell.userInteractionEnabled;
12.tableView的行被選中后,馬上彈起(其實就是取消選中)
調用選中時的代理方法(didSelectRowAtIndexPath),在方法內部調用:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
13.不同標識的cell
當眾多cell中有個別特殊的cell時,在循環利用的時候會引起混亂
解決的辦法:可以設置多個標識,注冊不同的cell,每次循環利用的時候,對應行只加載對應標識的cell
14.正在執行動畫的控件移出再回來后,恢復動畫
當正在執行動畫的cell被移出界面,再重新利用回來后,動畫不再執行
解決的辦法:拿到執行動畫的控件,再次開啟動畫
15.layoutIfNeeded,setNeedsLayout,setNeedsDisplay的區別**
//重新刷新自己和子控件的所有內容(狀態,尺寸)
[testView layoutIfNeeded];
//重新調用testView的layoutSubviews(重新排布子控件的frame)
[testView setNeedsLayout];
//重新調用testView的drawRect:方法(重新繪制testView里面的內容,一般不包括子控件)
[testView setNeedsDisplay];
- HTTP/1.1協議中共定義了八種方法(有時也叫“動作”)來表明Request-URI指定的資源的不同操作
方式:
OPTIONS 返回服務器針對特定資源所支持的HTTP請求方法。也可以利用向Web服務器發送'*'的請求來測試服務器的功能性。
HEAD 向服務器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以在不必傳輸整個響應內容的情況下,就可以獲取包含在響應消息頭中的元信息。
GET 向特定的資源發出請求。注意:GET方法不應當被用于產生“副作用”的操作中,例如在web app.中。其中一個原因是GET可能會被網絡蜘蛛等隨意訪問。
POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。
PUT 向指定資源位置上傳其最新內容。
DELETE 請求服務器刪除Request-URI所標識的資源。
TRACE 回顯服務器收到的請求,主要用于測試或診斷。
CONNECT HTTP/1.1協議中預留給能夠將連接改為管道方式的代理服務器。