viewWithTag
UIView *view = [self.view viewWithTag:100];
//內(nèi)部原理
1.首先會(huì)跟自己匹配
2.如果自己不匹配,會(huì)遍歷所有的子控件;首先會(huì)遍歷subViews數(shù)組中第0個(gè)控件,如果不匹配,會(huì)遍歷這個(gè)控件的子控件,依次遍歷
3.如果都不匹配,會(huì)返回nil
界面初始化方法
- 用Storyboard創(chuàng)建的界面,所以初始化應(yīng)該用 -(instancetype)initWithCoder:(NSCoder *)aDecoder 方法。
- 用的是代碼或者xib創(chuàng)建的界面,則應(yīng)該使用 -(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 初始化方法;
- -(void)awakeFromXib XIB加載完成時(shí)候調(diào)用
frame、bounds、center 區(qū)別
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
// 修改位置和尺寸,以父控件左上角為坐標(biāo)原點(diǎn)
redView.frame = CGRectMake(100, 100, 200, 100);
// 修改尺寸,以自己左上角為坐標(biāo)原點(diǎn)
// redView.bounds = CGRectMake(0, 0, 300, 200);
// 修改位置,以父控件左上角為坐標(biāo)原點(diǎn)
// redView.center = CGPointMake(200, 200);
[self.view addSubview:redView];
UIImageView
- UIImageView的初始化
//第一種方式
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2"]];
// initWithImage:會(huì)根據(jù)傳入的圖片創(chuàng)建imageView,并且imageView的尺寸等于圖片的尺寸
[self.view addSubview:imageView];
//第二種方式
UIImageView *imageView = [[UIImageView alloc] init];
imageView.image = [UIImage imageNamed:@"2"];
imageView.frame = CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height);
[self.view addSubview:imageView];
// oc語(yǔ)法規(guī)定:不能直接修改oc對(duì)象結(jié)構(gòu)體屬性的成員
CGRect tempFrame = imageView.frame;
tempFrame.size = imageView.image.size;
imageView.frame = tempFrame;
- UIImageview 的內(nèi)容模式
//帶有scale:圖片有可能會(huì)被拉伸
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,
UIViewContentModeScaleAspectFill,
// 不帶有Scale:顯示出來(lái)的圖片不會(huì)被拉伸,保持圖片原來(lái)的寬高比例
UIViewContentModeCenter,
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
*/
- UIImageview 的緩存
- UITableviewCell 分割線內(nèi)邊距
方法1
// ios8 出現(xiàn)布局邊緣
self.tableview.separatorInset = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
方法2
/*
1.取消tableview的分割線
2.設(shè)置tableview的背景色為分割線的顏色
3.setFrame 設(shè)置frame之前 ,把高度減 10
4.補(bǔ)回分割線的高度
*/
-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{
return 60 + 10;
}
- (void)setFrame:(CGRect)frame {
frame.size.height -= 10;
frame.origin.y +=10;
frame.origin.x += 10;
frame.size.width -= 20;
[super setFrame:frame];
}



