在开发中经常会遇到一些问题,刚开始感觉匪夷所思,但是当你真正探究,理解了就会发现确实如此。
19、translatesAutoresizingMaskIntoConstraints
translatesAutoresizingMaskIntoConstraints
属性和autolayout有关,
如果你定义的view想用autolayout,就将translatesAutoresizingMaskIntoConstraints设为NO,如果你使用的不是autolayout,就将translatesAutoresizingMaskIntoConstraints设为YES,对应关系如下
autolayout | translatesAutoresizingMaskIntoConstraints |
---|---|
是 | NO |
否 | YES |
18、navigationBar setBackgroundImage和setBarTintColor区别
在处理导航要不要透明时发现了下面的问题,
[nav.navigationBarsetBackgroundImage:[UIImageimageNamed:@"bt_green.png"]forBarMetrics:UIBarMetricsDefault];
用这个来跑的效果是在Xib里UI不用+64像素,
[nav.navigationBar setBarTintColor:[ColorTool colorWithHexString:COLOR_THEME_NAVIGATION]]; [nav.navigationBar setTintColor:[ColorTool colorWithHexString:COLOR_THEME_NAVIGATION]];
使用这2个方法来定义导航颜色时,在Xib里的UI实际位置需要+64个像素,
使用设置了
nav.navigationBar.translucent =NO;
在配合上面2个方法就能达到和setBackgroundImage
一样的效果。这都是在ios7之后的变化。
可以去体验下。
- navigation controller容器中布局到ios7中往上偏移了64px
iOS6中默认的布局将从navigation bar的底部开始,但到了iOS7中默认布局从navigation bar的顶部开始,这就是为什么所有的UI元素都往上漂移了。因为在iOS7中,苹果引入了一个新的属性,叫做[UIViewController setEdgesForExtendedLayout:]
,它的默认值为UIRectEdgeAll,使用edgesForExtendedLayout指定视图的哪条边需要扩展,不用理会操作栏的透明度。所以这种情况快速修复的方法是:在-(void)viewDidLoad中添加如下一行代码:
self.edgesForExtendedLayout = UIRectEdgeNone;
extendedLayoutIncludesOpaqueBars
关于这个属性的测试版本中默认值是YES,正式版本是NO!
如果你使用了不透明的navigation bar,设置edgesForExtendedLayout 还是默认值UIRectEdgeAll,你又想整个view全屏(navigation bar下面的内容网上漂移64px) extendedLayoutIncludesOpaqueBars 的值设置为YES。
17、other linker flags参数的作用
在前面我们说如果出现问题要在Other Linker Flags中加入-ObjC或者-all_load或者-force_load,我们为什么要加入这样的参数呢,他们究竟做了什么事呢?下面就是对这个三个参数的一个讲解.
ObjC
: 一般这个参数足够解决前面提到的问题,这个flag告诉链接器把库中定义的Objective-C类和Category都加载进来。这样编译之后的app会变大,因为加载了很多不必要的文件而导致可执行文件变大。但是如果静态库中有类和category的话只有加入这个flag才行,但是Objc也不是万能的,当静态库中只有分类而没有类的时候,Objc就失效了,这就需要使用-all_load或者-force_load了。-all_load
: -all_load会强制链接器把目标文件都加载进来,即使没有objc代码。但是这个参数也有一个弊端,那就是你使用了不止一个静态库文件,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件 这里会有两种方法解决 1:用命令行就行拆包. 2:就是用下面的这个参数-force_load
: 这个flag所做的事情跟-all_load其实是一样的,只是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载 .
总结
-
个人建议ObjC与force_load搭配使用比较好.
16、 如果项目中打了断点,但是Debug时不停,那可能时BuildSettings中了关掉了。修改Generate Debug Symbols
为YES
。
15、数组中排序可能使用 NSStringCompareOptions,每个参数的意义如下:
typedefNS_OPTIONS(NSUInteger, NSStringCompareOptions) {
NSCaseInsensitiveSearch = 1, //不区分大小写比较
NSLiteralSearch = 2, //逐字节比较 区分大小写
NSBackwardsSearch = 4, //从字符串末尾开始搜索
NSAnchoredSearch = 8, //搜索限制范围的字符串
NSNumericSearch = 64, //按照字符串里的数字为依据,算出顺序。例如 Foo2.txt < Foo7.txt < Foo25.txt
NSDiacriticInsensitiveSearchNS_ENUM_AVAILABLE(10_5, 2_0) = 128,//忽略 "-" 符号的比较
NSWidthInsensitiveSearchNS_ENUM_AVAILABLE(10_5, 2_0) = 256,//忽略字符串的长度,比较出结果
NSForcedOrderingSearchNS_ENUM_AVAILABLE(10_5, 2_0) = 512,//忽略不区分大小写比较的选项,并强制返回 NSOrderedAscending 或者 NSOrderedDescending
NSRegularExpressionSearchNS_ENUM_AVAILABLE(10_7, 3_2) = 1024 //只能应用于 rangeOfString:..., stringByReplacingOccurrencesOfString:...和 replaceOccurrencesOfString:... 方法。使用通用兼容的比较方法,如果设置此项,可以去掉 NSCaseInsensitiveSearch 和 NSAnchoredSearch
};
14、NavigationBar自定义高度和调整子控件的位置
- 设置navigationbar的高度
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, 64)];
[self.navigationController.navigationBar addSubview:view];
- 设置子空间的位置
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController.navigationBar setTitleVerticalPositionAdjustment:20.0 forBarMetrics:UIBarMetricsDefault];
[self.navigationItem.leftBarButtonItem setBackgroundVerticalPositionAdjustment:20.0 forBarMetrics:UIBarMetricsDefault];
}
- (void)viewDidDisappear:(BOOL)animated{
[self.navigationController.navigationBar setTitleVerticalPositionAdjustment:0.0 forBarMetrics:UIBarMetricsDefault];
[self.navigationItem.leftBarButtonItem setBackgroundVerticalPositionAdjustment:0.0 forBarMetrics:UIBarMetricsDefault];
}
注:上述运行结果的前提是使用自定义图片的leftBarButtonItem作为返回按钮替代系统默认的 backBarButtonItem,并且你的leftBarButtonItem是使用 initWithImage:(UIImage *)image style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action这个方法创建的(原因我后面会讲)。
问题1:系统默认的导航栏返回按钮垂直位置无法调节。
当返回按钮使用系统默认的backBarButtonItem的时候,使用UIBarButtonItem的- (void)setBackButtonBackgroundVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics来调整它的垂直位置,不起作用。
问题2:自定义的返回按钮在导航栏中的垂直位置仅在某一种情况下可以调节。
后来我又发现,即使不用系统默认地返回按钮,使用自定义的leftBarButtonItem,也只在使用 initWithImage:style target:action:这个方法创建的UIBarButtonItem时生效,使用其他init方法情况一律无效。至于什么原因不明觉厉。
参考:小荷才露尖尖角的iOS 如何自定义NavigationBar的高度
13、point的转换
-(CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;//点转换
-(CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;//点转换
-(CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;//矩形转换
-(CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;//矩形转换
使用注意:
1.使用convertPoint:toView:时,调用者应为covertPoint的父视图。即调用者应为point的父控件。toView即为需要转换到的视图坐标系,以此视图的左上角为(0,0)点。
2.使用convertPoint:fromView:时正好相反,调用者为需要转换到的视图坐标系。fromView为point所在的父控件。
3.toView可以为nil。此时相当于toView传入self.view.window
12、CATransform3D是一个4 x 4的矩阵,矩阵中每一个值所代表的意义
struct CATransform3D
{
CGFloat m11(x缩放), m12(y切变), m13(旋转), m14();
CGFloat m21(x切变), m22(y缩放), m23(), m24();
CGFloat m31(旋转), m32( ), m33(), m34(透视效果,要操作的这个对象要有旋转的角度,否则没有效果。正直/负值都有意义);
CGFloat m41(x平移), m42(y平移), m43(z平移), m44();
};
11、Xcode7 升级到Xcode8 一编写代码就闪退问题,记录下,希望对有些小伙伴有用。PS:也是网上友人的解决方法。
xcode升级到8之后 ,插件不能用了,就又从心装了一下插件装完插件之后,再打开xcode,发现一写代码就闪退,很是郁闷。。。网上找了一下资料,发现是插件KSImageName的问题,于是把这个插件删除,重启了一下xcode就可以了
xcode插件的路径:~/Library/Developer/Xcode/Plug-ins
老版本:~/Library/Developer/Application Support/Developer/Shared/Xcode/Plug-ins
10、Xcode 工程文件打开不出来, cannot be opened because the project file cannot be parsed.
svn更新代码后,打开xcode工程文件,会出现 xxx..xcodeproj cannot be opened because the project file cannot be parsed.
因为.xcodeproj工程文件冲突了,然后还是会强制更新,内部文件出现了冲突,所以解析不了文件。
会出现这样的冲突消息
<<<<<<< .mine 9ADAAC6A15DCEF6A0019ACA8 .... in Resources */, ======= 52FD7F3D15DCEAEF009E9322 ... in Resources */, >>>>>>> .r269
解决方法:
- 1.对.xcodeproj 文件右键,显示包内容
- 2.双击打开 project.pbxproj 文件
- 3.找到以上类似的冲突信息(可以用commad + f 搜索)
- 4.删除 <<<<<<<,======,>>>>>>这些行
- 5.保存,退出
- 6.重新打开.xcodeproj文件即可
9 、button 文字图片上下/左右经常会用到,记录一下
- 上下:
self.rechargeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;//使图片和文字水平居中显示
[self.rechargeButton setTitleEdgeInsets:UIEdgeInsetsMake(self.rechargeButton.imageView.frame.size.height+10 ,-self.rechargeButton.imageView.frame.size.width, 0.0,0.0)];//文字距离上边框的距离增加imageView的高度,距离左边框减少imageView的宽度,距离下边框和右边框距离不变
[self.rechargeButton setImageEdgeInsets:UIEdgeInsetsMake(-10, 0.0,0.0, -self.rechargeButton.titleLabel.bounds.size.width)];//图片距离右边框距离减少图片的宽度,其它不边
- 左右:(因为默认button 图片在左,文字在右, 下面代码是反过来的: 文字 图片)
[self.DetailButton setTitleEdgeInsets:UIEdgeInsetsMake(0, -self.DetailButton.imageView.bounds.size.width, 0, self.DetailButton.imageView.bounds.size.width)];
[self.DetailButton setImageEdgeInsets:UIEdgeInsetsMake(0, self.DetailButton.titleLabel.bounds.size.width, 0, -self.DetailButton.titleLabel.bounds.size.width)];
8、解决pod update 更新缓慢的问题。
第一次导入第三包:
pod install --verbose --no-repo-update
以后每次更新:
pod update --verbose --no-repo-update
7、三种设置图片圆角的方法
- 1.通过Layer的属性来设置圆角
// 设置圆角半径
view.layer.cornerRadius = cornersSize;
view.layer.masksToBounds = YES;
- 2.通过Layer和bezierPath来设置圆角,下面的方法是写在UIImageView的一个Category中,所以
self
是UIImageView
,可以根据项目需求对方法进行相应的改变:
//设置圆角
- (void)useShaperLayerCornersSize:(CGFloat)cornersSize {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:cornersSize];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
重点:CALayer 有个 mask 属性,用作 layer 的遮罩。这个遮罩和普通盖在上面的显示层不同,普通的遮罩是,盖上去,就遮住了下面的内容,而 mask 则是遮什么显示什么。
- 3、通过Graphics 和 BezierPath 设置圆角,下面这个方法也是写在
UIImageView
的分类中:
- (void) userGraphicsCornersSize:(CGFloat )cornersSize{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 1.f);
[[UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.frame.size.width] addClip];
[self drawRect:self.bounds];
self.image = UIGraphicsGetImageFromCurrentImageContext();
//结束画图
UIGraphicsEndImageContext();
}
6、UITableView当Style是Plain时,如果数据没有一屏幕,下面的这样显示,没有数据有一行行分割线,这样的界面往往不是我们想要的。
如何让没有数据的行不显示呢?
- 1、
TableView.tableFooterView = [[UIView alloc] init];
,通过设置TableView的footerView来实现。 - 2、
TableView.separatorStyle = UITableViewCellSeparatorStyleNone;
设置不显示分割线来实现。
有时候可能设置BackgroundColor
来使tableView更美观。
5、IOS中NSLog输出格式大全:
格式 | 对象 |
---|---|
%zd | NSInteger |
%tu | NSUInteger |
%02d | 不满两位的整数补0 |
%.2f | 保留两位小数 |
%@ | 对象 |
%d, %i | 整数 |
%u | 无符整形 |
%f | 浮点/双字 |
%x, %X | 二进制整数 |
%o | 八进制整数 |
%zu | size_t |
%p | 指针 |
%e | 浮点/双字 (科学计算) |
%g | 浮点/双字 |
%s | C 字符串 |
%.*s | Pascal字符串 |
%c | 字符 |
%C | unichar |
%lld | 64位长整数(long long) |
%llu | 无符64位长整数 |
%Lf | 64位双字 |
4、如何设置TabBar图片的渲染颜色
-
使用过TabBarController的小伙伴都知道,苹果提供按钮选中的默认颜色是蓝色,假如UI给你一张有颜色的TabBar选中图片,如下:
projecselect.png
但是你会悲催的发现事实不是这样的,而是下面这样的:
QQ20170224-145338.png
如何使用原始的图片呢?
实际上当你设置选中图片时,如果不需要渲染图片,需要这样设置
[tabBarItem setSelectedImage:[[UIImage imageNamed:@"xxx"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
UIImageRenderingModeAlwaysOriginal
这个属性可以完成你所想要的效果。
- 如果你想你的TabBar跟随主题颜色变化,当然也可以提供多套主题颜色相关的图片,但是这样太繁琐了,我们可以通过设置TabBar的tintColor来实现:
self.tabBar.tintColor = [UIColor orangeColor];
3、UITableView分割线
- IOS7以后UITableView的分割线距离左侧会有一点的距离,如何让分割线从屏幕左边开始呢?分别在ViewController中这两个方法中添加如下代码:
//设置分割线距离左侧屏幕距离为零 ios 7;
-(void)viewDidLayoutSubviews
{
if ([self.mainTableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.mainTableView setSeparatorInset:UIEdgeInsetsMake(0,0,0,0)];
}
if ([self.mainTableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.mainTableView setLayoutMargins:UIEdgeInsetsMake(0,0,0,0)];
}
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
2、NavigationBar 设置Item颜色和文字颜色
-
iOS7以前:
- tintColor:设置navigationBar和navigationItem的颜色,navigationItem里面的字体默认为白色,如果想修改navigationItem字体颜色,需要自定义给navigationItem(Custom)。
-
iOS7之后(新增barTintColor属性):
- tintColor:不再是以前的设置navigationBar和navigationItem的颜色,而是变成了只修改navigationItem里面的字体颜色。
- barTintColor:设置navigationBar和navigationItem的颜色,由于iOS7的navigationItem以文字的方式体现,默认为蓝色,所以barTintColor看似乎对navigationItem无效。
此外,如果想修改NavigationBar标题的颜色,可以通过设置
titleTextAttributes
属性来改变,颜色,字体,阴影等都可以设置
NSDictionary * dict = [NSDictionary dictionaryWithObject:color forKey:NSForegroundColorAttributeName];
//大功告成
self.navigationController.navigationBar.titleTextAttributes = dict;
1、图片缓存
应用中经常会加载图片,SDWebImage为我们提供了方便高效的请求网络资源图片的方法,但是有时候我们需要请求的图片可能服务器修改了,但是SDWebImage缓存还没有失效,这样的话就无法正确实时的展示服务器修改的图片。
SDWebImage可以通过
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options
方法中的options - SDWebImageOptions
来设置缓存策略。SDWebImageRefreshCached
每次都刷新缓存,但是这需要服务器配合:setHeader("Cache-Control", "no-cache");
要禁用缓存。-
还有一种方法就是简单粗暴的,直接清空图片缓存
- 一种是磁盘缓存
[[[SDWebImageManager sharedManager] imageCache] clearDisk];
- 一种为内存缓存
[[[SDWebImageManager sharedManager] imageCache] clearMemory];
- 在IOS7中你会发现使用这两个方法缓存总清除不干净,即使断网下还是会有数据。这是因为在IOS7中,缓存机制做了修改,使用上述两个方法只清除了SDWebImage的缓存,没有清除系统的缓存,所以我们可以在清除缓存的代理中额外添加以下
[[NSURLCache sharedURLCache] removeAllCachedResponses];
- 一种是磁盘缓存