开发中容易忽略并且比较重要的一些细小的知识点, 记录下来方便以后查阅, 本文会持续更新.
iOS跳转定位系统设置
OC:
1 |
|
swift:
1 |
|
使用tableview的第一行作为header,点击时判断第一行的快捷方法:
1 |
|
两个并排的label如何让其中一个有限完全展示
常规约束设置如下
label1.snp.makeConstraints { (make) in make.leading.equalTo(12) make.top.equalTo(100) } label2.snp.makeConstraints { (make) in make.leading.equalTo(label1.snp.trailing) make.top.equalTo(100) make.trailing.equalTo(-12) }但是我们希望有限展示完黄色的label,那么我们可以这么做,设置控件的抗压缩因素:
1 |
|
设置之后如下图:
另外还有一个抗拉伸因素:
1 |
|
使用Instruments调试的时候,无法定位到xcode代码
解决办法: Build Options > Debug Information Format >选择debug 中DWARF with dSYM File
读取PDF的多种方式
- 使用UIWebView读取PDF
- 使用第三方框架读取, 推荐使用Reader
如果PDF为加密文档, 使用UIWebView方式读取会自动弹框要求输入密码, 如下图:
使用框架Reader解析PDF是直接将PDF绘制出来, 界面不会弹出输入密码的界面, 而是需要开发者在代码中输入密码, 对用户来说无法感知此PDF是否经过密码加密.
Swift读取plist文件,然后使用SwiftyJson转化成json
1 |
|
UITableView使用block删除或者插入cell时, cell绑定的indexPath不对造成的越界问题
写法:
1 |
|
原因: cell所持有的indexPath在删除一个cell后没有及时变更, 造成cell的indexPath不准确.
正确做法:通过 tableView.indexPath(for: cell)
来获取准确的cell下标, 代码如下
1 |
|
swift如何声明只读属性
-
方法一: 使用
private(set)
修饰属性1
2
3
4
5
6
7
8
9
10
11class ReadOnly { private(set) var name: String init(_ name: String) { self.name = name } } let obj = ReadOnly.init("hah") //以下代码会报错 obj.name = "hahh"
-
方法二: 使用计算属性
1
2
3
4
5
6
7class ReadOnly { var name: String { get { return "" } } }
Slicing (点九图)
Swift 和 OC 混编注意事项
OC不能继承Swift的类
OC不能使用Swift的结构体
OC中定义为readonly的属性, 如果重写了get方法, 那么系统不会自动给我们生成成员变量, 我们要手动去生成, 生成方式有如下两种
-
@dynamic 属性名 = _属性名
-
直接定义成员变量
{Class *_属性名}
有没有定义想屏幕宽度, 高度等常量, 因为常量是不变的, 即使屏幕旋转他们也不会变化, 如果你的布局依赖这些常量, 屏幕旋转的时候一定要注意, 例如
1 |
|
autoresizingMask容易被误解
-
flexibleLeftMargin 左边自适应, 保证右边和俯视图对齐
-
flexibleWidth 宽度自适应, 保证左右和俯视图对齐
-
flexibleRightMargin 右边自适应, 保证左边和俯视图对齐
-
flexibleTopMargin 顶边自适应, 保证底边和俯视图对齐
-
flexibleHeight 高度自适应, 保证顶, 底边和俯视图对齐
-
flexibleBottomMargin 底边自适应, 保证顶边和俯视图对齐
UIVisualEffectView
通常要想创建一个特殊效果(如blur效果),可以创建一个UIVisualEffectView视图对象,这个对象提供了一种简单的方式来实现复杂的视觉效果。这个可以把这个对象看作是效果的一个容器,实际的效果会影响到该视图对象底下的内容,对添加到该视图对象的contentView中的内容不会有模糊效果。
我们举个例子来看看如果使用UIVisualEffectView:
1 |
|
这段代码是在当前视图控制器上添加了一个UIImageView作为背景图。然后在视图的一小部分中使用了blur效果。
我们可以看到UIVisualEffectView还是非常简单的。需要注意是的,不应该直接添加子视图到UIVisualEffectView视图中,而是应该添加到UIVisualEffectView对象的contentView中。
另外,尽量避免将UIVisualEffectView对象的alpha值设置为小于1.0的值,因为创建半透明的视图会导致系统在离屏渲染时去对UIVisualEffectView对象及所有的相关的子视图做混合操作。这不但消耗CPU/GPU,也可能会导致许多效果显示不正确或者根本不显示。
我们在上面看到,初始化一个UIVisualEffectView对象的方法是UIVisualEffectView(effect: blurEffect),其定义如下:
init(effect effect: UIVisualEffect) 这个方法的参数是一个UIVisualEffect对象。我们查看官方文档,可以看到在UIKit中,定义了几个专门用来创建视觉特效的,它们分别是UIVisualEffect、UIBlurEffect和UIVibrancyEffect。它们的继承层次如下所示:
1 |
|
UIVisualEffect是一个继承自NSObject的创建视觉效果的基类,然而这个类除了继承自NSObject的属性和方法外,没有提供任何新的属性和方法。其主要目的是用于初始化UIVisualEffectView,在这个初始化方法中可以传入UIBlurEffect或者UIVibrancyEffect对象。
一个UIBlurEffect对象用于将blur(毛玻璃)效果应用于UIVisualEffectView视图下面的内容。如上面的示例所示。不过,这个对象的效果并不影响UIVisualEffectView对象的contentView中的内容。
UIBlurEffect主要定义了三种效果,这些效果由枚举UIBlurEffectStyle来确定,该枚举的定义如下:
1 |
|
与UIBlurEffect不同的是,UIVibrancyEffect主要用于放大和调整UIVisualEffectView视图下面的内容的颜色,同时让UIVisualEffectView的contentView中的内容看起来更加生动。通常UIVibrancyEffect对象是与UIBlurEffect一起使用,主要用于处理在UIBlurEffect特效上的一些显示效果。接上面的代码,我们看看在blur的视图上添加一些新的特效,如下代码所示:
1 |
|
vibrancy特效是取决于颜色值的。所有添加到contentView的子视图都必须实现tintColorDidChange方法并更新自己。需要注意的是,我们使用UIVibrancyEffect(forBlurEffect:)方法创建UIVibrancyEffect时,参数blurEffect必须是我们想加效果的那个blurEffect,否则可能不是我们想要的效果。
另外,UIVibrancyEffect还提供了一个类方法notificationCenterVibrancyEffect,其声明如下:
class func notificationCenterVibrancyEffect() -> UIVibrancyEffect! 这个方法创建一个用于通知中心的Today扩展的vibrancy特效。
参考
1 |
|
获取对应日期所在的月或者年的天数
1 |
|
获取系统语言的方法
1 |
|
url带有中文的解决方案
1 |
|
内容能缩放的webview
1 |
|
swift中代理使用weak声明, 否则释放不了
1 |
|
闭包中使用 [unowned self],防止循环引用, 使用unowned修饰的值一定有值
OC中消除警告的方法
1 |
|
远程推送真机调试的时候能接收到通知, 打成IPA包后就收不到
解决办法: 一般测试打包选的时Hoc, 但是收不到推送, 选择最后一个就可以收到推送
字符串转换成时间会相差8小时
由于不同的时间计算方式导致的额, 解决方法: 使用世界时间
1 |
|
正则匹配手机和固话
1 |
|
_BOOL
@class可连接使用
1 |
|
通过url获取图片
1 |
|
NSNumberFormatter简单用法
1 |
|
UITextField和UITextView输入过程控制数字格式的正则
1 |
|
校验相机权限的方法
1 |
|
提高xcode编译速度的方法
1. 增加XCode执行的线程数
可以根据自己Mac的性能,更改线程数设置5:
1 |
|
另外也有一个设置可以开启(显示比编译时间):
1 |
|
XCode默认使用与CPU核数相同的线程来进行编译,但由于编译过程中的IO操作往往比CPU运算要多,因此适当的提升线程数可以在一定程度上加快编译速度。
2.将Debug Information Format改为DWARF
在工程对应Target的Build Settings中,找到 Debug Information Format这一项,将Debug时的DWARF with dSYM file 改为 DWARF。
这一项设置的是是否将调试信息加入到可执行文件中,改为DWARF后,如果程序崩溃,将无法输出崩溃位置对应的函数堆栈,但由于Debug模式下可以在XCode中查看调试信息,所以改为DWARF影响并不大。这一项更改完之后,可以大幅提升编译速度。
比如在目前本人负责的项目中,由于依赖了多个Target,所以需要在每个Target的Debug Information Format设置为DWARF。顺便提一下,如果通过Cocoapod引入第三方则Debug Information Format默认就是设置为DWARF的。
3.将Build Active Architecture Only改为Yes
在工程对应Target的Build Settings中,找到Build Active Architecture Only这一项,将Debug时的NO改为Yes。
这一项设置的是是否仅编译当前架构的版本,如果为NO,会编译所有架构的版本。需要注意的是,此选项在Release模式下必须为NO`,否则发布的ipa在部分设备上将不能运行。这一项更改完之后,可以显著提高编译速度。
备注: Debug Information Format和Link Time Optimizations可能会使调试模式出现各种问题,比如无法打印参数的值等,不建议更改
获取iOS设备ip地址
1 |
|
+ (NSString *)getIPAddress:(BOOL)preferIPv4 { NSArray *searchArray = preferIPv4 ? @[ IOS_VPN @”/” IP_ADDR_IPv4, IOS_VPN @”/” IP_ADDR_IPv6, IOS_WIFI @”/” IP_ADDR_IPv4, IOS_WIFI @”/” IP_ADDR_IPv6, IOS_CELLULAR @”/” IP_ADDR_IPv4, IOS_CELLULAR @”/” IP_ADDR_IPv6 ] : @[ IOS_VPN @”/” IP_ADDR_IPv6, IOS_VPN @”/” IP_ADDR_IPv4, IOS_WIFI @”/” IP_ADDR_IPv6, IOS_WIFI @”/” IP_ADDR_IPv4, IOS_CELLULAR @”/” IP_ADDR_IPv6, IOS_CELLULAR @”/” IP_ADDR_IPv4 ] ;
1 |
|
+ (NSDictionary *)getIPAddresses { NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
1 |
|
获取运营商信息
1 |
|
UIWebview自定义UserAgent的方法:
下是错误的方法
1 |
|
正确方法如下:
1 |
|
裁剪指定位置的圆角
OC
1 |
|
Swift
1 |
|
实例变量和属性良好使用习惯
1,在对象内部写入数据使用属性, 读取数据使用实例变量
2,在init 和 dealloc方法中只用是实例变量
3,使用过懒加载的,使用属性
对象的等同性判断
将汉字转化成拼音
1 |
|
两种加载xib文件的性能对比
第一种:[[NSBundle mainBundle] loadNibNamed:@”DataExplainViewController” owner:self options:nil].lastObject;
第二种: UINib *uinib = [UINib nibWithNibName:@”DataExplainViewController” bundle:nil]; self.view = [uinib instantiateWithOwner:self options:nil].lastObject;
第一种加载方式是使用读取文件, 并没有将读取的信息缓存, 所以高频操作会有降低性能; 第二种加载方式将读取的文件缓存到了内存中。
xib中的External Object 和 Object
External Object 使用在xib中, Object使用在SB中。 External Object 只能通过 [[NSBundle mainBundle] loadNibNamed:@”PersonView” owner:self options:dict] 方法配置,具体配置方法如下:
1 |
|
在xib中配置好external object 关联的类的class和 identifier之后就能将控件链接到此类中, 如果控件同事链接到了external Object类和控制器中, 那么但按钮事件触发是会同时调用。(可分别用来更新UI和实现业务逻辑)
Object只需要关联好类即可实现nsobject类和控件的关联
IB_DESIGNABLE 和 IBInspectable
1、IB_DESIGNABLE:能在xib上实时显示自定义view的效果 2、IBInspectable :能在xib的属性中控制自定义view的属性 3、使用方法如下:
1 |
|
pushMeBaby编译报错解决办法
1 |
|
重写hitTest:withEvent:返回指定view
想让谁成为最合适的view就重写谁自己的父控件的hitTest:withEvent:方法返回指定的子控件,或者重写自己的hitTest:withEvent:方法 return self。但是,建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view!
原因在于在自己的hitTest:withEvent:方法中返回自己有时候会出现问题。因为会存在这么一种情况:当遍历子控件时,如果触摸点不在子控件A自己身上而是在子控件B身上,还要要求返回子控件A作为最合适的view,采用返回自己的方法可能会导致还没有来得及遍历A自己,就有可能已经遍历了点真正所在的view,也就是B。这就导致了返回的不是自己而是触摸点真正所在的view。所以还是建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view! 例如:whiteView有redView和greenView两个子控件。redView先添加,greenView后添加。如果要求无论点击那里都要让redView作为最合适的view(把事件交给redView来处理)那么只能在whiteView的hitTest:withEvent:方法中return self.subViews[0];这种情况下在redView的hitTest:withEvent:方法中return self;是不好使的!
“xxx.h” file not found 解决办法
解决方法: 打开 Project->Info->Configurations,查看Configurations里面Debug 和Release是否有为None的配置项, 如果有改正即可
Xcode10编译项目报错: library not found for -lstdc++.6.0.9
原因: 苹果在XCode10中移除了libstdc++(libstdc++.6、libstdc++6.0.9)库。 解决办法: 从xcode9中将这个库复制一份,放到xcode10的安装目录中, 然后重启.具体步骤如下:
模拟器
-
在finder中打开应用程序,找到xcode的9的安装目录, 右键显示包内容->contents->developer->platforms->iphoneSimulator.platform->developer->sdks->iphoneSimulator.sdk->usr->lib, 最后在此目录中找到
libstdc++.6.0.9.tbd
然后复制 - 依照上述步骤找到xcode10的相同目录, 然后把复制的
libstdc++.6.0.9.tbd
粘贴进去 - 重新启动xcode, 编译即可
注意: 以上只是解决了模拟器的编译问题, 真机的解决方式同上,
真机
-
在finder中打开应用程序,找到xcode的9的安装目录, 右键显示包内容->contents->developer->platforms->iphoneOs.platform->developer->sdks->iphoneSimulator.sdk->usr->lib, 最后在此目录中找到
libstdc++.6.0.9.tbd
然后复制 - 依照上述步骤找到xcode10的相同目录, 然后把复制的
libstdc++.6.0.9.tbd
粘贴进去 - 重新启动xcode, 编译即可
Xcode10.1 import头文件无法索引
1 |
|
##删除文件之后编译不通过,但是根据报错路径找不到该文件,那么说明该文件已经被删除了
1 |
|
解决办法:
- 找到项目的 项目名.xcodeproj 文件
- 右键显示包内容找到 项目名.pbxproj 文件, 双击打开
- 全局搜索错误提示路径中的文件名, 然后删掉找到的所有内容即可
##将资源拖入工程之后根据bundle路径找不到对应的资源文件.
eg. 将icon.png拖入工程中, 然后通过 let path = Bundle.main.path(forResource: "icon.png", ofType: nil)
寻找资源, 发现 path = nil
.
解决方法: 虽然文件添加到了工程中, 但是没有将其添加到 bundle resources 中, 只需要将其添加进去即可.
点击加号, 添加需要的资源
collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath方法不执行
可能原因:
- 代理
- 设置item的大小, 设置不准确也不会执行, 比如itemsize的高度或者宽度为负数
- 注册
屏幕旋转界面控件尺寸布局不准确, 产生错乱
可能原因:
-
有没有定义想屏幕宽度, 高度等常量, 因为常量是不变的, 即使屏幕旋转他们也不会变化, 如果你的布局依赖这些常量, 屏幕旋转的时候一定要注意, 例如
1
2//这样定义的是常量, 在屏幕旋转的时候UIScreen的值变化, 但是kScreenWidth不会变化, 导致布局错误 //let kScreenWidth = UIScreen.main.bounds.width
swift项目中, 使用pod导入OC库, 在桥接文件中导入报错
eg, swift项目使用pod集成FMDB, 在桥接文件中
#import "FMDB.h"
报"FMDB.h" file not found
.
解决办法按下图操作:
在iOS9.3以上正常运行, 一下就在程序入口崩溃, 异常断点随机
可能原因:
在Xcode8中,如果你的图片资源文件里有16位图或者图片显示模式为P3,并且Deployment Target是iOS9.3以下的就会出现这个问题。(话说我公司的项目里面就出现了一个小按钮,导致了这次崩溃,不知道设计师是怎么弄出来的这个特殊图片…)如果你的App需要支持wide color functionality,那你就必须设置Deployment Target为iOS9.3以上。如果你的APP不需要支持wide color functionality并且你希望兼容iOS老版本,那么你需要将所有16-bit or P3 assets的图片转换为8-bit sRGB assets
定位到问题图片:
1.打一个ipa包,解压你的应用的ipa包,进入到你应用的Playload文件夹。
2.用find命令定位到Assets.car文件
find . -name 'Assets.car'
3.使用 assetutil 命令导出图片的信息存储到Assets.json文件中
sudo xcrun --sdk iphoneos assetutil --info Assets.car的文件路径 > 生成的Assets.json文件要保存到的路径
4.打开刚才生成的Assets.json文件,查找含有”DisplayGamut” : “P3”, “Encoding” : “ARGB-16″的内容。这个对应的Name就是出现问题的图片了。
1 |
|
正确的图片格式如下:
错误的图片格式可能如下:
app运行启动之后直接崩溃,错误描述如下
1 |
|
pod init出错, 错误如下
1 |
|
### Stack
1 |
|
解决办法一, 可能是由于Xcode安装最新的版本造成的, 在终端执行 gem install cocoapods
即可解决, 如果不能解决请使用方法二.
解决办法二,把Project Format修改成Xcode 8.0-compatible即可(此方法没有从根源解决问题, 比如Swift版本兼容的问题)。如下图
解决办法三, 升级cocoapods, 此方法可以从根源解决问题
执行 gem install cocoapods --pre
之后发现没啥卵用, 因为你的源不对,正确姿势如下:
1, 移除以前的源
查看源的方法: 执行 gem sources -l
, 会看到源的地址, 然后执行 gem sources --remove 源地址
, 即可删除原来的源
2, 添加新的源
gem sources --add 新源地址
这里的地址推荐使用 https://gems.ruby-china.org/
, 然后通过 gem sources -l
查看是否添加成功
3, 安装此源上最新的 cocoapods
gem install cocoapods
安装三方库之后无法导入头文件, 或者导入头文件后报找不到库的错, 特别是OC项目引入Swift库经常出现这种问题, 问题描述如下:
1 |
|
解决方法如下:
1,如果你已经运行了 pod install ,那么关闭并重新打开 Xcode workspace 。如果这样做还没解决问题,那么请接着进行下面的步骤。
2,删除 ~/Library/Developer/Xcode/DerivedData 整个目录,这里面包含了 ModuleCache 。
3,在 Manage Schemes 对话框中,勾选 Quick 、Nimble 、Pods-ProjectnameTests ,然后重新编译它们(Cmd+B)。
使用WebViewJavascriptBridge之后 webview不走代理方法
桥接会覆盖代理设置, 使用第三方多看注意一事项
按照如下方式代理不会生效
1 |
|
使用下面这种方式才会生效
1 |
|
Cordava测试没错, 打包报错
1 |
|
解决办法:
1 |
|
使用沙盒缓存后, 重装app确取不到缓存(知识点正确, 但是不可能出现此种情况)
代码如下:
1 |
|
原因: iOS8之后,苹果添加的新特性,将每次打开app内的沙盒重新生成,并保持上一次的沙盒文件(Documents、Library、tmp)移到新生成的文件内,旧文件删除,就是说,你保存的文件都在,只不过每次打开后,都会有一个新的绝对路径。
所以,使用NSSearchPathForDirectoriesInDomains获取沙河地址时,每次app重新运行都会生成一个不同的的路径。因为苹果现在的沙盒的保护机制。会不断的变化. 示例如下:
1 |
|
其中, 那一串字符串会随机变化. 所以在使用NSFileManager判断文件是否存在, 是找不到换存文件的. 我们只需将NSFileManager判断文件是否存在的代码删掉即可.
正确的代码如下:
1 |
|
运行直接崩溃
1 |
|
真机调试的时候显示这个问题, 版本低的尤其会出现 需要在link binary with library 里面添加 corefoundation.framework 选择option
打电话,录音时由于状态栏变化会是布局改变,
解决办法: 不适用固定的屏幕尺寸(例如宏定义屏幕的宽高等), 而是使用控制器view的宽高, 如果还有不能适配的地方可以监听状态栏变化的通知
同时: 状态栏也会影响启动图
解决办法:启动时隐藏状态栏
引入.mm文件编译报错, 而且错误莫名奇妙, 什么runtime balabala
可能原因: 自己定义的宏名与系统函数重名, 比如NSLog函数
解决办法: 修改重名宏即可
引入.c文件报很多莫名错误, 各种runtime错误
将.c 改为.m即可
pushMeBaby编译报错解决办法
1 |
|
webview支持缩放的方法
1 |
|
webView 去掉黑边的方法
1 |
|
合并模拟器和真机静态库
分别编译模拟器和真机的静态库,然后使用终端合并, $lipo -create 1.a 2.a -output name.a 最终生成真机和模拟器都能用的 name.a 静态库
查询静态库信息
1 |
|
将错误信息发送到指定邮箱
在appDelegate中写此方法: 会将bug以邮件的方式放送给指定的邮箱
1 |
|
IB_DESIGNABLE 和 IBInspectable
1、IB_DESIGNABLE:能在xib上实时显示自定义view的效果
2、IBInspectable :能在xib的属性中控制自定义view的属性
3、使用方法如下:
1 |
|
xib中的External Object 和 Object
External Object 使用在xib中, Object使用在SB中。 External Object 只能通过 [[NSBundle mainBundle] loadNibNamed:@”PersonView” owner:self options:dict] 方法配置,具体配置方法如下:
1 |
|
在xib中配置好external object 关联的类的class和 identifier之后就能将控件链接到此类中, 如果控件同事链接到了external Object类和控制器中, 那么但按钮事件触发是会同时调用。(可分别用来更新UI和实现业务逻辑)
Object只需要关联好类即可实现nsobject类和控件的关联
两种加载xib文件的性能对比
第一种:[[NSBundle mainBundle] loadNibNamed:@”DataExplainViewController” owner:self options:nil].lastObject;
第二种: UINib *uinib = [UINib nibWithNibName:@”DataExplainViewController” bundle:nil]; self.view = [uinib instantiateWithOwner:self options:nil].lastObject;
第一种加载方式是使用读取文件, 并没有将读取的信息缓存, 所以高频操作会有降低性能;
第二种加载方式将读取的文件缓存到了内存中。
判断运行环境
这些宏定义在如下位置,是模拟器或者真机系统里面的
1 |
|
取消某个控制器的左滑返回手势
1 |
|
将汉字转化成拼音
1 |
|