記錄一點點小問題處理
xcode調試在release模式下,控制臺不打印信息問題:
debug模式不要調整,自動可以po出屬性。release模式將building setting -> Optimization Level ->release 條件由Fastest, Smallest[-Os] 改成 None[-Oo].
發布版本的時候,記得改回來,倒數第二個哦。
1.一般我們進行刷新的下拉時候,都會先清掉數據源,在重新請求數據,加載數據源; 這時候你要直接就將數據清掉,可能會引起crash。因為你在清掉數據源,視圖還在,內部調用方法就crash了。這時候要先請求數據,確認數據請求到了,在清掉原來的數據,在加載新的數據源。
But t t t ——有的場景就不能這么處理,還沒有load到新數據之前,就必須要把舊的數據源清掉。這樣很容易導致crash;
我的處理方法是:在清掉數據源之后,緊接著刷新一下視圖;
[self.tableView reloadData]
。這樣就不會引起crash,具體為什么是這樣,我也不是很清楚,可能relaodData 方法內部進行什么處理了吧。。誰知道或是有更好的辦法求告知,感激不盡!!
2.當cell上有動畫時,一定要注意動畫完成的block與刷新數據方法的調用順序。
當你刷新數據方法在動畫完成block之前調用了,就可能會出現異常。
解決辦法:用GCD,確保方法的執行順序,block完成之后在調用數據刷新;添加到隊列里的方法,會按著添加的順序執行(FIFO),這樣就能保證了調用順序。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Do Something });
這么寫可能不太理解,反正就是要注意動畫完成的block之后在刷新數據。如果不能保證這樣的執行順序,就不要在動畫完成那里在處理一些你想做的視圖更新操作。
3.關于tableView的使用和代理方法
tableView的plain類型,sectionHead 會有懸停效果;grouped類型,不會懸停。
直接用這個方法設置頭視圖
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return @"Title"; }
當是plain類型時,顯示正確;當是grouped類型時,會強制轉成大寫“TITLE”。中文沒有影響。
//響應點擊索引時的委托方法
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
設置索引的時候,這個代理方法設置點擊索引跳轉的位置。默認不寫或是直接return index
,系統會自動關聯索引,自己實現這個代理方法可能還出錯呢,建議不要實現這個方法。
//修改索引字體
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
//修改索引顏色
// tableView.sectionIndexBackgroundColor = [UIColor greenColor];//修改右邊索引的背景色
tableView.sectionIndexColor = kMainColor;//修改右邊索引字體的顏色
// tableView.sectionIndexTrackingBackgroundColor = [UIColor orangeColor];//修改右邊索引點擊時候的背景色
return self.headerTitles;
}
設置sectionHeadView
在設置header和footer信息的時候,View的優先級高于titile。即使你寫了title代理方法,但是你實現了headView代理方法,這是title代理方法- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
無效。
sectionHead或footView 都要注意復用,提高效率,而且還可以在相應的代理方法中改變其屬性
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { UITableViewHeaderFooterView *vi = (UITableViewHeaderFooterView *)view; vi.textLabel.textColor = [UIColor redColor];//這時候已經拿到了headView 隨意更改它的屬性 }
4.UITableViewDelegate(tableView代理方法)
cell將要顯示時調用的方法
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
頭視圖將要顯示時調用的方法
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section;
尾視圖將要顯示時調用的方法
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section;
和上面的方法對應,這三個方法分別是cell,頭視圖,尾視圖已經顯示時調用的方法
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath;
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section;
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section;
設置自定義頭視圖和尾視圖
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
5.尋找第一響應者
實際開發中,經常用到第一響應者,做一些特別的操作。有時候還不太好找,用Apple 這個public API,當target是nil的時候,就會直接拿到第一響應者。
- (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event
什么意思呢?
The object to receive the action message. If target is nil, the app sends the message to the first responder, from whence it progresses up the responder chain until it is handled.
第一響應者也參考這個文章
6.iOS定時器——GCD定時器
//系統自帶里這個快捷創建方式(dispatch_source),只需要設置一個queue即可。
- (dispatch_source_t)createGCDTimer {
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
//定時器開始回調
});
dispatch_resume(timer);
return timer;
}
***********分步創建*****************
//0.創建一個隊列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//1.創建一個GCD的定時器
/*
第一個參數:說明這是一個定時器
第四個參數:GCD的回調任務添加到那個隊列中執行,如果是主隊列則在主線程執行
*/
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//2.設置定時器的開始時間,間隔時間以及精準度
//設置開始時間,三秒鐘之后調用
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW,3.0 *NSEC_PER_SEC);
//設置定時器工作的間隔時間
uint64_t intevel = 1.0 * NSEC_PER_SEC;
/*
第一個參數:要給哪個定時器設置
第二個參數:定時器的開始時間DISPATCH_TIME_NOW表示從當前開始
第三個參數:定時器調用方法的間隔時間
第四個參數:定時器的精準度,如果傳0則表示采用最精準的方式計算,如果傳大于0的數值,則表示該定時切換i可以接收該值范圍內的誤差,通常傳0
該參數的意義:可以適當的提高程序的性能
注意點:GCD定時器中的時間以納秒為單位(面試)
*/
dispatch_source_set_timer(timer, start, intevel, 0 * NSEC_PER_SEC);
//3.設置定時器開啟后回調的方法
/*
第一個參數:要給哪個定時器設置
第二個參數:回調block
*/
dispatch_source_set_event_handler(timer, ^{
NSLog(@"------%@",[NSThread currentThread]);
});
//4.執行定時器
dispatch_resume(timer);
//注意:dispatch_source_t本質上是OC類,在這里是個局部變量,需要強引用
self.timer = timer;
7.給字符串里的某些指定字符串設置富文本
NSString *marketPriceStr = [NSString stringWithFormat:@"¥%.2f", product.marketPrice];
NSString *showStr = [NSString stringWithFormat:@"¥%.2f %@", product.goodsPrice, marketPriceStr];
//先拿到要設置富文本字符串的位置 這里就是給showStr字符串里的marketPriceStr這些字設置富文本
NSRange range = [showStr rangeOfString:marketPriceStr options:NSBackwardsSearch];
//設置你想要的富文本
NSDictionary *attr = @{
NSFontAttributeName : [UIFont systemFontOfSize:12],
NSStrikethroughStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid),
NSStrikethroughColorAttributeName : [UIColor colorWithRed:230 / 255.0f green:23 / 255.0f blue:115 / 255.0f alpha:1]
};
//然后添加富文本 在這個找到的特殊位置
[showAttrStr addAttributes:attr range:range];
8.關于iOS通知機制NSNotificationCenter
通知在iOS開發中很常用,用于多個界面的傳值響應等,可以一對多傳遞。使用唯一注意一點的是:要先addObserver,在postNotificationName通知。 這個就要注意一下順序了。 只有addObserver這個界面先出現,在出現postNotification這個界面,當你切換到發通知這個界面時,前面添加接收通知的界面才會響應通知內容。。。這里要注意的就是這個順序問題
9.KVO 使用
使用不多說,就說一個地方要注意:Keypath的命名不是隨便的,要用你要監聽的那個屬性命名,不能錯。 而且,屬性值發生變化自動調用KVO的前提是:屬性必須調用了setter、getter方法或是KVC方法。 直接_name = "newName"是不可以的。
10.webView獲取js的meta內容
//js的標簽內容
<meta name="attach_title" content="">
<meta name="attach_url" content="">
//UIWebView獲取方法
NSString *js = @"document.getElementsByName(\"attach_title\")[0].content";
NSString *attach_title = [self.webView stringByEvaluatingJavaScriptFromString:js];
js = @"document.getElementsByName(\"attach_url\")[0].content";
NSString *attach_url = [self.webView stringByEvaluatingJavaScriptFromString:js];
//WKWebView的獲取方法
- (void)getWKwebViewCenterDic {
WEAKSELF;
[self.wkWebView evaluateJavaScript:@"document.getElementsByName(\"attach_title\")[0].content" completionHandler:^(id result, NSError * _Nullable error) {
NSString *attach_title = @"";
if ([result isKindOfClass:[NSString class]]) {
attach_title = result;
}
[weakSelf getWebViewJSResult:@{@"title" : attach_title}];
}];
[self.wkWebView evaluateJavaScript:@"document.getElementsByName(\"attach_url\")[0].content" completionHandler:^(id result, NSError * _Nullable error) {
NSString *attach_url = @"";
if ([result isKindOfClass:[NSString class]]) {
attach_url = result;
}
[weakSelf getWebViewJSResult:@{@"url" : attach_url}];
}];
}
iOS 保持界面流暢的技巧
暫時就這么多,隨時發現隨時記錄更新。