2016.07.04日更新:
因?yàn)榈谒墓?jié)課和第五節(jié)課內(nèi)容相似,故合并在一起,為了使學(xué)習(xí)總結(jié)的序號(hào)和課程的一致性,更正了標(biāo)題。
本節(jié)課講解了iOS框架里幾個(gè)重要的知識(shí)點(diǎn):動(dòng)態(tài)綁定,控制器的生命周期,屬性字符串等。最后演示了一個(gè)Demo用來(lái)講解屬性字符串的幾個(gè)功能。
動(dòng)態(tài)綁定
在OC的編譯期,所有的指針都是id類型,只有在運(yùn)行時(shí),對(duì)象的類型才會(huì)被確定。
舉個(gè)?? :
在編譯期,NSString* 實(shí)際上與id相同,但是加上去的好處是讓編譯器知道你至少是意圖讓該指針指向一個(gè)字符串。所以如果嘗試發(fā)送非字符串消息給該指針,它會(huì)發(fā)出警告,但是不會(huì)提示錯(cuò)誤,仍可以通過(guò)編譯。但是如果在運(yùn)行時(shí)就會(huì)“露餡”,因?yàn)榇藭r(shí)如果向該對(duì)象發(fā)送非字符串消息時(shí),就會(huì)引起崩潰。
再舉個(gè)具體的??:
NSString *hellow = @"hello";
Ship *hellowShip = (Ship *)hello;
[helloShip shoot];
編譯器會(huì)認(rèn)為
hellowShip是ship類型,因此向hellowShip發(fā)送shoot消息時(shí),在編譯器期是可以通過(guò)的。
但是,hellowShip實(shí)際上指向的是字符串,所以會(huì)導(dǎo)致在運(yùn)行時(shí)崩潰。
所以就引出了類型保護(hù)機(jī)制用來(lái)確定對(duì)象的類型:
類型保護(hù)機(jī)制
沒(méi)有添加類型保護(hù)機(jī)制:
PlayingCard *otherCard = [otherCards firstObject];
[otherCard play];
firstObject 方法返回的是id類型,這里需要保護(hù)機(jī)制確保取出的對(duì)象是
PlayingCard的實(shí)例,以防止向其發(fā)送消息時(shí)導(dǎo)致程序崩潰。
添加了類型保護(hù)機(jī)制:
PlayingCard *otherCard = [otherCards firstObject];
id card = [otherCards firstObjct];
if ([card isKindOfClass:[PlayingCard class]])
{
PlayingCard *otherCard = (PlaytingCard *)card;
[otherCard play];
}
我們可以看到
card指針通過(guò)isKindOfClass:方法被確認(rèn)了是PlayingCard類的實(shí)例,那么如果我們給card實(shí)例發(fā)送其消息時(shí),就不會(huì)發(fā)生崩潰。反之,若card是其他類的實(shí)例,如果向其發(fā)送card類的消息就會(huì)非常危險(xiǎn)!
NSRange
NSRange是一個(gè)表示“范圍”的結(jié)構(gòu)體,包括起點(diǎn)和長(zhǎng)度,主要用于字符串。
常用方法:
字符串所有的字符:
NSString *title = @"好好學(xué)習(xí)天天向上";
NSMakeRange(0, [title length])
判斷某個(gè)字符串里包含某個(gè)字符:
NSString *greeting = @"hellow world";
Nsstring *hi = @"hi";
NSRange r = [greeting rangeOfString:hi];
if(r.location != NSNotFound)
{
NSLog(@"Found");
}
控制器生命周期
在控制器(ViewController)的生命周期里,處于某個(gè)特定的時(shí)間點(diǎn)會(huì)執(zhí)行某個(gè)特定的方法。通過(guò)在這些方法里之行某些特定的任務(wù),可以正確地實(shí)現(xiàn)其應(yīng)實(shí)現(xiàn)的功能。
viewDidLoad
控制器的viewDidLoad方法在控制器的view為nil的時(shí)候被調(diào)用,在控制器的生命周期中只調(diào)用一次。
- (voidviewDidLoad
{
[super viewDidLoad];
//可執(zhí)行:
//1. 控制器的初始化數(shù)據(jù)
//2. 網(wǎng)絡(luò)請(qǐng)求
//不可執(zhí)行:
//1. 視圖形狀的初始化信息
}
viewWillAppear:
控制器的viewWillAppear:在UIViewController對(duì)象的視圖即將加入窗口時(shí)調(diào)用。只要該控制器的view即將要出現(xiàn),都會(huì)調(diào)用,在控制器的生命周期中可以調(diào)用多次。
而且,如果該方法被調(diào)用,就說(shuō)明視圖一定會(huì)出現(xiàn)在屏幕上。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//可執(zhí)行:
//1. 更新view離開(kāi)界面后可能會(huì)改變的數(shù)據(jù)。
//2. view的幾何變化。
}
viewWillDisappear:
控制器的viewWillDisappear:在UIViewController的view即將不顯示的時(shí)候調(diào)用,在控制器的生命周期中可以調(diào)用多次。
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//可執(zhí)行:
//1. 記錄滾動(dòng)視圖的偏移量(因?yàn)橐涀L動(dòng)位置,便于下次查看)
//2. 存儲(chǔ)數(shù)據(jù),便于再次顯示該控制器時(shí)使用。
}
屬性字符串Demo
設(shè)計(jì)需求
- 布局為TextView下方有四個(gè)顏色按鈕,再下方有添加輪廓按鈕和去除輪廓按鈕。
- 選中TextView的文本后,點(diǎn)擊色彩按鈕,選中的文本的顏色變成點(diǎn)擊的色彩按鈕的背景色。
- 選中TextView的文本后,點(diǎn)擊添加輪廓,選中的文本增加了輪廓,再點(diǎn)擊色彩按鈕,輪廓變成了相應(yīng)的顏色。
- 文本有輪廓的狀態(tài)下,點(diǎn)擊去除輪廓按鈕,輪廓消失。
- 在設(shè)置選項(xiàng)來(lái)改變系統(tǒng)字體,再回到本Demo界面,字體會(huì)做相應(yīng)改變。
效果圖

