ios-记录


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

扫描二维码关注公众号,回复: 13512397 查看本文章
  • 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)]


选择目的 模块 进行编译

  1. 选择目的 target

  2. cmd + B 构建, 构建成功后在 Products 目录可以找到 (白色的表示存在)


导出 模块

  1. 创建一个模块, 如: Classes

  2. 创建 头文件 UnityAppController.h 和 实现文件 UnityAppController.mm

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fgET0wQB-1612831658428)(http://yxbl.itengshe.com/20210130152633-1.webp)]

  3. 导出 头文件 UnityAppController.h

    在对应的 target 上, 在 头文件 的 public 下添加 UnityAppController.h (可以直接拖文件到 public 下)

  4. done. 在其他模块就可以进行导入这个文件了

    使用 <> 去导入, 表示引用库中搜索


导入 模块

  • 动态库的链接 - https://www.jianshu.com/p/ffa343009789

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5IF5xnIT-1612831658430)(http://yxbl.itengshe.com/20210130155928-1.webp)]

  1. target depnedencies(编译前)

    这个选项只是告诉工程在运行的时候先去编译这里导入的库.

  2. Link Binary With Libraries(编译时期)

    Link Binary With Libraries里添加的即你的某个project需要链接的库.

    这里添加的库都会被编译到工程的最终包里.
    只有在这里添加了.app才能找到该库的.o文件

  3. Embedded Binaries(运行时)

    这个是告诉工程在app运行时去哪些库里找实现方法.

    这个选项只有在可运行的project里有.即你工程的总壳(有main.m文件的project)
    不可运行(静.动态库 >> 没有main.m文件)的project是没有这个选项的.因为他们不可能进入运行时状态.

  • 总结

    1. 当你导入一个库时.target dependencies和link binary with libraries两个选项都必须设置.
      只有可运行的project里需要设置embedded binaries.

    2. 所以当你引入一个静态库的时候.只需要设置Link binary with libraries选项就可以了.因为他不需要编译.

    3. 当你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是编译器的默认选项,表示自动生成gettersetter,如果需要gettersetter不写即可。
readonly表示只合成getter而不合成setter
assign assign表示对属性只进行简单的赋值操作,不更改所赋的新值的引用计数,也不改变旧值的引用计数,常用于标量类型,如NSIntegerNSUIntegerCGFloatNSTimeInterval等。 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修饰,使用strongassign等修饰则会因为多态导致属性值被修改。
unsafe_unretained 使用unsafe_unretained修饰时效果与assign相同,不会增加新值的引用计数,也不会减少旧值的引用计数(unretained)当所赋的值被销毁时不会被置为nil可能会发生野指针错误(unsafe)。unsafe_unretainedassign的区别在于,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 静态库.

解决办法:

  1. 在 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
    
  2. 执行 pod install 生成 pod 工程配置, 然后打开 pod 工程编译出 libPods-ATests.a 静态库, 丢到 ATests 能 link 的的地方.

  3. done. 然后执行 测试用例 就不会编译报错, 正常执行.

猜你喜欢

转载自blog.csdn.net/yangxuan0261/article/details/113765873