title: ios-记录
categories: Ios
tags: [xcode, ios, 记录]
date: 2017-10-17 21:12:17
comments: false
mathjax: true
toc: true
ios-记录
前面
- Objective-C 简介 - https://www.runoob.com/ios/ios-objective-c.html
Enable Bitcode 报错
打 debug (build setting)包默认 enable bitcode 是 on的,关掉即可
相关链接:https://forum.unity.com/threads/set-enable-bitcode-default-value-when-building-for-ios.353236/
如果我们的工程需要支持bitcode,则必要要求所有的引入的第三方库都支持bitcode
http://www.cocoachina.com/ios/20150818/13078.html
xcode 账号管理
证书过期后 build 会报错, 需要删除掉无用的证书, 加入有用的证书
-
xcode -> preferences -> accounts
报错: failed to register bundle identifier
构建时报这个无法注册 包名 (identifier) 的错误, 是因为此包名已经在 AppStore 被使用了
解决办法: 使用一个新包名
Build 与 version 区别
- Xcode进行iOS开发中Build与version区别?build自增设置?build随时间变化? - https://www.jianshu.com/p/a2e10a56fa89
- iOS Xcode中Version和Build的区别 - https://blog.csdn.net/FreeTourW/article/details/53423369
-
Version(应用程序发布版本号)
对应的就是CFBundleShortVersionString。该版本的版本号是三个时期分隔的整数组成的字符串:
第一个整数代表重大修改的版本,如实现新的功能或重大变化的修订。
第二个整数表示的修订,实现较突出的特点。
第三个整数代表维护版本。该键的值不同于CFBundleVersion标识。
如当前上架版本为1.1.0,之后你更新的时候可以改为1.1.1 -
Build(应用程序内部标示)
对应的是CFBundleVersion。标识(发布或未发布)的内部版本号。用以记录开发版本的,每次更新的时候都需要比上一次高。如:当前版本是1,下一次就要大于1,比如2,3。
比如团队打算发布1.0版本的时候,会发布很多build版本供测试或QA团队进行测试,你发布了很多build,因为一直在修改着代码,因此当你收到一条bug信息时候,你怎么知道是哪个build引起的问题呢,这时候build版本号的优点就可以体现出来了。
xocde 下载模拟器
动态库 vs 静态库
- Library vs Framework in iOS - https://juejin.cn/post/6844903687328890887
- iOS 静态库,动态库与 Framework 浅析 - https://www.cnblogs.com/Jenaral/p/5530383.html
关于Static Framework,见:
伪Framework
是指使用Xcode的Bundle来实现的。在使用时和Cocoa Touch Framework没有区别。但通过Framework,可以或者其中包含的资源文件(Image, Plist, Nib)。
framework 编译顺序
模块a 应用了 模块b, 如果 修改了 模块b, 要先编译 模块b (光标移到 模块b 中的某一个文件 cmd+b 即可), 模块a 才能正常调用.
xcode 编辑器
编译设置
-
设置模块的构建类型, build settings -> 搜索 mach
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DrtCsZnd-1612831658423)(http://yxbl.itengshe.com/20210127145544-1.webp)]
-
设置编译的 cpu 架构, build settings -> 搜索 architecture
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t75bIt4V-1612831658424)(http://yxbl.itengshe.com/20210205155013-1.webp)]
-
目标 sdk, build settings -> 搜索 deployment target
-
添加编译 flag. build settings -> 搜索 other linker flags
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B2UNfoUy-1612831658426)(http://yxbl.itengshe.com/20210208232047-1.webp)]
选择目的 模块 进行编译
-
选择目的 target
-
cmd + B 构建, 构建成功后在 Products 目录可以找到 (白色的表示存在)
导出 模块
-
创建一个模块, 如: Classes
-
创建 头文件 UnityAppController.h 和 实现文件 UnityAppController.mm
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fgET0wQB-1612831658428)(http://yxbl.itengshe.com/20210130152633-1.webp)]
-
导出 头文件 UnityAppController.h
在对应的 target 上, 在 头文件 的 public 下添加 UnityAppController.h (可以直接拖文件到 public 下)
-
done. 在其他模块就可以进行导入这个文件了
使用 <> 去导入, 表示引用库中搜索
导入 模块
- 动态库的链接 - https://www.jianshu.com/p/ffa343009789
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5IF5xnIT-1612831658430)(http://yxbl.itengshe.com/20210130155928-1.webp)]
-
target depnedencies(编译前)
这个选项只是告诉工程在运行的时候先去编译这里导入的库.
-
Link Binary With Libraries(编译时期)
Link Binary With Libraries里添加的即你的某个project需要链接的库.
这里添加的库都会被编译到工程的最终包里.
只有在这里添加了.app才能找到该库的.o文件 -
Embedded Binaries(运行时)
这个是告诉工程在app运行时去哪些库里找实现方法.
这个选项只有在可运行的project里有.即你工程的总壳(有main.m文件的project)
不可运行(静.动态库 >> 没有main.m文件)的project是没有这个选项的.因为他们不可能进入运行时状态.
-
总结
-
当你导入一个库时.target dependencies和link binary with libraries两个选项都必须设置.
只有可运行的project里需要设置embedded binaries. -
所以当你引入一个静态库的时候.只需要设置Link binary with libraries选项就可以了.因为他不需要编译.
-
当你embedded 一个库时xcode会自动帮你设置target dependencies 和 link binary with libraries
-
查看证书的 team id
双击证书, organizational unit 就是 team id
单元测试
- iOS-使用Xcode自带单元测试UnitTest - https://www.jianshu.com/p/009844a0b9ed
- https://www.jianshu.com/p/c54f0cc08c20
测试用例方法必须以 test 开头, 如:
- (void)testExample { ... }
执行测试用例
-
执行 全部 测试用例: cmd + U
-
执行 单个 测试用例, 点击测试方法左边的按钮
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sl9JrzZ1-1612831658431)(http://yxbl.itengshe.com/20210128174315-1.webp)]
测试按钮消失的话, 重启 xcode 试试 (卧槽)
快捷键
-
xcode常用快捷键 - https://www.jianshu.com/p/8acd08eda54c
-
编译: cmd + B
-
运行: cmd + R
-
执行 全部 测试用例: cmd + U
-
显示/隐藏 控制台: cmd + shift + Y
-
格式化代码: 1. 选中代码块, 2. ctrl + i
光标移动
- 上一单词: option + ←
- 下一单词: option + →
- 上一次光标: ctrl + cmd + ←
- 下一次光标: ctrl + cmd + →
- 跳转到 定义: ctrl + cmd + J
查找编辑
- 当前文件中查找: cmd + F
- 项目中查找: cmd + shift + F
object-c 语法相关
@property指示符
- iOS @property探究(一): 基础详解 - https://www.jianshu.com/p/646ae400fe7b
- 全面理解Objective-C中的Property属性 - https://www.jianshu.com/p/85890909a81b
在声明属性的时候一般会带上几个指示符,常用指示符有
属性参数主要可以分为三类:
- 原子性: atomic,nonatomic
- 读写语义:readwrite,readonly,getter,setter
- 内存管理语义:assign,weak,unsafe_unretained,retain,strong,copy
指示符 | 作用 |
---|---|
atomic/nonatomic |
指定合成存取方法是否为原子操作,可以理解为是否线程安全,但在iOS上即时使用atomic 也不一定是线程安全的,要保证线程安全需要使用锁机制可以发现几乎所有代码的属性设置都会使用 nonatomic ,这样能够提高访问性能,在iOS中使用锁机制的开销较大,会损耗性能。 |
readwrite/readonly |
readwrite 是编译器的默认选项,表示自动生成getter 和setter ,如果需要getter 和setter 不写即可。readonly 表示只合成getter 而不合成setter 。 |
assign |
assign 表示对属性只进行简单的赋值操作,不更改所赋的新值的引用计数,也不改变旧值的引用计数,常用于标量类型,如NSInteger ,NSUInteger ,CGFloat ,NSTimeInterval 等。 assign 也可以修饰对象如NSString 等类型对象,上面说过使用assign 修饰不会更改所赋的新值的引用计数,也不改变旧值的引用计数,如果当所赋的新值引用计数为0对象被销毁时属性并不知道,编译器不会将该属性置为nil ,指针仍旧指向之前被销毁的内存,这时访问该属性会产生野指针错误并崩溃,因此使用assign 修饰的类型一定要为标量类型。 |
strong |
strong 表示属性对所赋的值持有强引用表示一种“拥有关系”(owning relationship),会先保留新值即增加新值的引用计数,然后再释放旧值即减少旧值的引用计数。只能修饰对象。如果对一些对象需要保持强引用则使用strong 。 |
weak |
weak 表示对所赋的值对象持有弱引用表示一种“非拥有关系”(nonowning relationship),对新值不会增加引用计数,也不会减少旧值的引用计数。所赋的值在引用计数为0被销毁后,weak 修饰的属性会被自动置为nil 能够有效防止野指针错误。 weak 常用在修饰delegate等防止循环引用的场景。 |
copy |
copy 修饰的属性会在内存里拷贝一份对象,两个指针指向不同的内存地址。 一般用来修饰有对应可变类型子类的对象。 如:NSString/NSMutableString ,NSArray/NSMutableArray ,NSDictionary/NSMutableDictionary 等。 为确保这些不可变对象因为可变子类对象影响,需要copy 一份备份,如果不使用copy 修饰,使用strong 或assign 等修饰则会因为多态导致属性值被修改。 |
unsafe_unretained |
使用unsafe_unretained 修饰时效果与assign 相同,不会增加新值的引用计数,也不会减少旧值的引用计数(unretained)当所赋的值被销毁时不会被置为nil 可能会发生野指针错误(unsafe)。unsafe_unretained 与assign 的区别在于,unsafe_unretained 只能修饰对象,不能修饰标量类型,而assign 两者均可修饰。 |
retain |
在ARC环境下使用较少,在MRC下使用效果与strong 一致。 |
h 和 m
- h 是头文件, 声明 方法/变量
- m 是实现文件, 实现 方法
头文件不能写 @implementation, 否则出警告.
编译有先后顺序
编译有先后顺序, 不是有声明就可以. 比如
@interface CHttpJsonRsp : NSObject // 先声明之后
@end
typedef void (^HttpCb)(CHttpJsonRsp* rsp); // 才能使用 CHttpJsonRsp
一样的道理, import 也是有先后顺序
控件使用
添加按钮
-
基础控件添加和事件绑定 - https://www.jianshu.com/p/6eb302a62956
-
添加事件
回到【Main.storyboard】上,点击登录按钮,
按住【Control】键,这时候会出现带箭头的线,把箭头指向【View Controller】,然后放开。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HpEKJ7xu-1612831658432)(http://yxbl.itengshe.com/20210128161606-1.webp)]
-
移除事件
第三方库
AFNetworking
-
允许 http (不安全) 请求
在 info.plist 配置中添加允许设置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rNeOoqsV-1612831658433)(http://yxbl.itengshe.com/20210204110746-1.webp)]
参考: https://blog.csdn.net/lixianyue1991/article/details/50600607
-
报错:
Error Domain=com.alamofire.error.serialization.response Code=-1016
参考: https://www.jianshu.com/p/d0884204aced
踩坑
run 到真机报错 证书过期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yo9RxWej-1612831658434)(http://yxbl.itengshe.com/20210131164103-1.webp)]
解决办法, 重新下载证书即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p4QTDMcW-1612831658434)(http://yxbl.itengshe.com/20210131165302-1.webp)]
按指示 <> 引入头文件报错
明明按照 xcode 的指示用 <> 方式引入头文件, 改为报错.
product -> clean build folder 清楚一下再次编译即可.
可执行/库 编译正常, 单元测试执行时编译报错
在单元测试模块执行用例时报错: Undefined symbol: _OBJC_CLASS_$_AFHTTPSessionManager
, 但是在 可执行/库 模块又可以正常编译运行.
报的错是找不到 AFNetworking 第三方库 模块
原因是: 模块A的测试模块 引入了 模块A, 而 模块A 又引入 AFNetworking 第三方库 pod install
后的 libPods-A.a
静态库, 此时 模块A的测试模块 没有引入对应的 libPods-ATests.a
静态库.
解决办法:
-
在 Podfile 中加入 ATests 模块
platform :ios, '9.0' def shared_pods01 pod 'AFNetworking', '~> 4.0' end target 'A' do shared_pods01 end target 'ATests' do // 增加 测试块 shared_pods01 end
-
执行
pod install
生成 pod 工程配置, 然后打开 pod 工程编译出libPods-ATests.a
静态库, 丢到 ATests 能 link 的的地方. -
done. 然后执行 测试用例 就不会编译报错, 正常执行.