知識(shí)點(diǎn)詳解
屬性字符串的設(shè)置
屬性字符串分為不可變屬性字符串NSAttributedString和NSMutableAttributedString。
設(shè)置屬性字符串的一般步驟為:
- 初始化可變屬性字符串。
- 向其添加屬性字典和制定屬性字典被應(yīng)用的范圍。
舉個(gè)??:
//1. 由現(xiàn)有字符串初始化可變屬性字符串
NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:self.outLineButton.currentTitle];
//2. 添加屬性字典和范圍
[title setAttributes:@{NSStrokeWidthAttributeName : @3,
NSStrokeColorAttributeName : self.outLineButton.tintColor}
range: NSMakeRange(0, [title length])];
//3. 將屬性字符串賦給按鈕的屬性字符串屬性
[self.outLineButton setAttributedTitle:title forState:UIControlStateNormal];
//設(shè)定選中的字都被設(shè)置為和點(diǎn)擊的按鈕一樣的背景顏色
[self.textView.textStorage addAttribute:NSForegroundColorAttributeName value:sender.backgroundColor range:self.body.selectedRange];
關(guān)于按鈕的操作
//獲取按鈕的背景色
self.button.backgroundColor
//獲取按鈕當(dāng)前的標(biāo)題
self.button.currentTitle
//設(shè)定按鈕當(dāng)前的屬性字符串標(biāo)題
[self.button setAttributedTitle:title forState:UIControlStateNormal];
屬性字典里的key:
-
NSForegroundColorAttributeName:屬性字符串字符的顏色 -
NSStrokeColorAttributeName:屬性字符串字符輪廓的顏色 -
NSStrokeWidthAttributeName:屬性字符串字符輪廓的寬度
獲取TextView被選中的范圍
self.textView.selectedRange
通知機(jī)制
為了實(shí)現(xiàn)本Demo最后一個(gè)需求,我們需要監(jiān)聽(tīng)系統(tǒng)字體何時(shí)被改變了。所以需要注冊(cè)一個(gè)能收聽(tīng)“系統(tǒng)改變”廣播的頻道:
注冊(cè)通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(prefredFontsChaged:) name:UIContentSizeCategoryDidChangeNotification object:nil];
這樣一來(lái),當(dāng)系統(tǒng)字體發(fā)生變化時(shí),注冊(cè)該頻道的對(duì)象會(huì)收到通知并執(zhí)行自定義的方法。
當(dāng)改變系統(tǒng)字體的大小后,該類會(huì)收到通知,并調(diào)用prefredFontsChaged:方法,此時(shí)Demo上的字體也要做相應(yīng)的改變:
- (void)prefredFontsChaged: (NSNotification *)notification
{
//收到通知后,調(diào)用本地自定義的方法
[self userPreferredFonts];
}
- (void)userPreferredFonts
{
//使用被改變后的系統(tǒng)字體
self.body.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
self.headLine.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
}
這里,顯然又是一個(gè)MVC的流程:系統(tǒng)字體(模型)被改變了,通過(guò)廣播(通知)的機(jī)制來(lái)告訴控制器,然后控制器再調(diào)用更改View的方法。還記得在第一篇(詳情請(qǐng)見(jiàn):斯坦福大學(xué)iOS開(kāi)發(fā)公開(kāi)課總結(jié)(一) :iOS的MVC框架)里強(qiáng)調(diào)的,從模型到控制器的通信是通過(guò)廣播或KVO機(jī)制完成的么?
最后的話
如果哪位小伙伴想拿到此Demo的代碼請(qǐng)不要客氣,在評(píng)論里留言即可。
而且十分歡迎給筆者的代碼和文筆拋出寶貴的意見(jiàn)和建議~
本文為筆者原創(chuàng),如需轉(zhuǎn)載,請(qǐng)事先與筆者交涉~
2016.7.12日更新:
筆者已經(jīng)把目前為止整理的所有Demo(第二課到第十課)放入到了我的GitHub倉(cāng)庫(kù)里。分為英文注釋版和中文注釋版(英文注釋要少一點(diǎn),嘿嘿)想要的小伙伴可以果斷下載~ 如果有不知道怎么下載的小伙伴請(qǐng)聯(lián)系我~
本文已在版權(quán)印備案,如需轉(zhuǎn)載請(qǐng)?jiān)L問(wèn)版權(quán)印。48422928
-------------------------------- 2018年7月17日更新 --------------------------------
注意注意?。?!
筆者在近期開(kāi)通了個(gè)人公眾號(hào),主要分享編程,讀書(shū)筆記,思考類的文章。
- 編程類文章:包括筆者以前發(fā)布的精選技術(shù)文章,以及后續(xù)發(fā)布的技術(shù)文章(以原創(chuàng)為主),并且逐漸脫離 iOS 的內(nèi)容,將側(cè)重點(diǎn)會(huì)轉(zhuǎn)移到提高編程能力的方向上。
- 讀書(shū)筆記類文章:分享編程類,思考類,心理類,職場(chǎng)類書(shū)籍的讀書(shū)筆記。
- 思考類文章:分享筆者平時(shí)在技術(shù)上,生活上的思考。
因?yàn)楣娞?hào)每天發(fā)布的消息數(shù)有限制,所以到目前為止還沒(méi)有將所有過(guò)去的精選文章都發(fā)布在公眾號(hào)上,后續(xù)會(huì)逐步發(fā)布的。
而且因?yàn)楦鞔蟛┛推脚_(tái)的各種限制,后面還會(huì)在公眾號(hào)上發(fā)布一些短小精干,以小見(jiàn)大的干貨文章哦~
掃下方的公眾號(hào)二維碼并點(diǎn)擊關(guān)注,期待與您的共同成長(zhǎng)~
