從iOS9開始的常見報錯
Application windows are expected to have a root view controller at the end of application launch
- 從iOS9開始, 在
程序啟動完畢那一刻
顯示出來的窗口必須
要設(shè)置根控制器
有些圖片顯示出來會自動渲染成藍(lán)色
比如
- 設(shè)置tabBarItem的選中圖片
vc.tabBarItem.selectedImage = image;
- 設(shè)置UIButtonTypeSystem樣式按鈕的image時
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setImage:image forState:UIControlStateNormal];
解決方案
- 再次產(chǎn)生一張不會進(jìn)行渲染的圖片
// 加載圖片
UIImage *tempImage = [UIImage imageNamed:@"tabBar_essence_click_icon"];
// 產(chǎn)生一張不會進(jìn)行自動渲染的圖片
UIImage *selectedImage = [tempImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
vc.tabBarItem.selectedImage = selectedImage;
-
直接在xcassets文件中配置
設(shè)置TabBarItem的文字屬性
- 直接設(shè)置每一個tabBarItem對象
// 普通狀態(tài)下的文字屬性
NSMutableDictionary *normalAttrs = [NSMutableDictionary dictionary];
normalAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:14];
normalAttrs[NSForegroundColorAttributeName] = [UIColor grayColor];
[vc.tabBarItem setTitleTextAttributes:normalAttrs forState:UIControlStateNormal];
// 選中狀態(tài)下的文字屬性
NSMutableDictionary *selectedAttrs = [NSMutableDictionary dictionary];
selectedAttrs[NSForegroundColorAttributeName] = [UIColor darkGrayColor];
[vc.tabBarItem setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
// 字典中用到的key
1.iOS7之前(在UIStringDrawing.h中可以找到)
- 比如UITextAttributeFont\UITextAttributeTextColor
- 規(guī)律:UITextAttributeXXX
2.iOS7開始(在NSAttributedString.h中可以找到)
- 比如NSFontAttributeName\NSForegroundColorAttributeName
- 規(guī)律:NSXXXAttributeName
- 通過UITabBarItem的appearance對象統(tǒng)一設(shè)置
/**** 設(shè)置所有UITabBarItem的文字屬性 ****/
UITabBarItem *item = [UITabBarItem appearance];
// 普通狀態(tài)下的文字屬性
NSMutableDictionary *normalAttrs = [NSMutableDictionary dictionary];
normalAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:14];
normalAttrs[NSForegroundColorAttributeName] = [UIColor grayColor];
[item setTitleTextAttributes:normalAttrs forState:UIControlStateNormal];
// 選中狀態(tài)下的文字屬性
NSMutableDictionary *selectedAttrs = [NSMutableDictionary dictionary];
selectedAttrs[NSForegroundColorAttributeName] = [UIColor darkGrayColor];
[item setTitleTextAttributes:normalAttrs forState:UIControlStateSelected];
Appearance的使用場合
- 只要后面帶有
UI_APPEARANCE_SELECTOR
的方法或者屬性,都可以通過appearance對象統(tǒng)一設(shè)置 - 比如
@interface UISwitch : UIControl <NSCoding>
@property(nullable, nonatomic, strong) UIColor *onTintColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
@end
UISwitch *s = [UISwitch appearance];
s.onTintColor = [UIColor redColor];
項目的圖片資源
- 可以利用一個Mac軟件解壓
顏色相關(guān)的一些知識
- 顏色的基本組成
- 一種顏色由N個顏色通道組成
- 顏色通道
- 1個顏色通道占據(jù)8bit
- 1個顏色通道的取值范圍
- 10進(jìn)制 : [0, 255]
- 16進(jìn)制 : [00, ff];
- 常見的顏色通道
- 紅色 red R
- 綠色 green G
- 藍(lán)色 blue B
- 透明度 alpha A
- R\G\B一樣的是灰色
- 顏色的種類
- 24bit顏色
- 由R\G\B組成的顏色
- 常見的表示形式
- 10進(jìn)制(
僅僅是用在CSS
)- 紅色 : rgb(255,0,0)
- 綠色 : rgb(0,255,0)
- 藍(lán)色 : rgb(0,0,255)
- 黃色 : rgb(255,255,0)
- 黑色 : rgb(0,0,0)
- 白色 : rgb(255,255,255)
- 灰色 : rgb(80,80,80)
- 16進(jìn)制(
可以用在CSS\android
)- 紅色 : #ff0000 #f00
- 綠色 : #00ff00 #0f0
- 藍(lán)色 : #0000ff #00f
- 黃色 : #ffff00 #ff0
- 黑色 : #000000 #000
- 白色 : #ffffff #fff
- 灰色 : #979797
- 10進(jìn)制(
- 32bit顏色
- 由R\G\B\A組成的顏色
- 常見的表示形式
- 10進(jìn)制(
僅僅是用在CSS
)- 紅色 : rgba(255,0,0,255)
- 綠色 : rgba(0,255,0,255)
- 藍(lán)色 : rgba(0,0,255,255)
- 黃色 : rgba(255,255,0,255)
- 黑色 : rgba(0,0,0,255)
- 白色 : rgba(255,255,255,255)
- 16進(jìn)制(#AARRGGBB,
僅僅是用在android
)- 紅色 : #ffff0000
- 綠色 : #ff00ff00
- 藍(lán)色 : #ff0000ff
- 黃色 : #ffffff00
- 黑色 : #ff000000
- 白色 : #ffffffff
- 10進(jìn)制(
- 24bit顏色
PCH文件可能引發(fā)的錯誤
- 解決方案
#ifndef PrefixHeader_pch
#define PrefixHeader_pch
/*** 如果希望某些內(nèi)容能拷貝到任何源代碼文件(OC\C\C++等), 那么就不要寫在#ifdef __OBJC__和#endif之間 ***/
/***** 在#ifdef __OBJC__和#endif之間的內(nèi)容, 只會拷貝到OC源代碼文件中, 不會拷貝到其他語言的源代碼文件中 *****/
#ifdef __OBJC__
#endif
/***** 在#ifdef __OBJC__和#endif之間的內(nèi)容, 只會拷貝到OC源代碼文件中, 不會拷貝到其他語言的源代碼文件中 *****/
#endif
在Build Setting中配置宏
- 如果項目中有些宏找不到, 可能是配置在Build Setting中
注意點:宏的名字不能全部是小寫字母
-
如果宏的名字全部是小寫, 會出現(xiàn)以下錯誤
控制臺可能會輸出以下警告信息
- 警告的原因: [UIImage imageNamed:nil]
CUICatalog: Invalid asset name supplied: (null)
CUICatalog: Invalid asset name supplied: (null)
- 警告的原因: [UIImage imageNamed:@""]
CUICatalog: Invalid asset name supplied:
CUICatalog: Invalid asset name supplied:
準(zhǔn)確判斷一個字符串是否有內(nèi)容
if (string.length) {
}
/*
錯誤寫法:
if (string) {
}
*/
替換UITabBarController內(nèi)部的tabBar
// 這里的self是UITabBarController
[self setValue:[[LYWTabBar alloc] init] forKeyPath:@"tabBar"];
center和size的設(shè)置順序
- 建議的設(shè)置順序
- 先設(shè)置size
- 再設(shè)置center
給系統(tǒng)自帶的類增加分類
- 建議增加的分類屬性名\方法名前面加上前綴, 比如
@interface UIView (LYWExtension)
@property (nonatomic,assign) CGFloat LYW_X;
@property (nonatomic,assign) CGFloat LYW_Y;
@property (nonatomic,assign) CGFloat LYW_W;
@property (nonatomic,assign) CGFloat LYW_H;
@property (nonatomic,assign) CGSize LYW_size;
@property (nonatomic,assign) CGPoint LYW_point;
@property (assign, nonatomic) CGFloat LYW_centerX;
@property (assign, nonatomic) CGFloat LYW_centerY;
@property (nonatomic,assign) CGFloat LYW_right;
@property (nonatomic,assign) CGFloat LYW_bottom;
+(instancetype)LYWviewFromXib;
@end
按鈕常見的訪問方法
[button imageForState:UIControlStateNormal].size;
button.currentImage.size;
[button backgroundImageForState:UIControlStateNormal];
button.currentBackgroundImage;
[button titleForState:UIControlStateNormal];
button.currentTitle;
[button titleColorForState:UIControlStateNormal];
button.currentTitleColor;
設(shè)置按鈕的內(nèi)邊距
@property(nonatomic) UIEdgeInsets contentEdgeInsets UI_APPEARANCE_SELECTOR;
@property(nonatomic) UIEdgeInsets titleEdgeInsets;
@property(nonatomic) UIEdgeInsets imageEdgeInsets;
解決導(dǎo)航控制器pop手勢失效
self.interactivePopGestureRecognizer.delegate = self;
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 手勢何時有效 : 當(dāng)導(dǎo)航控制器的子控制器個數(shù) > 1就有效
return self.childViewControllers.count > 1;
}
frame和bounds的重新認(rèn)識
- frame
- 以
父控件
內(nèi)容
的左上角為坐標(biāo)原點, 計算出的控件自己
矩形框
的位置和尺寸
- 以
- bounds
- 以
控件自己
內(nèi)容
的左上角為坐標(biāo)原點, 計算出的控件自己
矩形框
的位置和尺寸
- 以
- 概括
- frame.size == bounds.size
- scrollView.bounds.origin == scrollView.contentOffset
bounds和frame的區(qū)別
矩形框和內(nèi)容的理解
- 矩形框
- 控件自己的顯示位置和尺寸
- 內(nèi)容
- 控件內(nèi)部的東西,比如它的子控件
在使用UITableViewController過程中,可能會出現(xiàn)的錯誤
@interface TestTableViewController : UITableViewController
@end
'-[UITableViewController loadView] instantiated view controller with identifier "UIViewController-BYZ-38-t0r" from storyboard "Main", but didn't get a UITableView.'
- 造成這個錯誤的原因
- 錯誤地將一個UIViewController當(dāng)做UITableViewController來用
-
錯誤做法
- 正確做法
contentInset的調(diào)整
- 默認(rèn)情況下, 如果一個控制器A處在導(dǎo)航控制器管理中, 并且控制器A的第一個子控件是UIScrollView, 那么就會自動調(diào)整這個UIScrollView的contentInset
- UIEdgeInsetsMake(64, 0, 0, 0) // 有導(dǎo)航欄
- UIEdgeInsetsMake(20, 0, 0, 0) // 沒有導(dǎo)航欄
- 默認(rèn)情況下, 如果一個控制器A處在導(dǎo)航控制器管理中, 并且導(dǎo)航控制器又處在UITabBarController管理中, 并且控制器A的第一個子控件是UIScrollView, 那么就會自動調(diào)整這個UIScrollView的contentInset
- UIEdgeInsetsMake(64, 0, 49, 0)
- 如何禁止上述的默認(rèn)問題?
控制器A.automaticallyAdjustsScrollViewInsets = NO;
文字內(nèi)容換行
- 如何讓storyboard\xib中的文字內(nèi)容換行
- 快捷鍵: option + 回車鍵
- 在storyboard\xib輸入\n是無法實現(xiàn)換行的
- 在代碼中輸入\n是可以實現(xiàn)換行的
self.label.text = @"534534534\n5345345\n5345";
修改狀態(tài)欄樣式
-
使用UIApplication來管理
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
在Info.plist中做了圖中的配置,可能會出現(xiàn)以下警告信息
- 使用UIViewController來管理
@implementation LYWLoginRegisterViewController
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
@end
在xib\storyboard中使用KVC
修改UITextField的光標(biāo)顏色
textField.tintColor = [UIColor whiteColor];
UITextField占位文字相關(guān)的設(shè)置
// 設(shè)置占位文字內(nèi)容
@property(nullable, nonatomic,copy) NSString *placeholder;
// 設(shè)置帶有屬性的占位文字, 優(yōu)先級 > placeholder
@property(nullable, nonatomic,copy) NSAttributedString *attributedPlaceholder;
NSAttributedString
- 帶有屬性的字符串, 富文本
- 由2部分組成
- 文字內(nèi)容 : NSString *
- 文字屬性 : NSDictionary *
- 文字顏色 - NSForegroundColorAttributeName
- 字體大小 - NSFontAttributeName
- 下劃線 - NSUnderlineStyleAttributeName
- 背景色 - NSBackgroundColorAttributeName
- 初始化
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
attributes[NSForegroundColorAttributeName] = [UIColor yellowColor];
attributes[NSBackgroundColorAttributeName] = [UIColor redColor];
attributes[NSUnderlineStyleAttributeName] = @YES;
NSAttributedString *string = [[NSAttributedString alloc] initWithString:@"123" attributes:attributes];
- 使用場合
- UILabel - attributedText
- UITextField - attributedPlaceholder
NSMutableAttributedString
- 繼承自NSAttributedString
- 常見方法
// 設(shè)置range范圍的屬性, 重復(fù)設(shè)置同一個范圍的屬性, 最后一次設(shè)置才是有效的(之前的設(shè)置會被覆蓋掉)
- (void)setAttributes:(nullable NSDictionary<NSString *, id> *)attrs range:(NSRange)range;
// 添加range范圍的屬性, 同一個范圍, 可以不斷累加屬性
- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
- (void)addAttributes:(NSDictionary<NSString *, id> *)attrs range:(NSRange)range;
- 圖文混排
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(100, 100, 200, 25);
label.backgroundColor = [UIColor redColor];
label.font = [UIFont systemFontOfSize:14];
[self.view addSubview:label];
// 圖文混排
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] init];
// 1 - 你好
NSAttributedString *first = [[NSAttributedString alloc] initWithString:@"你好"];
[attributedText appendAttributedString:first];
// 2 - 圖片
// 帶有圖片的附件對象
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = [UIImage imageNamed:@"header_cry_icon"];
CGFloat lineH = label.font.lineHeight;
attachment.bounds = CGRectMake(0, - ((label.lyw_height - lineH) * 0.5 - 1), lineH, lineH);
// 將附件對象包裝成一個屬性文字
NSAttributedString *second = [NSAttributedString attributedStringWithAttachment:attachment];
[attributedText appendAttributedString:second];
// 3 - 哈哈哈
NSAttributedString *third = [[NSAttributedString alloc] initWithString:@"哈哈哈"];
[attributedText appendAttributedString:third];
label.attributedText = attributedText;
- 一個Label顯示多行不同字體的文字
UILabel *label = [[UILabel alloc] init];
// 設(shè)置屬性文字
NSString *text = @"你好\n哈哈哈";
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text];
[attributedText addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:10] range:NSMakeRange(0, text.length)];
[attributedText addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:13] range:NSMakeRange(3, 3)];
label.attributedText = attributedText;
// 其他設(shè)置
label.numberOfLines = 0;
label.textAlignment = NSTextAlignmentCenter;
label.frame = CGRectMake(0, 0, 100, 40);
[self.view addSubview:label];
self.navigationItem.titleView = label;
在storyboard\xib中給UIScrollView子控件添加約束
- 給添加一個UIView類型的子控件A(這將是UIScrollView唯一的一個子控件)
- 設(shè)置A距離UIScrollView上下左右間距都為0
-
往A中再添加其他子控件
- 上下滾動(垂直滾動)
-
設(shè)置A的高度(這個高度就是UIScrollView的內(nèi)容高度: contentSize.height)
-
設(shè)置A在UIScrollView中左右居中(水平居中)
-
- 左右滾動(水平滾動)
- 設(shè)置A的寬度(這個寬度就是UIScrollView的內(nèi)容寬度: contentSize.width)
- 設(shè)置A在UIScrollView中上下居中(垂直居中)
- 上下左右滾動(水平垂直滾動)
- 設(shè)置A的寬度(這個寬度就是UIScrollView的內(nèi)容寬度: contentSize.width)
- 設(shè)置A的高度(這個高度就是UIScrollView的內(nèi)容高度: contentSize.height)
修改UITextField占位文字的顏色
- 使用attributedPlaceholder
@property(nullable, nonatomic,copy) NSAttributedString *attributedPlaceholder;
- 重寫- (void)drawPlaceholderInRect:(CGRect)rect;
- (void)drawPlaceholderInRect:(CGRect)rect;
- 修改內(nèi)部占位文字Label的文字顏色
[textField setValue:[UIColor grayColor] forKeyPath:@"placeholderLabel.textColor"];
如何監(jiān)聽一個控件內(nèi)部的事件
- 如果繼承自UIControl
- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
代理
通知
-
利用內(nèi)部的某些機制
- 比如重寫UITextField的
becomeFirstResponder
和resignFirstResponder
來監(jiān)聽UITextField的獲得焦點和失去焦點事件
- 比如重寫UITextField的
assign和weak的區(qū)別
- 本質(zhì)區(qū)別
- 速度比較: __unsafe_unretained > __weak
@property (nonatomic, assign) MyDog *dog; // MyDog *__unsafe_unretained _dog;
__unsafe_unretained的特點:
1.不是強引用, 不能保住OC對象的命
2.如果引用的OC對象銷毀了, 指針并不會被自動清空, 依然指向銷毀的對象(很容易產(chǎn)生野指針錯誤: EXC_BAD_ACCESS)
@property (nonatomic, weak) MyDog *dog; // MyDog * _Nullable __weak _dog;
__weak的特點:
1.不是強引用, 不能保住OC對象的命
2.如果引用的OC對象銷毀了, 指針會被自動清空(變?yōu)閚il), 不再指向銷毀的對象(永遠(yuǎn)不會產(chǎn)生野指針錯誤)
- 用途
- assign一般用在基本數(shù)據(jù)類型上面, 比如int\double等
- weak一般用在代理對象上面, 或者用來解決循環(huán)強引用的問題
監(jiān)聽UITextField的獲得焦點和失去焦點事件
- addTarget
[textField addTarget:target action:@selector(editingDidBegin) forControlEvents:UIControlEventEditingDidBegin];
[textField addTarget:target action:@selector(editingDidEnd) forControlEvents:UIControlEventEditingDidEnd];
UIControlEventEditingDidBegin
1.開始編輯
2.獲得焦點
3.彈出鍵盤
UIControlEventEditingDidEnd
1.結(jié)束編輯
2.失去焦點
3.退下鍵盤
- delegate
textField.delegate = self;
#pragma mark - <UITextFieldDelegate>
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
}
- 通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginEditing) name:UITextFieldTextDidBeginEditingNotification object:textField];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endEditing) name:UITextFieldTextDidEndEditingNotification object:textField];
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)beginEditing
{
}
- (void)endEditing
{
}
- 重寫UITextField的
becomeFirstResponder
和resignFirstResponder
方法
/**
* 調(diào)用時刻 : 成為第一響應(yīng)者(開始編輯\彈出鍵盤\獲得焦點)
*/
- (BOOL)becomeFirstResponder
{
return [super becomeFirstResponder];
}
/**
* 調(diào)用時刻 : 不做第一響應(yīng)者(結(jié)束編輯\退出鍵盤\失去焦點)
*/
- (BOOL)resignFirstResponder
{
return [super resignFirstResponder];
}
枚舉值的某個規(guī)律
- 凡是使用了1 << n格式的枚舉值, 都可以使用|進(jìn)行組合使用
UIControlEventEditingDidBegin = 1 << 16,
UIControlEventEditingChanged = 1 << 17,
UIControlEventEditingDidEnd = 1 << 18,
UIControlEventEditingDidEndOnExit = 1 << 19,
[textField addTarget:self action:@selector(test) forControlEvents:UIControlEventEditingDidBegin | UIControlEventEditingChanged];
通知相關(guān)的補充
使用block監(jiān)聽通知
// object對象發(fā)出了名字為name的通知, 就在queue隊列中執(zhí)行block
self.observer = [[NSNotificationCenter defaultCenter] addObserverForName:UITextFieldTextDidBeginEditingNotification object:self queue:[[NSOperationQueue alloc] init] usingBlock:^(NSNotification * _Nonnull note) {
// 一旦監(jiān)聽到通知, 就會執(zhí)行這個block中的代碼
}];
// 最后需要移除監(jiān)聽
[[NSNotificationCenter defaultCenter] removeObserver:self.observer];
一次性通知(監(jiān)聽1次后就不再監(jiān)聽)
id observer = [[NSNotificationCenter defaultCenter] addObserverForName:UITextFieldTextDidBeginEditingNotification object:self queue:[[NSOperationQueue alloc] init] usingBlock:^(NSNotification * _Nonnull note) {
// 移除通知
[[NSNotificationCenter defaultCenter] removeObserver:observer];
}];
其他
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 因為是在子線程注冊了通知監(jiān)聽器, 所以beginEditing和endEditing會在子線程中執(zhí)行
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginEditing) name:UITextFieldTextDidBeginEditingNotification object:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endEditing) name:UITextFieldTextDidEndEditingNotification object:self];
});
CocoaPods
- Podfile.lock文件
- 最后一次更新Pods時, 所有第三方框架的版本號
- 常用指令的區(qū)別
- pod install
- 會根據(jù)Podfile.lock文件中列舉的版本號來安裝第三方框架
- 如果一開始Podfile.lock文件不存在, 就會按照Podfile文件列舉的版本號來安裝第三方框架
- 安裝框架之前, 默認(rèn)會執(zhí)行pod repo update指令
- pod update
- 將所有第三方框架更新到最新版本, 并且創(chuàng)建一個新的Podfile.lock文件
- 安裝框架之前, 默認(rèn)會執(zhí)行pod repo update指令
- pod install --no-repo-update
- pod update --no-repo-update
- 安裝框架之前, 不會執(zhí)行pod repo update指令
- pod install
利用SDWebImage設(shè)置UIButton的圖片
- 正確用法
[button sd_setImageWithURL:[NSURL URLWithString:url] forState:UIControlStateNormal placeholderImage:image];
解決tableView設(shè)置tableFooterView時contentSize不正確的問題
tableView.tableFooterView = footerView;
// 重新刷新數(shù)據(jù)(會重新計算contentSize)
[tableView reloadData];
查找字符串的常見方法
// 如果range.location == 0, 說明是以searchString開頭
// 如果range.location == NSNotFound或者range.length == 0, 說明沒找到對應(yīng)的字符串
- (NSRange)rangeOfString:(NSString *)searchString;
// 是否以str開頭
- (BOOL)hasPrefix:(NSString *)str;
// 是否以str結(jié)尾
- (BOOL)hasSuffix:(NSString *)str;
// 是否包含了str(不管頭部\中間\尾部)
- (BOOL)containsString:(NSString *)str;
計算某個文件\文件夾的大小
@implementation NSString (LYWExtension)
//- (unsigned long long)fileSize
//{
// // 總大小
// unsigned long long size = 0;
//
// // 文件管理者
// NSFileManager *mgr = [NSFileManager defaultManager];
//
// // 文件屬性
// NSDictionary *attrs = [mgr attributesOfItemAtPath:self error:nil];
//
// if ([attrs.fileType isEqualToString:NSFileTypeDirectory]) { // 文件夾
// // 獲得文件夾的大小 == 獲得文件夾中所有文件的總大小
// NSDirectoryEnumerator *enumerator = [mgr enumeratorAtPath:self];
// for (NSString *subpath in enumerator) {
// // 全路徑
// NSString *fullSubpath = [self stringByAppendingPathComponent:subpath];
// // 累加文件大小
// size += [mgr attributesOfItemAtPath:fullSubpath error:nil].fileSize;
// }
// } else { // 文件
// size = attrs.fileSize;
// }
//
// return size;
//}
- (unsigned long long)fileSize
{
// 總大小
unsigned long long size = 0;
// 文件管理者
NSFileManager *mgr = [NSFileManager defaultManager];
// 是否為文件夾
BOOL isDirectory = NO;
// 路徑是否存在
BOOL exists = [mgr fileExistsAtPath:self isDirectory:&isDirectory];
if (!exists) return size;
if (isDirectory) { // 文件夾
// 獲得文件夾的大小 == 獲得文件夾中所有文件的總大小
NSDirectoryEnumerator *enumerator = [mgr enumeratorAtPath:self];
for (NSString *subpath in enumerator) {
// 全路徑
NSString *fullSubpath = [self stringByAppendingPathComponent:subpath];
// 累加文件大小
size += [mgr attributesOfItemAtPath:fullSubpath error:nil].fileSize;
}
} else { // 文件
size = [mgr attributesOfItemAtPath:self error:nil].fileSize;
}
return size;
}
@end
LYWLog(@"%zd", @"/Users/lyw/Desktop".fileSize);
計算文字的寬度
CGFloat titleW = [字符串 sizeWithFont:字體大小].width;
CGFloat titleW = [字符串 sizeWithAttributes:@{NSFontAttributeName : 字體大小}].width;
有透明度的顏色
[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.2];
[UIColor colorWithWhite:1.0 alpha:0.2];
[[UIColor whiteColor] colorWithAlphaComponent:0.2];
viewWithTag:內(nèi)部的大致實現(xiàn)思路
@implementation UIView
- (UIView *)viewWithTag:(NSInteger)tag
{
if (self.tag == tag) return self;
for (UIView *subview in self.subviews) {
return [subview viewWithTag:tag];
}
}
@end
addObject:和addObjectsFromArray:的區(qū)別
self.topics = @[20, 19, 18]
moreTopics = @[17, 16, 15]
self.topics = @[20, 19, 18, @[17, 16, 15]]
[self.topics addObject:moreTopics];
self.topics = @[20, 19, 18, 17, 16, 15]
[self.topics addObjectsFromArray:moreTopics];
服務(wù)器分頁的做法
服務(wù)器數(shù)據(jù)庫的數(shù)據(jù) = @[23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10]
第1頁數(shù)據(jù) == @[20, 19, 18, 17, 16]
做法1:
發(fā)送page參數(shù) : page=2
第2頁數(shù)據(jù) == @[18, 17, 16, 15, 14]
做法2:
發(fā)送maxid參數(shù) : maxid=16
第2頁數(shù)據(jù) == @[15, 14, 13, 12, 11]
集成MJRefresh
- github
- 基本用法
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewTopics)];
[self.tableView.mj_header beginRefreshing];
self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreTopics)];
利用AFN取消請求
// 取消所有請求
for (NSURLSessionTask *task in self.manager.tasks) {
[task cancel];
}
// 取消所有請求
[self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];
// 關(guān)閉NSURLSession + 取消所有請求
// NSURLSession一旦被關(guān)閉了, 就不能再發(fā)請求
[self.manager invalidateSessionCancelingTasks:YES];
// 注意: 一個請求任務(wù)被取消了(cancel), 會自動調(diào)用AFN請求的failure這個block, block中傳入error參數(shù)的code是NSURLErrorCancelled
NSDateFormatter的作用
- NSString * -> NSDate *
- (nullable NSDate *)dateFromString:(NSString *)string;
- NSDate * -> NSString *
- (NSString *)stringFromDate:(NSDate *)date;
常見的日期格式
NSString * -> NSDate *
- 2015-11-20 09:10:05
// 時間字符串
NSString *string = @"2015-11-20 09:10:05";
// 日期格式化類
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
// 設(shè)置日期格式(為了轉(zhuǎn)換成功)
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
// NSString * -> NSDate *
NSDate *date = [fmt dateFromString:string];
NSLog(@"%@", date);
- 11月-20號/2015年 09-10:05秒
// 時間字符串
NSString *string = @"11月-20號/2015年 09-10:05秒";
// 日期格式化類
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"MM月-dd號/yyyy年 HH-mm:ss秒";
NSLog(@"%@", [fmt dateFromString:string]);
- Tue May 31 17:46:55 +0800 2011
// 時間字符串
NSString *string = @"Tue May 31 17:46:55 +0800 2011";
// 日期格式化類
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
// fmt.dateFormat = @"EEE MMM dd HH:mm:ss ZZZZ yyyy";
// 設(shè)置語言區(qū)域(因為這種時間是歐美常用時間)
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSLog(@"%@", [fmt dateFromString:string]);
- 1745645645645
// 時間戳 : 從1970年1月1號 00:00:00開始走過的毫秒數(shù)
// 時間字符串 - 時間戳
NSString *string = @"1745645645645";
NSTimeInterval second = string.longLongValue / 1000.0;
// 時間戳 -> NSDate *
NSDate *date = [NSDate dateWithTimeIntervalSince1970:second];
NSLog(@"%@", date);
NSCalendar的注意點
#define iOS(version) ([UIDevice currentDevice].systemVersion.doubleValue >= (version))
NSCalendar *calendar = nil;
if ([UIDevice currentDevice].systemVersion.doubleValue >= 8.0) {
calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
} else {
calendar = [NSCalendar currentCalendar];
}
NSCalendar *calendar = nil;
if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
} else {
calendar = [NSCalendar currentCalendar];
}
NSDate * -> NSString *
NSDate *date = [NSDate date];
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy年MM月dd號 HH:mm:ss";
NSString *string = [fmt stringFromDate:date];
獲得日期元素
NSString *string = @"2015-11-20 09:10:05";
NSString *month = [string substringWithRange:NSMakeRange(5, 2)];
NSLog(@"%@", month);
// 時間字符串
NSString *string = @"2015-11-20 09:10:05";
// 日期格式化類
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
// 設(shè)置日期格式(為了轉(zhuǎn)換成功)
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
// NSString * -> NSDate *
NSDate *date = [fmt dateFromString:string];
// 利用NSCalendar處理日期
NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
NSInteger hour = [calendar component:NSCalendarUnitHour fromDate:date];
NSInteger minute = [calendar component:NSCalendarUnitMinute fromDate:date];
NSLog(@"%zd %zd %zd", month, hour, minute);
// 時間字符串
NSString *string = @"2015-11-20 09:10:05";
// 日期格式化類
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
// 設(shè)置日期格式(為了轉(zhuǎn)換成功)
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
// NSString * -> NSDate *
NSDate *date = [fmt dateFromString:string];
// 利用NSCalendar處理日期
NSCalendar *calendar = [NSCalendar currentCalendar];
NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *cmps = [calendar components:unit fromDate:date];
// NSLog(@"%zd %zd %zd", cmps.year, cmps.month, cmps.day);
NSLog(@"%@", cmps);
日期比較
// 時間字符串
NSString *createdAtString = @"2015-11-20 11:10:05";
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSDate *createdAtDate = [fmt dateFromString:createdAtString];
// 手機當(dāng)前時間
NSDate *nowDate = [NSDate date];
/**
NSComparisonResult的取值
NSOrderedAscending = -1L, // 升序, 越往右邊越大
NSOrderedSame, // 相等
NSOrderedDescending // 降序, 越往右邊越小
*/
// 獲得比較結(jié)果(誰大誰小)
NSComparisonResult result = [nowDate compare:createdAtDate];
if (result == NSOrderedAscending) { // 升序, 越往右邊越大
NSLog(@"createdAtDate > nowDate");
} else if (result == NSOrderedDescending) { // 降序, 越往右邊越小
NSLog(@"createdAtDate < nowDate");
} else {
NSLog(@"createdAtDate == nowDate");
}
// 時間字符串
NSString *createdAtString = @"2015-11-20 09:10:05";
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSDate *createdAtDate = [fmt dateFromString:createdAtString];
// 手機當(dāng)前時間
// NSDate *nowDate = [NSDate date];
// 獲得createdAtDate和nowDate的時間間隔(間隔多少秒)
// NSTimeInterval interval = [nowDate timeIntervalSinceDate:createdAtDate];
NSTimeInterval interval = [createdAtDate timeIntervalSinceNow];
NSLog(@"%f", interval);
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
// 時間字符串
NSString *createdAtString = @"2015-11-01 09:10:05";
NSDate *createdAtDate = [fmt dateFromString:createdAtString];
// 其他時間
NSString *otherString = @"2015-10-31 08:56:45";
NSDate *otherDate = [fmt dateFromString:otherString];
// 獲得NSCalendar
NSCalendar *calendar = nil;
if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
} else {
calendar = [NSCalendar currentCalendar];
}
// 獲得日期之間的間隔
NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
NSDateComponents *cmps = [calendar components:unit fromDate:createdAtDate toDate:otherDate options:0];
NSLog(@"%@", cmps);
條件判斷的一些注意點
1.判斷一個數(shù)組中是否有具體內(nèi)容
1> 正確
if (array.count) {
}
2> 錯誤
if (array) {
}
2.判斷一個字符串是否有具體內(nèi)容
1> 正確
if (string.length) {
}
2> 錯誤
if (string) {
}
自動拉伸問題
- 從xib中加載進(jìn)來的控件的
autoresizingMask
屬性值默認(rèn)是UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
- 如果一個控件顯示出來的大小和當(dāng)初設(shè)置的frame大小不一致,有可能是因為
autoresizingMask
屬性值包含了UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
,解決方案
控件.autoresizingMask = UIViewAutoresizingNone;
獲得自定義的所有相簿
// 獲得所有的自定義相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 遍歷所有的自定義相簿
for (PHAssetCollection *assetCollection in assetCollections) {
}
獲得相機膠卷相簿
// 獲得相機膠卷
PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
獲得某個相簿的縮略圖
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步獲得圖片, 只會返回1張圖片
options.synchronous = YES;
// 獲得某個相簿中的所有PHAsset對象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (PHAsset *asset in assets) {
CGSize size = CGSizeZero;
// 從asset中獲得圖片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"%@", result);
}];
}
獲得某個相簿的原圖
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步獲得圖片, 只會返回1張圖片
options.synchronous = YES;
// 獲得某個相簿中的所有PHAsset對象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (PHAsset *asset in assets) {
CGSize size = CGSizeMake(asset.pixelWidth, asset.pixelHeight);
// 從asset中獲得圖片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"%@", result);
}];
}
利用UIImagePickerController挑選圖片
// UIImagePickerController : 可以從系統(tǒng)自帶的App(照片\相機)中獲得圖片
// 判斷相冊是否可以打開
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;
UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
// 打開照片應(yīng)用(顯示所有相簿)
ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
// 打開照片應(yīng)用(只顯示"時刻"這個相簿)
// ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
// 照相機
// ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.delegate = self;
[self presentViewController:ipc animated:YES completion:nil];
#pragma mark - <UIImagePickerControllerDelegate>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
// 銷毀控制器
[picker dismissViewControllerAnimated:YES completion:nil];
// 設(shè)置圖片
self.imageView.image = info[UIImagePickerControllerOriginalImage];
}
NaN錯誤
- 錯誤起因:0被當(dāng)做除數(shù), 比如 10 / 0
最簡單的方法保存圖片到相機膠卷
UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
/**
* 通過UIImageWriteToSavedPhotosAlbum函數(shù)寫入圖片完畢后就會調(diào)用這個方法
*
* @param image 寫入的圖片
* @param error 錯誤信息
* @param contextInfo UIImageWriteToSavedPhotosAlbum函數(shù)的最后一個參數(shù)
*/
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
[SVProgressHUD showErrorWithStatus:@"圖片保存失敗!"];
} else {
[SVProgressHUD showSuccessWithStatus:@"圖片保存成功!"];
}
}
保存圖片到自定義相冊
- (IBAction)save {
/*
PHAuthorizationStatusNotDetermined, 用戶還沒有做出選擇
PHAuthorizationStatusDenied, 用戶拒絕當(dāng)前應(yīng)用訪問相冊(用戶當(dāng)初點擊了"不允許")
PHAuthorizationStatusAuthorized 用戶允許當(dāng)前應(yīng)用訪問相冊(用戶當(dāng)初點擊了"好")
PHAuthorizationStatusRestricted, 因為家長控制, 導(dǎo)致應(yīng)用無法方法相冊(跟用戶的選擇沒有關(guān)系)
*/
// 判斷授權(quán)狀態(tài)
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if (status == PHAuthorizationStatusRestricted) { // 因為家長控制, 導(dǎo)致應(yīng)用無法方法相冊(跟用戶的選擇沒有關(guān)系)
[SVProgressHUD showErrorWithStatus:@"因為系統(tǒng)原因, 無法訪問相冊"];
} else if (status == PHAuthorizationStatusDenied) { // 用戶拒絕當(dāng)前應(yīng)用訪問相冊(用戶當(dāng)初點擊了"不允許")
LYWLog(@"提醒用戶去[設(shè)置-隱私-照片-xxx]打開訪問開關(guān)");
} else if (status == PHAuthorizationStatusAuthorized) { // 用戶允許當(dāng)前應(yīng)用訪問相冊(用戶當(dāng)初點擊了"好")
[self saveImage];
} else if (status == PHAuthorizationStatusNotDetermined) { // 用戶還沒有做出選擇
// 彈框請求用戶授權(quán)
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized) { // 用戶點擊了好
[self saveImage];
}
}];
}
}
- (void)saveImage
{
// PHAsset : 一個資源, 比如一張圖片\一段視頻
// PHAssetCollection : 一個相簿
// PHAsset的標(biāo)識, 利用這個標(biāo)識可以找到對應(yīng)的PHAsset對象(圖片對象)
__block NSString *assetLocalIdentifier = nil;
// 如果想對"相冊"進(jìn)行修改(增刪改), 那么修改代碼必須放在[PHPhotoLibrary sharedPhotoLibrary]的performChanges方法的block中
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
// 1.保存圖片A到"相機膠卷"中
// 創(chuàng)建圖片的請求
assetLocalIdentifier = [PHAssetCreationRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset.localIdentifier;
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success == NO) {
[self showError:@"保存圖片失敗!"];
return;
}
// 2.獲得相簿
PHAssetCollection *createdAssetCollection = [self createdAssetCollection];
if (createdAssetCollection == nil) {
[self showError:@"創(chuàng)建相簿失敗!"];
return;
}
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
// 3.添加"相機膠卷"中的圖片A到"相簿"D中
// 獲得圖片
PHAsset *asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetLocalIdentifier] options:nil].lastObject;
// 添加圖片到相簿中的請求
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];
// 添加圖片到相簿
[request addAssets:@[asset]];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success == NO) {
[self showError:@"保存圖片失敗!"];;
} else {
[self showSuccess:@"保存圖片成功!"];;
}
}];
}];
}
/**
* 獲得相簿
*/
- (PHAssetCollection *)createdAssetCollection
{
// 從已存在相簿中查找這個應(yīng)用對應(yīng)的相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *assetCollection in assetCollections) {
if ([assetCollection.localizedTitle isEqualToString:LYWAssetCollectionTitle]) {
return assetCollection;
}
}
// 沒有找到對應(yīng)的相簿, 得創(chuàng)建新的相簿
// 錯誤信息
NSError *error = nil;
// PHAssetCollection的標(biāo)識, 利用這個標(biāo)識可以找到對應(yīng)的PHAssetCollection對象(相簿對象)
__block NSString *assetCollectionLocalIdentifier = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
// 創(chuàng)建相簿的請求
assetCollectionLocalIdentifier = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:LYWAssetCollectionTitle].placeholderForCreatedAssetCollection.localIdentifier;
} error:&error];
// 如果有錯誤信息
if (error) return nil;
// 獲得剛才創(chuàng)建的相簿
return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetCollectionLocalIdentifier] options:nil].lastObject;
}
- (void)showSuccess:(NSString *)text
{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:text];
});
}
- (void)showError:(NSString *)text
{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showErrorWithStatus:text];
});
}
Xcode插件的安裝路徑
/Users/用戶名/Library/Application Support/Developer/Shared/Xcode/Plug-ins
屬性名注意點
- 對象屬性名不能以new開頭
@property (nonatomic, strong) NSMutableArray<LYWComment *> *newComments;
常見錯誤
-[__NSArray0 objectForKeyedSubscript:]: unrecognized selector sent to instance 0x7fb738c01870
// 錯誤地將NSArray當(dāng)做NSDictionary來使用了
block細(xì)節(jié)
- 如果【block內(nèi)部】使用【外部聲明的強引用】訪問【對象A】, 那么【block內(nèi)部】會自動產(chǎn)生一個【強引用】指向【對象A】
- 如果【block內(nèi)部】使用【外部聲明的弱引用】訪問【對象A】, 那么【block內(nèi)部】會自動產(chǎn)生一個【弱引用】指向【對象A】
矩形框比較的2個函數(shù)
- bool CGRectContainsRect(CGRect rect1, CGRect rect2)
- 判斷rect1是否包含了rect2
- bool CGRectIntersectsRect(CGRect rect1, CGRect rect2)
- 判斷rect1和rect2是否有重疊
注意:rect1和rect2要在同一個坐標(biāo)系,比較結(jié)果才準(zhǔn)確
轉(zhuǎn)換坐標(biāo)系總結(jié)
view2坐標(biāo)系 : 以view2的左上角為坐標(biāo)原點
view1坐標(biāo)系 : 以view1的左上角為坐標(biāo)原點
CGRect newRect = [view1 convertRect:rect fromView:view2];
// 讓rect這個矩形框宦言, 從view2坐標(biāo)系轉(zhuǎn)換到view1坐標(biāo)系, 得出一個新的矩形框newRect
// rect和view2的含義 : 用來確定矩形框原來在哪
CGRect newRect = [view1 convertRect:rect toView:view2];
// 讓rect這個矩形框杨耙, 從view1坐標(biāo)系轉(zhuǎn)換到view2坐標(biāo)系, 得出一個新的矩形框newRect
// rect和view1的含義 :用來確定矩形框原來在哪
獲得一個控件在window中的位置和尺寸
- 以獲得redView在window中的位置和尺寸為例
CGRect newRect = [[UIApplication sharedApplication].keyWindow convertRect:redView.bounds fromView:redView];
CGRect newRect = [[UIApplication sharedApplication].keyWindow convertRect:redView.frame fromView:redView.superview];
CGRect newRect = [redView convertRect:redView.bounds toView:[UIApplication sharedApplication].keyWindow];
CGRect newRect = [redView.superview convertRect:redView.frame toView:[UIApplication sharedApplication].keyWindow];
CGRect newRect = [redView convertRect:redView.bounds toView:nil];
CGRect newRect = [redView.superview convertRect:redView.frame toView:nil];
關(guān)于tableView的估算高度的那個屬性的深入研究
// 所有cell的高度 -> contentSize.height -> 滾動條長度
// 1000 * 20 -> contentSize.height -> 滾動條長度
// contentSize.height -> 200 * 20 -> 16800
/*
使用estimatedRowHeight的優(yōu)缺點
1.優(yōu)點
1> 可以降低tableView:heightForRowAtIndexPath:方法的調(diào)用頻率
2> 將【計算cell高度的操作】延遲執(zhí)行了(相當(dāng)于cell高度的計算是懶加載的)
2.缺點
1> 滾動條長度不準(zhǔn)確捧弃、不穩(wěn)定医咨,甚至有卡頓效果(如果不使用estimatedRowHeight,滾動條的長度就是準(zhǔn)確的)
*/
/**
這個方法的特點:
1.默認(rèn)情況下(沒有設(shè)置estimatedRowHeight的情況下)
1> 每次刷新表格時误续,有多少數(shù)據(jù)飘哨,這個方法就一次性調(diào)用多少次(比如有100條數(shù)據(jù),每次reloadData時尼啡,這個方法就會一次性調(diào)用100次)
2> 每當(dāng)有cell進(jìn)入屏幕范圍內(nèi)暂衡,就會調(diào)用一次這個方法
2.設(shè)置estimatedRowHeight的情況下
1> 用到了(顯示了)哪個cell,才會調(diào)用這個方法計算那個cell的高度(方法調(diào)用頻率降低了)
*/