目錄ios
---恢復內容開始---git
1程序員

技術目標:github
運行就是打包的過程,把包放到模擬器中,此時設置一系列的內容,找到程序的入口(MainInterface),依次按照步驟來.編程
爲何用weak?
拖拽的控件所在的控制器都是被強引用所存在的,這個控制器被強引用,控制器的view被控制器強引用,view的控件被view強引用。因此外部拖線這件事其實就是我拿到這個控件,而不須要strong再引用了。json
什麼能夠單擊事件?
通常繼承UIControl的都有單擊事件數組
UI元素
都叫作控件,全部控件都繼承自UIView
,哪怕是UIControl
也是繼承UIView
.這些控件的基本屬性都放到了公共的UIView
中.superView
: 父控件subViews
: 子控件tag
: 標識frame
: 控件在父控件的位置尺寸(以父控件左上角爲00)bounds
: 控件的位置尺寸(以本身左上角爲00)
center
: 控件中心(以父控件左上角爲00)addSubView
: 添加removeFromsuperView
: 從父控件移除viewWithTag
:根據tag找到View
用於顯示文字xcode
numberofLines
: 文字行數,等於0的時候自動換行lineBreakMode
: 換行模式,是頭部省略仍是尾部省略仍是中間省略font
: 字體用於顯示圖片瀏覽器
contentMode
: 填充模式
帶有scale的會縮放,不帶的不會縮放,可是須要裁剪 typedef NS_ENUM(NSInteger, UIViewContentMode) { UIViewContentModeScaleToFill,// 徹底壓縮或拉伸 UIViewContentModeScaleAspectFit, // 寬高比不變,不會變形 UIViewContentModeScaleAspectFill,// 寬高比不變,填充 UIViewContentModeRedraw,// 從新繪製 UIViewContentModeCenter, UIViewContentModeTop, UIViewContentModeBottom, UIViewContentModeLeft, UIViewContentModeRight, UIViewContentModeTopLeft, UIViewContentModeTopRight, UIViewContentModeBottomLeft, UIViewContentModeBottomRight, };
緩存
clipsToBounds
: 裁剪多餘部分animationImages
: 設置動畫圖片(放一個數組)animationRepeatCount
: 播放次數animationDuration
: 播放時間
設置毛玻璃效果
因爲UIToolBar
自帶毛玻璃效果,因此能夠給UIImageView增長UIToolBar的方法設置毛玻璃的簡單效果。UIToolBar有一個barStyle
枚舉能夠設置毛玻璃樣式,配合alpha透明度能夠作設置。
序列幀動畫
UIImageNamed
imageWithContentsOfFile
拿到圖片路徑:
NSString *path = [[NSBundle mainBundle] pathForResource:@"資源名字" ofType:@"資源類型"]; self.imgView.image = [UIImage imageWithContentsOfFile:path];
按鈕既能顯示文字又能顯示圖片,還能隨時調整內部圖片文字的位置
normal
:通常hightlighted
:高亮disabled
:不可點擊button.titleLabel.font
xxxForState
調整按鈕內部子控件位置:默認的是圖片左邊,文字右邊,可是開發是各類需求的
當本身算完按鈕每部距離何時,可能出現文字顯示不全問題,這時候只須要sizeToFit
,可是有時會出現文字錯位問題!由於這個方法可能會修改center,那麼能夠先sizetofit算,而後再修改center便可。
(CGRect)imageRectForContentRect:(CGRect)contentRect;
方法2: 其實既然都重寫了,不如直接在`layoutSubViews`方法裏面修改 方法3: 不須要重寫一個新的Button,直接修改內邊距
objc{
CGFloat labelWidth = modelButton.titleLabel.frame.size.width;
CGFloat imageWith = modelButton.imageView.frame.size.width;
modelButton.imageEdgeInsets = UIEdgeInsetsMake(0, labelWidth, 0, -labelWidth);
modelButton.titleEdgeInsets = UIEdgeInsetsMake(0, -imageWith, 0, imageWith);
```
```objc
/*
1、按鈕的狀態
1.UIControlStateNormal
1> 除開UIControlStateHighlighted、UIControlStateDisabled、UIControlStateSelected之外的其餘狀況,都是normal狀態
2> 這種狀態下的按鈕【能夠】接收點擊事件
2.UIControlStateHighlighted
1> 【當按住按鈕不鬆開】或者【highlighted = YES】時就能達到這種狀態
2> 這種狀態下的按鈕【能夠】接收點擊事件
3.UIControlStateDisabled
1> 【button.enabled = NO】時就能達到這種狀態
2> 這種狀態下的按鈕【沒法】接收點擊事件
4.UIControlStateSelected
1> 【button.selected = YES】時就能達到這種狀態
2> 這種狀態下的按鈕【能夠】接收點擊事件
2、讓按鈕沒法點擊的2種方法
1> button.enabled = NO;
*【會】進入UIControlStateDisabled狀態
2> button.userInteractionEnabled = NO;
*【不會】進入UIControlStateDisabled狀態,繼續保持當前狀態
*/
```
保護一部分不被拉伸
,例如四個角什麼的
// 拉伸 UIImage *img = [UIImage imageNamed:@"1"]; // 方法一:返回一張受保護而且拉伸平鋪的圖片(edge是受保護區域),此時就留下了圖片最中心1,1的像素點無線平鋪 UIImage *resizableImage = [img resizableImageWithCapInsets:UIEdgeInsetsMake(img.size.height * 0.5, img.size.width * 0.5, img.size.height * 0.5 - 1, img.size.width * 0.5 - 1)]; // 方法二:左邊和右邊須要保護的區域 UIImage *strechImage = [img stretchableImageWithLeftCapWidth:img.size.width * 0.5 topCapHeight:img.size.height * 0.5] [self.btn setBackgroundImage:resizableImage forState:UIControlStateNormal];
其實這些能夠寫在分類裏,返回一張受保護的圖片(寫一個UIImage分類)
直接拉伸
選擇Slicing,會自動計算最合適的保護區域,要不本身拽。

訪問數據就是重寫get方法,通常的控件,數組等都應該用懶加載
開發中有一些小數據能夠存儲在plist中。例如不少頁面用的數據,NSArray或者NSDictionary之類的數據。
writeToFile
到本地,而後拽到項目中解析
```objc{
// 寫入
NSArray *array = @[@"1",@"2",@{@"aaa":@"aa"}];
[array writeToFile:@"/Users/aixiaoxin/Desktop/study.plist" atomically:YES];
// 讀取
NSArray *arr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"study" ofType:@"plist"]];
NSLog(@"%@",arr);
```
所謂模型
,就是專門用來存放數據的對象。
方法:
純手工:本身創造模型,模型新增構造方法initWithDict等,而後外界賦值,內部實現.
```objc{
-(instancetype)initWithDict:(NSDictionary *)dict {
if (self == [super init]) {
self.name = dict[@"name"]; self.icon = dict[@"icon"];
}
return self;
}
```
kvc字典轉模型:
YYModel:
自定義UIView,通常在init初始化方法中添加本身的子控件(initWithFrame中寫就能夠,這個方法init也會調用),在layoutsubView中佈局frame(這裏能拿到self.frame),再引入模型接口,在模型的set方法中賦值模型,設置數據(或者提供接口方法直接設置)

加載xibView:
```objc{
// 讀取xib
// last是最後一個數組,由於一個xib可能拽了不少view,其實通常狀況下就一個,便於開發
UIView *xibView = [[[NSBundle mainBundle] loadNibNamed:@"Play" owner:nil options:nil] lastObject];
xibView.frame = CGRectMake(100, 100, 300, 100);
[self.view addSubview:xibView];
若是xib各處都用,那應該提供快速的建立方法
```objc{
// 快速加載xib
+(instancetype)play {
return [[[NSBundle mainBundle] loadNibNamed:@"Play" owner:nil options:nil] lastObject];
}
initWithCoder:
,在這裏建立子控件就能夠了。initWithCoder
中建立的,此時控件是處於爲喚醒狀態,此時要用到awakeFromNib
方法,在這裏能夠添加xib中建立的子控件的子控件。其實若是想在xib中再加控件,統一這個方法就行。allocinit
直接加載的。方法

KVC 能夠取值/賦值/字典轉模型等。
賦值:setValueForKey
:能夠進行自動類型轉換,若是用KVC和網絡搭建,很是方便。通常一個對象KVC賦值屬性值是可行的。而 setValueForKeyPath
: keyPath是能夠嵌套對象的,假如賦值一我的的狗屬性的名字(點語法點出來),就能夠 person setValue: @"旺財 forKeyPath:@"dog.name"
。其實後者包含前者所有功能,因此直接用setValueForKeyPath
就行。
改變類的私有變量: 通常私有類都是在.m的{}中
,此時是點不出來的,這意味着我定義了一個_age
,而我直接能夠setValueForKeyPath:@"_age"
來修改這個值(寫@"age"都行,他會去找下劃線和不帶下劃線的)。
字典轉模型:
```objc{
-(instancetype)initWithDict:(NSDictionary *)dict {
if (self == [super init]) {
// 廢棄
// self.name = dict[@"name"];
// self.icon = dict[@"icon"];
// KVC字典轉模型 [self setValuesForKeysWithDictionary:dict];
}
return self;
}
-(void)setValue:(id)value forUndefinedKey:(NSString *)key {
}```
KVC字典轉模型的問題:若是有模型嵌套,就會出問題,由於是暴力的鍵值對賦值。固然,此時就會用到框架(YYModel,MJExtension)
valueForKeyPath
方法,開發通常不怎麼用,由於點語法就好了Key Value Observing(鍵值監聽)
當某個對象的屬性發生改變時進行監聽。假如監聽一個對象的名字改變,scrollView的contentOffSet改變等。
若是一個類用KVO監聽,蘋果會自動爲這個類生成一個子類(查看isa指針的時候就是NSKVONotifying_XXX類型),因此用的多了性能不好
- - -
監聽屬性,就要給屬性的對象增長觀察者
MYModel *model = [MYModel new]; // 增長監聽觀察後,那麼應該有個方法來進行 監聽完成後的做爲 [model addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]; model.name = @"改變前"; model.name = @"改變後"; [model removeObserver:self forKeyPath:@"name"];
/** 監聽屬性值改變後 @param keyPath 要改變的屬性 @param object 要改變的屬性所屬的對象 @param change 改變的內容 @param context 上下文 */ -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{ NSLog(@"%@==%@===%@",keyPath,object,change); }
結果:
2017-03-20 18:10:22.341 button[6755:1544348] name==<MYModel: 0x60800022d7e0>==={ kind = 1; new = "\U6539\U53d8\U524d"; } 2017-03-20 18:13:10.575 button[6785:1563494] name==<MYModel: 0x618000030500>==={ kind = 1; new = "\U6539\U53d8\U540e"; }
設備的屏幕大小是有限的,普通的View不具有滾動功能,UIScrollView能夠經過滾動展現大量內容。
- - -
contentSize
屬性,也就是滾動範圍(能夠遠大於本體scrollView的size),因此當contentSize尺寸減去本體size是負數的話就沒法滾動了,怎麼也要大於本體尺寸clipsToBounds = YES
,也就是內容超出邊框後就隱藏scrollView.scrollEnabled
設置爲NO(只是不能滾動)scrollView.userInteraction
設置爲NO(失去任何交互能力)bounces
默認YES,彈簧效果alwaysBouncesHorizontal
默認NO,和下一個方法同樣,設置YES的時候可讓沒有contentsize的scrollView滾動(只是一個彈簧效果)alwaysBouncesVertical
默認NO,這兩個值就算設置YES也沒區別,由於這時候已經設置了contentSize。當沒有設置contentSize的時候,若是設置這兩個是YES就能夠滾動了,就像網絡圖片還沒下載完成,只有下拉才能下載,而後加載contentsize,這時候就須要用到這兩個屬性了showHorizontalScrollIndicator
展現水平滾動條showVerticalScrollIndicator
展現垂直滾動條public var contentOffset: CGPoint // 滾動視圖偏移量 public var contentSize: CGSize // 滾動視圖的內容大小 public var contentInset: UIEdgeInsets // scrollview的contentview的頂點相對於scrollview的位置 public var directionalLockEnabled: Bool // default NO. if YES, try to lock vertical or horizontal scrolling while dragging public var bounces: Bool // 是否開啓回彈效果 public var alwaysBounceVertical: Bool // 是否始終水平回彈 public var alwaysBounceHorizontal: Bool // 是否始終垂直回彈 public var pagingEnabled: Bool // 是否分頁(開啓後滑動有自動定位功能) public var scrollEnabled: Bool // 是否能夠滾動 public var showsHorizontalScrollIndicator: Bool // 是否顯示水平滾動條 public var showsVerticalScrollIndicator: Bool // 是否顯示垂直滾動條 public var indicatorStyle: UIScrollViewIndicatorStyle // 滾動條的樣式(黑色/白色/默認) public var scrollsToTop: Bool // 默認YES,單擊上方狀態欄(服務商和電池那個地方),會自動回到頂端
重要屬性
contentOffSet
,是一個CGPoint屬性,是一個偏移量
contentInset
,是UIEdgeInset屬性,是內邊距,分別是上左下右,滾動的時候會多出來一起不顯示的部分就是內邊距效果,會變相的增長額外的滾動距離代理(監聽行爲)
在UIScrollView滾動時候就會告訴代理,代理髮送一系列消息。
public protocol UIScrollViewDelegate : NSObjectProtocol { @available(iOS 2.0, *) optional public func scrollViewDidScroll(scrollView: UIScrollView) // 滾動的時候 @available(iOS 3.2, *) optional public func scrollViewDidZoom(scrollView: UIScrollView) // 滾動視圖已經縮放時候 @available(iOS 2.0, *) optional public func scrollViewWillBeginDragging(scrollView: UIScrollView) // 將要開始拖動視圖調用 @available(iOS 5.0, *) optional public func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) // 將要結束拖拽視圖調用 @available(iOS 2.0, *) optional public func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) // 已經結束拖拽視圖 @available(iOS 2.0, *) optional public func scrollViewWillBeginDecelerating(scrollView: UIScrollView) // 即將減速的時候 @available(iOS 2.0, *) optional public func scrollViewDidEndDecelerating(scrollView: UIScrollView) // 減速中止的時候 @available(iOS 2.0, *) optional public func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) // 滾動動畫結束時候 @available(iOS 2.0, *) optional public func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? // 設置進行縮放的子視圖(誰縮放) @available(iOS 3.2, *) optional public func scrollViewWillBeginZooming(scrollView: UIScrollView, withView view: UIView?) // 將要進行縮放時候 @available(iOS 2.0, *) optional public func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView?, atScale scale: CGFloat) // 完成縮放的時候 @available(iOS 2.0, *) optional public func scrollViewShouldScrollToTop(scrollView: UIScrollView) -> Bool // return a yes if you want to scroll to the top. if not defined, assumes YES @available(iOS 2.0, *) optional public func scrollViewDidScrollToTop(scrollView: UIScrollView) // 點擊狀態欄回到頂部,僅針對可上下滾動的scrollview 有效}
注意: 任何OC對象均可以成爲代理,哪怕你SCrollView滾動,讓一條狗遵照ScrollViewDelegate而且實現方法成爲代理,那再狗的.m中就能夠監聽到scrollView滾動
6.代理(監聽行爲)
scrollView能夠經過手勢完成內容縮放放大
1. 用代理找到要縮放的scrollViewviewForZoomingInScrollView
2. 設置縮放比例:
``` scrollView.maximumZoomScale = 2.0 scrollView.minimumZoomScale = 0.5 scrollView.bouncesZoom = true // 縮放屬性是否回彈 ```
7.分頁功能
- 就像蘋果手機開機的分頁頁面,當你滾動的時候,左邊比較多右邊比較少,那麼就自動滾動到左邊,這就是分頁功能。不少App的分頁滾動功能,也是依據分頁來實現的。
其實就是一個屬性pageingEnable
開啓後就能夠了。系統分頁的判斷是按照scrollView的大小來分的。若是要添加分頁控件再自行添加UIpageControl
。
- 不少分頁的點都用得圖片,這樣看起來很好看,可是其實觀察UIpageControl
頭文件是沒有圖片選擇的,它隱藏在.m的私有拓展中有一個屬性_currentPageImage
,_otherPageImage
,此時能夠經過KVC來轉化成本身喜歡的圖片
- 分頁定時器:每隔必定的時間,但願scrollView作一些事情,去滾動,要用到定時器NSTimer
。在用戶即將拖拽scrollView的時候中止定時器,不在拖拽的時候開啓定時器。
1.一個定時器要不永久開啓,只要一中止就自動銷燬了,只能建立一個新的 2.程序一啓動會默認開啓一條線程,是主線程,主線程顯示刷新UI界面,處理用戶交互界面,因此主頁面在進行別的操做的時候,定時器可能會卡住。因此要把`NSTimer`添加到運行循環(修改定時器在runloop的模式,目的是無論主線程在作什麼,都會分配必定時間處理事情)。 // 添加到運行循環 [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
隨便一個控件,點開頭文件,若是繼承自UIControl就均可以經過addTarget
來監聽,有些特殊的提供delegate
就能夠經過代理來監聽。像TextField
這類比較特殊,它既有代理也繼承UIControl,此時二者均可以監聽開始編輯,文字改變,結束編輯
等狀態的。
程序員只需關注的是點,而不是像素,一個點所容納的像素越多,越清晰。在iphone4S時代,屏幕尺寸固定,那麼固定值算就能夠適配。在5和5s時代尺寸變化了,此時還沒法用autolayout(由於還要適配ios5),此時用的是AutoresizingMask
,在iphone6時代開始用AutoLayOut

AutoResizingMask
枚舉,能夠選擇是上左下右怎麼適配frame
約束
和參照
完成佈局兩個控件中心點x同樣/中心點y同樣

Relation->LessThan
,告訴UILabel何時開始換行。那麼固定位置和寬度,UILabel就會自動剔除上下兩端的空格了。約束優先級:兩個互相沖突的約束若是修改優先級,那麼優先級較高的生效,當優先級較高的失效了或者刪除了,優先級較低的纔會生效。例如三個方塊並排放各自距離20,當中間的刪除後,讓第三個自動到中間位置,這時候就用到優先級了。

self.myView.translatesAutoresizingMaskIntoConstraints = NO;
NSLayoutconstraint
類建立約束關係
修改約束:
// 修改約束 self.myWidth.constant = 25; [UIView animateWithDuration:2.0 animations:^{ // 須要強制更新 [self.view layoutIfNeeded]; }];
- 目前最流行的第三方框架 - [Masonry/SnipKit](https://github.com/SnapKit/Masonry) - 兩個pch上面的宏定義可讓`mas_`所有省略 - `makeConstraints`是添加新的約束 - `updateConstraints`是更新約束 - `remakeConstraints`是刪除以前全部約束,而後添加新的約束
TableView
分爲Plain
和Group
兩種style類型,這個是隻讀的,意味着只有在建立tableView的時候能夠設置。indexPath
分爲section
和row
兩個屬性,分別是組和行,根據這個能夠肯定惟一的一行cell.accessoryView
能夠設置系統cell右側的那個按鈕狀態樣式rowHeight
:每一行cell高度sectionHeader(Footer)Height
:每一組頭尾高度separateStyle
:分割線樣式(刪除分割線separateNone)tableHeader(footer)View
:整個tableView的頭尾部,上面的是每一組的頭尾,這個是整個的(插播個廣告什麼的)accessoryView
--accessoryType
:都是設置右邊控件的(View優先級更大)selectedStyle
:選中樣式(有Blur,Gray,None等,ios6以前有效果,7以後所有都是灰色)backgroundView
:cell背景能夠是好看的圖片,selectedBackgroundView
:選中的背景圖片contentView
:cell上添加的東西都是添加在contentView上的。由於有時候cell刪除,滑動,整個cell都向左移動了,此時若是移動cell很是麻煩,可是移動contentView就方便多了self.view
和self.tableView
是一個對象。self.tableView.tableFooterView = [UIView new]
[cell class]
都是經過cell alloc initWithStyle
方法實現的-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { _name = [UILabel new]; [self.contentView addSubview:_name]; } return self; }
layoutifNeed
裏面,由於這裏才能拿到self的frame.可是用約束計算的話直接寫在cell alloc initWithStyle
方法裏就行(寫在addSubView之後),由於這是根據父控件的約束,無論父控件如何[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([MyTableViewCell class]) bundle:nil] forCellReuseIdentifier:@"cell"];
cellforRowAtIndexpath
方法返回一個cell,因此能夠根據indexpath改變cell。說白了就是註冊N個cell和reusedId,根據indexPath來dequeue不一樣的cell。廣告cell就這麼來的Static Cells
是寫死的,在sb中/xib中直接修改cell類型而後繪製出來的。能夠作一些設置界面,而後經過代理監聽MJExtension
GitHubMJExtension
---
model-objetArrayWith...
YYModel
GitHubYYModel
---
model-yy_modelWithJson..
UILabel *lab = [[UILabel alloc] init]; // 100是固定寬度 後者是最大寬度,不限制 CGSize size = CGSizeMake(100, MAXFLOAT); // 計算出高度 CGFloat height = [lab.text sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:size].height;
heightForRowAtIndexpath
方法中能夠拿到模型方便計算,可是在這裏計算要調用無數次,性能不好,這時候還必須先返回一個高度給cell,因此一開始以爲應該給數據模型增長全部的cell子控件frame 和總高度frame
屬性,在總高度屬性中,利用懶加載來計算 高度/各個frame,而後外界heightForRowAtIndexpath
直接設置高度。可是這麼作,重用刷新就會出現問題,由於刷新的時候高度大於0,可是不是你想要的高度。真正作法是刷新的時候,拿到json的時候,字典轉模型的時候,建立一個新的frame模型,裏面存放着高度和各個cell子控件的frame,每次刷新數據就綁定好,而後heightForRowAtIndexpath
直接拿frame模型。heightForRowAtIndexpath
纔會執行cellForRowAtIndexPath
,說白了就是cell展現前,全部高度早就計算好了。layoutsubVies
,寫在模型的set方法也能夠,由於這時候是確定有frame的self.tableView.estimatedRowHeight
:預估高度,會優化性能,讓heightForRowAtIndexpath
執行次數少不少。並且沒有估算的時候,是先執行heightForRowAtIndexpath
後執行cellForRowAtIndexPath
。當寫了估算行高後,反過來了,由於已經有一個默認高度了。reloadData
:就是從新調用數據源方法reloadRowsAtIndexPath
:適合模型數量不變insertRowsAtIndexPath
deleteRowsAtIndexPath
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ // 刪除模型,動畫單行刷新 [self.dataSource removeObjectAtIndex:indexPath.row]; [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop]; } -(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{ return @"刪除"; }
-(NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"關注" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { // 關注 }]; action1.backgroundColor = [UIColor orangeColor]; UITableViewRowAction *action2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"刪除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { // 刪除模型,動畫單行刷新 [self.dataSource removeObjectAtIndex:indexPath.row]; [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop]; }]; action2.backgroundColor = [UIColor redColor]; return @[action1,action2]; }
若是想點擊後退出編輯模式,tableView.editing = no
tableView.editing = yes
時,左側就會出現刪除按鈕,其實就是上方的那個編輯模式。並且編輯模式有三種// 設置cell的編輯模式,有NONE,插入,刪除三種 override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle { return UITableViewCellEditingStyle.Insert }
UICollectionViewFlowLayout
:說白了就是當裏面內容變寬了變窄了這個那個了,可是整個佈局會改變。就像手機界面,刪除一個app,後面的會滑上去。self.collrctionView 不等於 self.view
,不像tableView,collectionView是添加到view上的。flowLayout
佈局的時候能夠設置item的大小,行間距,item間距,滾動方向,每一組內邊距(sectionInset),self.collectionView
能夠設置分頁(pagingEnable),彈簧效果(bounces),隱藏滾動條(showH..)等操做,其實不少都是UIScrollView的屬性
相冊照片瀏覽器
// 必需要有佈局,自帶循環機制,每個item就是每個cell // 必需要註冊cell,而且必需要自定義cell,由於collectionView的默認cell什麼都沒有! // 調整尺寸什麼的都是佈局的事,cell自定義後經過代理來完成註冊,數量,模型內容 // 當要作的內容例如item大小不一的時候,系統沒法知足,此時要自定義流水佈局 #import "FlowLayout.h" /* 自定義佈局:只要瞭解5個方法 - (void)prepareLayout; - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect; - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds; - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity; // return a point at which to rest after scrolling - for layouts that want snap-to-point scrolling behavior - (CGSize)collectionViewContentSize; */ @implementation FlowLayout /* UICollectionViewLayoutAttributes:肯定cell的尺寸 一個UICollectionViewLayoutAttributes對象就對應一個cell 拿到UICollectionViewLayoutAttributes至關於拿到cell */ // 重寫它方法,擴展功能 // 何時調用:collectionView第一次佈局,collectionView刷新的時候也會調用 // 做用:計算cell的佈局,條件:cell的位置是固定不變 // - (void)prepareLayout //{ // [super prepareLayout]; // // NSLog(@"%s",__func__); // //} // 做用:指定一段區域給你這段區域內cell的尺寸(就是這個rect,一開始系統固定的,以後超過這個值就新增) // 能夠一次性返回全部cell尺寸,也能夠每隔一個距離返回cell - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { // NSLog(@"%s",__func__); // 這時候就返回全部了 NSArray *attrs = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, MAXFLOAT, MAXFLOAT)]; return attrs; } // 何時調用:用戶手指一鬆開就會調用 // 做用:肯定最終偏移量 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{ // 拖動比較快 最終偏移量 不等於 手指離開時偏移量 // 最終偏移量 CGPoint targetP = [super targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity]; // 獲取collectionView偏移量 NSLog(@"%@ %@",NSStringFromCGPoint(targetP),NSStringFromCGPoint(self.collectionView.contentOffset)); return CGPointZero; } // Invalidate:刷新 // 在滾動的時候是否容許刷新佈局 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{ return YES; } // 計算collectionView滾動範圍 //- (CGSize)collectionViewContentSize{ // return [super collectionViewContentSize]; //}
NSNotificationCenter
實例,負責不一樣對象之間消息傳遞。NSNotification
一個通知有三個屬性
// 發佈通知(object是誰發送) [[NSNotificationCenter defaultCenter] postNotificationName:@"RemoveNotification" object:self userInfo:@{@"money":self.wine.money}]; // 監聽通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(remove:) name:@"RemoveNotification" object:nil]; - (void)remove:(NSNotification*)noti { NSLog(@"%@---%@---%@",noti.name,noti.object,noti.userInfo); int money = [[noti.userInfo objectForKey:@"money"] intValue]; self.totalPriceLabel.text = [NSString stringWithFormat:@"%d",[self.totalPriceLabel.text intValue]-money]; }
object誰發佈的name什麼通知。能夠不寫name,那就是監聽這個object的全部通知。
remove
,當對象被銷燬,就刪除@property (nonatomic, weak) id observe; @end @implementation ViewController - (void)test { // 方式一: // Observer:觀察者 // selector:只要一監聽到通知,就會調用觀察者這個方法 // Name:通知名稱 // object:誰發出的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveNote) name:@"note" object:nil]; } - (void)test2 { // Name:通知名稱 // object:誰發出的通知 // queue:決定block在哪一個線程執行,nil:在發佈通知的線程中執行 // [NSOperationQueue mainQueue]:通常都是使用主隊列 // usingBlock:只要監聽到通知,就會執行這個block // 注意:必定要記得移除 _observe = [[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { // 只要監聽到通知 就會調用 NSLog(@"%@",[NSThread currentThread]); NSLog(@"%@",self); }]; } // 一個對象即將銷燬就會調用 - (void)dealloc { // 移除通知 [[NSNotificationCenter defaultCenter] removeObserver:_observe]; } // 異步:監聽通知 主線程:發出通知 接收通知代碼在主線程 // 主線程:監聽通知 異步:發出通知 接收通知代碼在異步 // 注意:在接收通知代碼中 能夠加上主隊列任務
UIDevice
提供一個單例UIDevice-currentDevice
,表明設備,能夠獲取一些設備信息,例如電池電量,電池狀態,設備類型,設備系統等等。sytemVersion
來進行代碼不一樣的寫法,能夠用於系統適配UIDevice
會不間斷的發佈一些通知,例如
鍵盤也有一些系統的通知,來判斷鍵盤狀態

Assset
裏面的啓動頁設置。Bundle name
:應用程序名稱(項目名稱通常不是中文的,由於要打包,可是app不少中文名字,這時候在這裏改這個選項是中文,例如 財務審批
)Bundle identifier
:應用程序惟一標識(上傳appStore的時候必須有這個,作推送的時候也必須有這個(推送是把消息發送給蘋果服務器,服務器根據你手機的Bundle identifier來找到你這個app))Bundle version string , short
:版本號,軟件版本號Bundle version
:應用程序打包版本號// 定義debugFKLog #ifdef DEBUG #define FKLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #else #define FKLLog(...) #endif
Build Settings - 搜索prefix - 尋找 LLVM 7.0 Lauguage - pch改YES - 填寫pch路徑fullPath
UIApplication
是應用程序的象徵。每個app只有一個,是單例。sharedApplication
UIApplication
,利用它而已作一些應用層設置。例如
applicationIconBadgeNumber
:設置app右上角紅色提醒數字設置圖標屬性
```// ios 8後須要受權,目前只會寫一種受權方式,iOS10有新方法 NSInteger times = arc4random() % 100; [[UIApplication sharedApplication] setApplicationIconBadgeNumber:times];
- `networkActivituIndicatorVisible`:設置聯網小菊花的可見性(Bool)通常寫在網絡方法中 - `statusBarHidden`:設置狀態欄隱藏 ```
/**
想要使用 默認要在info.plist新增最後一個鍵值對,選no,這時候控制器設置無效
全局設置狀態欄白色
全局設置導航欄背景mainColor
全局設置導航欄標題文字顏色白色,微軟雅黑
全局設置導航欄Item顏色 白色
*/
(void)systemSetting {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[[UINavigationBar appearance] setBarTintColor:mainColor];
[[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
[[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: [UIColor whiteColor], NSForegroundColorAttributeName, [UIFont fontWithName:@"MicrosoftYaHei" size:18.0], NSFontAttributeName, nil]];
}
```
// 不是全局 交給每一個控制器獨立控制,默認是交給控制器的 -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } -(BOOL)prefersStatusBarHidden { return YES; }
keyWindow
:應用程序主窗口
openURL
方法 [NSURL URLWithString:]
-->根據協議頭tel: sms:http:等來區分
UIApplication
代理:UIApplication
會有代理監聽(也就是AppDelegate裏面那一堆方法)
UIWindow
是一個特殊的UIView,ios啓動完畢後,啓動的第一個視圖控件就是UIWindow
,而後建立控制器View,把控制器view加到UIWindow
上。因此說沒有UIWindow
就看不到任何UI界面的。
self.window makeKeyAndVisible
的做用是顯示,把跟控制器的view加載到個人window上。UIWindow
windowLevel
:窗口層級(不一樣窗口誰前誰後能夠分層級)Alert > StatusBar > Normal
控制器利用loadView
方法,專門建立控制器View。當控制器的View第一次使用的時候調用此方法。那麼loadView
作了什麼?
1. 判斷若是控制器是sb加載的,就找sb的View設置爲本身當前View 2. 若是是xib加載,就把xibView設置本身View 3. 若是都不是,就會建立一個空白的View
一旦重寫了這個方法,那麼這個View就須要本身建立了,這樣能夠自定義控制器最一開始的View。
若是一個控件是透明的,那麼它不能接收事件。一開始建立的控制器不是透明的,只是顏色是透明的,是能夠接收事件的。
self.inputView
:修改文本框彈出鍵盤類型代理選擇設置內容。通常配合UITextField
的鍵盤類型設置爲是自定義的PickerView
datepickerMode
: 日期模式能夠選擇想要的年月日
locale
:設置區域爲localeWithLocaleId:@"zh"
中國
監聽日期改變用addTarget-Valuechange
項目中這些選項都有,例如左邊國家右邊國旗的界面, 年月日時間的界面, 選擇城市(市區)的界面。國家國旗就是一個pickerView,自定義View弄上imageView和label,用代理完成。年月日就如上,選擇城市~~
字符串 用copy
目的是外界修改了,不會影響到本身。其實,一個字符串屬性被賦值的時候,self.name = @"xxx"
這個賦值的值,要不就是寫死的,要不就是網絡獲取的,可是必定都是NSString
類型。而copy屬性呢,會在set方法的時候作一次copy,copy會作一次判斷,判斷外界給的值得類型是可變的仍是不可變的,若是是不可變的,直接賦值,若是是可變的,就copy一份賦值。因此其實app的字符串都是不可變的,因此寫strong
也是能夠的,甚至會少一次判斷,性能上會高一些。財務審批NSString很是多
,這一點用strong
是可行的。
---恢復內容結束---