兩年iOS經(jīng)驗(yàn)之你忽略的小知識(shí)點(diǎn)

1.子視圖超出frame的部分不顯示? view.clipsToBounds 設(shè)置為YES;? ?UIScrollview的clipsToBounds默認(rèn)就是YES

2.UIImage 有一個(gè)屬性叫size 。? 當(dāng)為對(duì)象Image賦值一張圖片以后,Image會(huì)自動(dòng)生成一個(gè)size。 那么也就是說你可以用image.size.height或者image.size.width來設(shè)置其父視圖的size。即:

UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageWithName:@"text.png"]];??

這樣不用給定frame 系統(tǒng)也可以顯示出帶圖片大小的ImageView。

3.contentOffset 表示UIScrollView滾動(dòng)的位置。(其實(shí)就是內(nèi)容視圖左上角與scrollView顯示視圖左上角的間距值)

4.?contentInset?(UIEdgeInsets結(jié)構(gòu)體類型 )這個(gè)屬性能夠在UIScrollView的四周增加額外的滾動(dòng)區(qū)域,一般用來避免scrollView的內(nèi)容被其他控件擋住。

5.UIView漸變動(dòng)畫有三種:(UI控件屬性被修改)

[UIView animateWithDuration:0.1 animations:^{

? ? ?//需要?jiǎng)赢嫷膬?nèi)容?

? ? ? self.imageView.frame = CGRectMake(20, 20, 30, 20);//e.g? ? ?

?}];

[UIView beginAnimations:nil context:nil];? ?

[UIView setAnimationDuration:2.0f];//修改動(dòng)畫持續(xù)時(shí)間

? ? ? //? ?需要做動(dòng)畫的內(nèi)容

? ? ?self.imageView.frame = CGRectMake(20, 20, 30, 20);//e.g

[UIView commitAnimations];


[UIView transitionWithView:noteView duration:0.6 // 在noteView視圖上設(shè)置過渡效果? options:UIViewAnimationOptionTransitionCurlUp? animations:^{?

? ? ?NSString *currentText = noteView.text;

? ? ? noteView.text = nextText;

? ? ?self.nextText = currentText;?

}? completion:^(BOOL finished){

}];

6.OC語法細(xì)節(jié):不允許直接修改OC對(duì)象的結(jié)構(gòu)體屬性的成員


修改結(jié)構(gòu)體


7.圖片縮放不止可以用手勢,也可以用ScrollView


利用ScollerView縮放控件

順便提一句,viewForZoomingInScrollView不僅僅可以縮放圖片,只要是繼承自UIIView的控件都可以進(jìn)行縮放

8.NSArray? 有一個(gè)方法讓所有對(duì)象都執(zhí)行某個(gè)方法

[self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

后邊的方法可以自定義,也可以用系統(tǒng)的。

當(dāng)然類似東西都用for - in? 了,如果在循環(huán)中用的是系統(tǒng)的一些操作、方法。不妨試試上邊這個(gè)方法。

9.從Xib、Storybord加載控件執(zhí)行方法順序

- initWithCoder:aCoder? ?作用是將xib的控件通過aCoder解析器創(chuàng)建所有子控件,通過IBOutlet 連接的屬性在這個(gè)方法里邊值是null。走了initWithCoder? 就不會(huì)走initWithFrame。

- awakeFormNib? 是將凍結(jié)的nib控件喚醒,即所有子控件創(chuàng)建完畢后就會(huì)調(diào)用這個(gè)方法,在這個(gè)地方IBOutlet連接的屬性才會(huì)真正的有值,所以修改nib控件的屬性值應(yīng)該在這個(gè)方法或者運(yùn)行過程之后的方法。

10.為什么 iOS 開發(fā)中,控件一般為 weak 而不是 strong?

IBOutlet的屬性一般可以設(shè)為weak是因?yàn)樗呀?jīng)被view引用了,除非view被釋放,否則IBOutlet的屬性也不會(huì)被釋放,另外IBOutlet屬性的生命周期和view應(yīng)該是一致的,所以IBOutlet屬性一般設(shè)為weak。

通俗點(diǎn)講:

因?yàn)榭丶? view.superview )已經(jīng)揪著它的小辮了( strong reference ),你( viewController )眼瞅著( weak reference )就好了。當(dāng)然,如果你想在 view 從 superview 里面 remove 掉之后還繼續(xù)持有的話,還是要用 strong 的( 你也揪著它的小辮, 這樣如果他爹松手了它也跑不了 )。

11、用NSLayoutConstrain給控件做了約束以后,如何執(zhí)行一定的UIView動(dòng)畫呢?

// 高度約束,為了點(diǎn)擊方法可以改變??

@property (nonatomic, strong) NSLayoutConstraint? ? *heightConstraint;

//在修改了約束以后,只要執(zhí)行下邊的代碼,就能做動(dòng)畫效果? ?

[UIView animateWithDuration:2.0 animations:^{

? ? ? ? [添加了約束的View? ? layoutIfNeeded];? ?

}];