contentSize、contentOffset、contentInset
contentSize:內(nèi)容 滾動(dòng)范圍
內(nèi)容無(wú)限大 ,可視區(qū)域
contentOffset: 偏移量 ,tableview頂點(diǎn)與內(nèi)容頂點(diǎn)的距離
額外的滾動(dòng)區(qū)域,超出內(nèi)容可以滾動(dòng)多少,額外滾動(dòng)區(qū)域不屬于內(nèi)容
tableview默認(rèn)會(huì)滾動(dòng)到最上面
contentInset: 內(nèi)邊距
UI復(fù)習(xí) 基礎(chǔ)
什么是控制器?
任何繼承于UIViewController的類, 都稱之為控制器
控制器的作用?
管理UI界面(負(fù)責(zé)管理UI界面的創(chuàng)建和一些事件的處理)
連線問(wèn)題
- 一個(gè)控件可以關(guān)聯(lián)多個(gè)屬性,一個(gè)屬性不可以關(guān)聯(lián)多個(gè)控件
- 如果將屬性和控件連線之后又將屬性刪除了, 那么只要程序運(yùn)行就會(huì)報(bào)一個(gè)經(jīng)典錯(cuò)誤
[<ViewController 0x7fe9d9f1a5d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key lable. - 任何UI控件都可以和屬性進(jìn)行連線, 但是并不是任何控件都可以和方法連線. 只有繼承于UIControl的控件才可以連線
- 一個(gè)方法可以很多個(gè)控件關(guān)聯(lián),一個(gè)控件可以和很多方法進(jìn)行連線
- 如果將按鈕關(guān)聯(lián)的方法刪除, 運(yùn)行之后會(huì)報(bào)一個(gè)經(jīng)典錯(cuò)誤
reason: '-[ViewController redBtnClick]: unrecognized selector sent to instance 0x7fb4aa618e50'
父子控件
雖然在Storyboard中不能將某個(gè)控件添加到另一個(gè)控件中, 但是只要通過(guò)代碼, 所以繼承于UIView的控件都可以添加子控件
通過(guò)Tag獲取控件
viewWithTag只能查找當(dāng)前控件和當(dāng)前控件的子控件, 不能查找兄弟控件, 或者父控件
UISwitch *sw = [[UISwitch alloc] init];sw.tag = 998;
`UIView *sw = [self.view viewWithTag:998];
類擴(kuò)展
匿名分類和分類的區(qū)別?
1.匿名分類沒(méi)有名字, 分類有名稱
2.匿名分類不需要有對(duì)應(yīng)的實(shí)現(xiàn), 而分類需要有對(duì)應(yīng)的實(shí)現(xiàn)
3.匿名分類可以聲明屬性, 也可以聲明方法, 分類只能聲明方法
4.分類中的@property只會(huì)生成getter/setter方法的聲明, 不會(huì)生成實(shí)現(xiàn)以及私有的成員變量
分類和原來(lái)注意點(diǎn)
1.如果多個(gè)分類中都有和原有類中同名的方法, 那么調(diào)用該方法的時(shí)候執(zhí)行誰(shuí)由編譯器決定,會(huì)執(zhí)行最后一個(gè)參與編譯的分類中的方法
2.如果分類中有和原有類同名的方法, 會(huì)調(diào)用分類中的方法,也就是說(shuō)會(huì)忽略原有類的方法
load 和 initialize
1.只要程序啟動(dòng)就會(huì)將所有類的代碼加載到內(nèi)存中, 放到代碼區(qū)
2.load方法會(huì)在當(dāng)前類被加載到內(nèi)存的時(shí)候調(diào)用, 有且僅會(huì)調(diào)用一次
3.如果存在繼承關(guān)系, 會(huì)先調(diào)用父類的load方法, 再調(diào)用子類的load方法
1.當(dāng)前類第一次被使用的時(shí)候就會(huì)調(diào)用(創(chuàng)建類對(duì)象的時(shí)候)
2.initialize方法在整個(gè)程序的運(yùn)行過(guò)程中只會(huì)被調(diào)用一次, 無(wú)論你使用多少次這個(gè)類都只會(huì)調(diào)用一次
3.initialize用于對(duì)某一個(gè)類進(jìn)行一次性的初始化
4.initialize和load一樣, 如果存在繼承關(guān)系, 會(huì)先調(diào)用父類的initialize再調(diào)用子類的initialize
獲取按鈕狀態(tài)的屬性值
獲得按鈕的文字
- (NSString *)titleForState:(UIControlState)state
獲得按鈕的文字顏色
- (UIColor *)titleColorForState:(UIControlState)state
獲得按鈕內(nèi)部的小圖片
- (UIImage *)imageForState:(UIControlState)state
獲得按鈕的背景圖片
- (UIImage *)backgroundImageForState:(UIControlState)state
解析Plist文件
獲得Plist文件的全路徑
NSBundle *bundle = [NSBundle mainBundle]; NSString *path = [bundle pathForResource:@"shops" ofType:@"plist"];
加載plist文件
_shops = [NSArray arrayWithContentsOfFile:path]
模型取代字典的好處
1.一般情況下,設(shè)置數(shù)據(jù)和取出數(shù)據(jù)都使用“字符串類型的key”,編寫這些key時(shí),編輯器沒(méi)有智能提示,手敲字符串key,key容易寫錯(cuò),Key如果寫錯(cuò)了,編譯器不會(huì)有任何警告和報(bào)錯(cuò),造成設(shè)錯(cuò)數(shù)據(jù)或者取錯(cuò)數(shù)據(jù)
2.所謂模型,其實(shí)就是數(shù)據(jù)模型,專門用來(lái)存放數(shù)據(jù)的對(duì)象,用它來(lái)表示數(shù)據(jù)會(huì)更加專業(yè),模型設(shè)置數(shù)據(jù)和取出數(shù)據(jù)都是通過(guò)它的屬性,屬性名如果寫錯(cuò)了,編譯器會(huì)馬上報(bào)錯(cuò),使用模型訪問(wèn)屬性時(shí),編譯器會(huì)提供一系列的提示,提高編碼效率
instancetype 和 id
1.instancetype在類型表示上,跟id一樣,可以表示任何對(duì)象類型
2.instancetype只能用在返回值類型上,不能像id一樣用在參數(shù)類型上
3.instancetype比id多一個(gè)好處:編譯時(shí)編譯器會(huì)檢測(cè) instancetype的真實(shí)類型
封裝控件的基本步驟
- 在initWithFrame:方法中添加子控件,提供便利構(gòu)造方法
- 在layoutSubviews方法中設(shè)置子控件的frame(一定要調(diào)用super的layoutSubviews)
- 增加模型屬性,在模型屬性set方法中設(shè)置數(shù)據(jù)到子控件上
Xib和storyboard對(duì)比
共同點(diǎn)
- 都用來(lái)描述軟件界面
- 都用Interface Builder工具來(lái)編輯
- 本質(zhì)都是轉(zhuǎn)換成代碼去創(chuàng)建控件
不同點(diǎn) - Xib是輕量級(jí)的,用來(lái)描述局部的UI界面
- Storyboard是重量級(jí)的,用來(lái)描述整個(gè)軟件的多個(gè)界面,并且能展示多個(gè)界面之間的跳轉(zhuǎn)關(guān)系
Xib的加載
方法1
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"xib文件名" owner:nil options:nil]
方法2
UINib *nib = [UINib nibWithNibName:@"xib文件名" bundle:nil];
NSArray *views = [nib instantiateWithOwner:nil options:nil];
注意點(diǎn)
一個(gè)控件有2種創(chuàng)建方式:
通過(guò)代碼創(chuàng)建
初始化時(shí)一定會(huì)調(diào)用initWithFrame:方法
通過(guò)xib\storyboard創(chuàng)建
初始化時(shí)不會(huì)調(diào)用initWithFrame:方法,只會(huì)調(diào)用initWithCoder:方法
初始化完畢后會(huì)調(diào)用awakeFromNib方法
剪切超出UIImageView的部分
UIImageView *iv = [[UIImageView alloc]] init];
iv.clipsToBounds = YES;
播放動(dòng)畫
self.UIImageView.animationImages = arrM(存放圖片); [[self. UIImageView startAnimating ]]; // 開(kāi)始動(dòng)畫
資源拷貝注意事項(xiàng)
拷貝資源的時(shí)候選擇的copy的含義:
是否要將資源拷貝一份到項(xiàng)目中, 如果不勾選就代表著不拷貝, 那么原來(lái)的資源不見(jiàn)了, 項(xiàng)目中的也不能用了
注意:
1.雖然項(xiàng)目中的圖片和外部的圖片是同一張圖片, 但是這僅僅是在開(kāi)發(fā)階段, 如果將應(yīng)用程序安裝到手機(jī)上, 那么系統(tǒng)會(huì)自動(dòng)給我們拷貝一張圖片到手機(jī)中
2.雖然安裝的時(shí)候會(huì)自動(dòng)拷貝, 但是還是不建議大家不勾選copy。
圖片除了可以放到supporting files中, 還可以放到Assets.xcassets文件夾中
> 如果是放到supporting files中, 使用圖片的時(shí)候需要加上圖片的后綴
> 如果是放到Assets.xcassets中, 使用圖片的時(shí)候不需要加上圖片的后綴
> 如果是放到Assets.xcassets中, 那么系統(tǒng)會(huì)自動(dòng)對(duì)圖片進(jìn)行copy操作
> 如果是放到Assets.xcassets中, 可以對(duì)圖片進(jìn)行一些額外的屬性設(shè)置
> 如果是放到Assets.xcassets中, 可以提高軟件的安全性, 它會(huì)將圖片都加密壓縮保存到Assets.car文件中
** add to target的含義**
是否需要將資源打包到main bundle中(03-拷貝資源的選項(xiàng).app)
> 如果不勾選就不會(huì)打包進(jìn)去, 也就是說(shuō)程序安裝之后資源不會(huì)在手機(jī)上
**模擬器的路徑:**
/Users/xiaomage/Library/Developer/CoreSimulator/Devices/
imageNamed: 默認(rèn)是去mian bundle中加載, 如果是在mian bundle子文件夾中, 需要告訴系統(tǒng)具體的路徑
播放本地音樂(lè)
NSURL *url = [[NSBundle mainBundle]] URLForResource:@"kyo_dazhao" withExtension:@".mp3"];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[[self.player play]];`
layoutSubviews方法什么時(shí)候調(diào)用
1.只要一個(gè)控件尺寸確定, 那么就會(huì)調(diào)用
2.只要修改控件的尺寸就會(huì)調(diào)用(bounds/frame)
3.修改位置不會(huì)調(diào)用
4.如果當(dāng)前修改的尺寸和上一次的尺寸沒(méi)有變化, 不會(huì)調(diào)用