2016.07.04日更新:
因為第四節(jié)課和第五節(jié)課內(nèi)容相似既忆,故合并在一起漱凝,為了使學(xué)習(xí)總結(jié)的序號和課程的一致性吼肥,更正了標(biāo)題乌叶。
本節(jié)課講解了iOS框架里幾個重要的知識點:動態(tài)綁定跷敬,控制器的生命周期讯私,屬性字符串等。最后演示了一個Demo用來講解屬性字符串的幾個功能西傀。
動態(tài)綁定
在OC的編譯期斤寇,所有的指針都是id類型,只有在運行時拥褂,對象的類型才會被確定娘锁。
舉個?? :
在編譯期,NSString*
實際上與id相同饺鹃,但是加上去的好處是讓編譯器知道你至少是意圖讓該指針指向一個字符串致盟。所以如果嘗試發(fā)送非字符串消息給該指針,它會發(fā)出警告尤慰,但是不會提示錯誤馏锡,仍可以通過編譯。但是如果在運行時就會“露餡”伟端,因為此時如果向該對象發(fā)送非字符串消息時杯道,就會引起崩潰。
再舉個具體的??:
NSString *hellow = @"hello";
Ship *hellowShip = (Ship *)hello;
[helloShip shoot];
編譯器會認(rèn)為
hellowShip
是ship
類型,因此向hellowShip
發(fā)送shoot
消息時党巾,在編譯器期是可以通過的萎庭。
但是,hellowShip
實際上指向的是字符串齿拂,所以會導(dǎo)致在運行時崩潰驳规。
所以就引出了類型保護(hù)機制用來確定對象的類型:
類型保護(hù)機制
沒有添加類型保護(hù)機制:
PlayingCard *otherCard = [otherCards firstObject];
[otherCard play];
firstObject 方法返回的是id類型,這里需要保護(hù)機制確保取出的對象是
PlayingCard
的實例署海,以防止向其發(fā)送消息時導(dǎo)致程序崩潰吗购。
添加了類型保護(hù)機制:
PlayingCard *otherCard = [otherCards firstObject];
id card = [otherCards firstObjct];
if ([card isKindOfClass:[PlayingCard class]])
{
PlayingCard *otherCard = (PlaytingCard *)card;
[otherCard play];
}
我們可以看到
card
指針通過isKindOfClass:
方法被確認(rèn)了是PlayingCard
類的實例,那么如果我們給card
實例發(fā)送其消息時砸狞,就不會發(fā)生崩潰捻勉。反之刀森,若card
是其他類的實例踱启,如果向其發(fā)送card
類的消息就會非常危險研底!
NSRange
NSRange是一個表示“范圍”的結(jié)構(gòu)體,包括起點和長度,主要用于字符串榜晦。
常用方法:
字符串所有的字符:
NSString *title = @"好好學(xué)習(xí)天天向上";
NSMakeRange(0, [title length])
判斷某個字符串里包含某個字符:
NSString *greeting = @"hellow world";
Nsstring *hi = @"hi";
NSRange r = [greeting rangeOfString:hi];
if(r.location != NSNotFound)
{
NSLog(@"Found");
}
控制器生命周期
在控制器(ViewController)的生命周期里胚想,處于某個特定的時間點會執(zhí)行某個特定的方法芽隆。通過在這些方法里之行某些特定的任務(wù)统屈,可以正確地實現(xiàn)其應(yīng)實現(xiàn)的功能胚吁。
viewDidLoad
控制器的viewDidLoad
方法在控制器的view為nil的時候被調(diào)用,在控制器的生命周期中只調(diào)用一次愁憔。
- (voidviewDidLoad
{
[super viewDidLoad];
//可執(zhí)行:
//1. 控制器的初始化數(shù)據(jù)
//2. 網(wǎng)絡(luò)請求
//不可執(zhí)行:
//1. 視圖形狀的初始化信息
}
viewWillAppear:
控制器的viewWillAppear:
在UIViewController對象的視圖即將加入窗口時調(diào)用腕扶。只要該控制器的view即將要出現(xiàn)吨掌,都會調(diào)用,在控制器的生命周期中可以調(diào)用多次膜宋。
而且,如果該方法被調(diào)用史简,就說明視圖一定會出現(xiàn)在屏幕上肛著。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//可執(zhí)行:
//1. 更新view離開界面后可能會改變的數(shù)據(jù)跺讯。
//2. view的幾何變化殉农。
}
viewWillDisappear:
控制器的viewWillDisappear:
在UIViewController的view即將不顯示的時候調(diào)用,在控制器的生命周期中可以調(diào)用多次超凳。
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//可執(zhí)行:
//1. 記錄滾動視圖的偏移量(因為要記住滾動位置聪建,便于下次查看)
//2. 存儲數(shù)據(jù),便于再次顯示該控制器時使用金麸。
}
屬性字符串Demo
設(shè)計需求
- 布局為TextView下方有四個顏色按鈕,再下方有添加輪廓按鈕和去除輪廓按鈕揍魂。
- 選中TextView的文本后棚瘟,點擊色彩按鈕,選中的文本的顏色變成點擊的色彩按鈕的背景色偎蘸。
- 選中TextView的文本后,點擊添加輪廓限书,選中的文本增加了輪廓章咧,再點擊色彩按鈕,輪廓變成了相應(yīng)的顏色赁严。
- 文本有輪廓的狀態(tài)下,點擊去除輪廓按鈕卤档,輪廓消失程剥。
- 在設(shè)置選項來改變系統(tǒng)字體,再回到本Demo界面,字體會做相應(yīng)改變茎活。
效果圖
知識點詳解
屬性字符串的設(shè)置
屬性字符串分為不可變屬性字符串NSAttributedString
和NSMutableAttributedString
琢唾。
設(shè)置屬性字符串的一般步驟為:
- 初始化可變屬性字符串。
- 向其添加屬性字典和制定屬性字典被應(yīng)用的范圍懒熙。
舉個??:
//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è)置為和點擊的按鈕一樣的背景顏色
[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
通知機制
為了實現(xiàn)本Demo最后一個需求工扎,我們需要監(jiān)聽系統(tǒng)字體何時被改變了衔蹲。所以需要注冊一個能收聽“系統(tǒng)改變”廣播的頻道:
注冊通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(prefredFontsChaged:) name:UIContentSizeCategoryDidChangeNotification object:nil];
這樣一來,當(dāng)系統(tǒng)字體發(fā)生變化時舆驶,注冊該頻道的對象會收到通知并執(zhí)行自定義的方法。
當(dāng)改變系統(tǒng)字體的大小后拘荡,該類會收到通知撬陵,并調(diào)用prefredFontsChaged:
方法,此時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];
}
這里垢夹,顯然又是一個MVC的流程:系統(tǒng)字體(模型)被改變了维费,通過廣播(通知)的機制來告訴控制器,然后控制器再調(diào)用更改View的方法犀盟。還記得在第一篇(詳情請見:斯坦福大學(xué)iOS開發(fā)公開課總結(jié)(一) :iOS的MVC框架)里強調(diào)的阅畴,從模型到控制器的通信是通過廣播或KVO機制完成的么?
最后的話
如果哪位小伙伴想拿到此Demo的代碼請不要客氣,在評論里留言即可颤专。
而且十分歡迎給筆者的代碼和文筆拋出寶貴的意見和建議~
本文為筆者原創(chuàng)钠乏,如需轉(zhuǎn)載,請事先與筆者交涉~
2016.7.12日更新:
筆者已經(jīng)把目前為止整理的所有Demo(第二課到第十課)放入到了我的GitHub倉庫里簇捍。分為英文注釋版和中文注釋版(英文注釋要少一點俏拱,嘿嘿)想要的小伙伴可以果斷下載~ 如果有不知道怎么下載的小伙伴請聯(lián)系我~
本文已在版權(quán)印備案,如需轉(zhuǎn)載請訪問版權(quán)印锅必。48422928
-------------------------------- 2018年7月17日更新 --------------------------------
注意注意!7直汀尔许!
筆者在近期開通了個人公眾號,主要分享編程蒸甜,讀書筆記余佛,思考類的文章。
- 編程類文章:包括筆者以前發(fā)布的精選技術(shù)文章辉巡,以及后續(xù)發(fā)布的技術(shù)文章(以原創(chuàng)為主),并且逐漸脫離 iOS 的內(nèi)容憔恳,將側(cè)重點會轉(zhuǎn)移到提高編程能力的方向上净蚤。
- 讀書筆記類文章:分享編程類,思考類程梦,心理類,職場類書籍的讀書筆記屿附。
- 思考類文章:分享筆者平時在技術(shù)上,生活上的思考衣厘。
因為公眾號每天發(fā)布的消息數(shù)有限制压恒,所以到目前為止還沒有將所有過去的精選文章都發(fā)布在公眾號上,后續(xù)會逐步發(fā)布的型宙。
而且因為各大博客平臺的各種限制伦吠,后面還會在公眾號上發(fā)布一些短小精干,以小見大的干貨文章哦~
掃下方的公眾號二維碼并點擊關(guān)注毛仪,期待與您的共同成長~