12、關(guān)于TableView的[-?tableView: heightForRowAtIndexPath:]和[ -tableView: cellForRowAtIndexPath:? ]歷史版本調(diào)用順序的變遷

iOS? 7及之前:?

?先依次調(diào)一遍heightForRow方法再依次調(diào)一遍cellForRow方法,在調(diào)cellForRow方法的時(shí)候并不會(huì)再調(diào)一次對(duì)應(yīng)的heightForRow方法。如果我們實(shí)現(xiàn)了:【-tableView: estimatedHeightForRowAtIndexPath:】給了系統(tǒng)估計(jì)高度,那么上述兩個(gè)方法的執(zhí)行順序就會(huì)顛倒。并且給定估計(jì)高度對(duì)于TableView的性能方面也提示不少。

iOS8? :

先依次調(diào)heightForRow(如果行數(shù)超過屏幕依次調(diào)用兩次,如果行數(shù)很少,沒有超過屏幕,只依次調(diào)用一次),之后每調(diào)一次cellForRow的時(shí)候又調(diào)一次對(duì)應(yīng)的heightForRow方法。

iOS9和iOS10:

heightForRow方法會(huì)先調(diào)用三次,然后每調(diào)用一次cellForRow的時(shí)候再調(diào)用一次對(duì)應(yīng)的heightForRow。

iOS 11 :

?先row = 0調(diào)用一次 cellForRow,然后一次heightForRow.然后再是row =1 ,依次類推。看打印結(jié)果

iOS11圖片

PS:本次更新感謝小C醬油醋?的留言。并且關(guān)于歷史版本驗(yàn)證截圖請(qǐng)查看博客關(guān)于heightForRow和cellForRow方法的調(diào)用次數(shù)和順序的系統(tǒng)差異性

13、LayoutIfNeeded小理解

這個(gè)方法和另一個(gè)方法配對(duì)的,setNeedLayout和layoutIfNeed,還有一個(gè)關(guān)聯(lián)的方法是layoutSubviews,在我們沒有任何干預(yù)的情況下,一個(gè)view的fram或bounds發(fā)生變化時(shí),系統(tǒng)會(huì)設(shè)置一個(gè)flag給這個(gè)view,當(dāng)下一個(gè)渲染時(shí)機(jī)到來時(shí)系統(tǒng)會(huì)重新按新的布局來渲染視圖。setNeedLayout就是我們主動(dòng)為這個(gè)視圖設(shè)置一個(gè)flag,告訴系統(tǒng)這個(gè)視圖再下一個(gè)時(shí)機(jī)到來時(shí)要重新渲染,而layoutIfNeed則是告訴系統(tǒng),如果設(shè)置了flag那么不用等待時(shí)機(jī)到來了,直接渲染吧。而layoutSubviews這個(gè)方法是系統(tǒng)調(diào)用的,我們不需要主動(dòng)調(diào)用,我們只需要調(diào)用layoutIfNeed就可以了,讓系統(tǒng)判斷是否在當(dāng)前時(shí)機(jī)下立即渲染。

另同時(shí)附上一個(gè)場景舉個(gè)例,當(dāng)想知道tableView reloadData后的contentSize的話可以在reloadData后用這兩個(gè)方法,然后就可以直接提取contentSize了。

14、UILabel.preferredMaxLayoutWidth屬性

?-?設(shè)置label每一行文字的最大寬度

這個(gè)屬性建立在autoLayout布局的label中,如果是非零,那么這個(gè)屬性用于多行Label的文字固定寬度

15、iOS NSLog去掉時(shí)間戳及其他輸出樣式

加宏定義

#ifdef DEBUG

#define NSLog(FORMAT, ...) fprintf(stderr,"%s\n",[[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);

#else

#define NSLog(...)

#endif


16、UITableView點(diǎn)擊一下就出現(xiàn)灰色但是立馬消失掉。

點(diǎn)擊那一刻可以指示出點(diǎn)擊了哪一行,灰色停留一秒鐘消失掉。

//1.設(shè)置cell點(diǎn)擊時(shí)候?yàn)榛疑?/p>

cell.selectionStyle?=?UITableViewCellSelectionStyleGray;??

//2.在tableView代理方法didSelectedRow方法這樣寫

- (void)tableView:(UITableView *)tableView didSelecteRowAtIndexPath:(NSIndexPath *)indexPath{

? ? ? [ tableView deselectRowAtIndexPath:indexPath animated:YES];//直接取消選中這一行

}


更新記錄:

2018-04-28更新:第12條關(guān)于tableView的執(zhí)行調(diào)用順序機(jī)制。

2018-05-17更新:

第二條-:imageWithImage:應(yīng)該傳一個(gè)圖片對(duì)象而不是一個(gè)字符串。

第三條:將類型UIEdgeInsets 改成屬性contentOffset

2018-08-02:調(diào)整樣式 技術(shù)點(diǎn)無改動(dòng)


獲取筆者更多記錄小知識(shí)點(diǎn),請(qǐng)點(diǎn)擊三年經(jīng)驗(yàn)之你忽略的小知識(shí)點(diǎn)




如果您有什么疑問或者書寫歧義,非常感激您能留言~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容