ios-记录

ios-记录


前面


icon 生成


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 区别

  • 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 静态库

关于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

  • 设置编译的 cpu 架构, build settings -> 搜索 architecture

  • 目标 sdk, build settings -> 搜索 deployment target

  • 添加编译 flag. build settings -> 搜索 other linker flags


选择目的 模块 进行编译

  1. 选择目的 target

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


导出 模块

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

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

  3. 导出 头文件 UnityAppController.h

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

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

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


导入 模块

  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


查看所有的 archive

  • Window -> Organizer


修改 架构

  • build settings -> architectures, 改成多少这里就显示多少.


修改 product 构建路径

  • build settings -> build locations -> build products path, 例如: 修改为 ./build, 就是在 项目目录的相对目录 ./build, 修改完重启 xcode 生效.


xcode 默认构建路径

编辑器默认构建路径


自定义参数 User-Defined

可以在 xcode 中自定义一个参数, 然后其他地方应用这个参数

  1. build settings -> user-defined 中可以增加参数, 如 PODS_BUILD_DIR

  2. 然后别的地方就可以 ${PODS_BUILD_DIR} 这样引用这个参数, 如:


构建 debug/release products

其实就是修改 scheme 中的

  1. 点击 edit scheme 就可以编辑 勾选中的 scheme, 然后修改 build configuration 即可, 比如改为 release

  2. 然后 cmd + b 就构建出 release 的 products


取消代码区小地图 minimap


查看证书的 team id

双击证书, organizational unit 就是 team id


查看 framework cpu 架构

  • 合并

    1
    $ lipo -create Debug-iphoneos/UnityApi.framework/UnityApi Debug-iphonesimulator/UnityApi.framework/UnityApi -output UnityApi
  • 查看

    1
    2
    $ lipo -info UnityApi
    Architectures in the fat file: UnityApi are: armv7 x86_64 arm64

    x86_64 就是 模拟器 支持的架构, armv7 arm64 都是真机支持的架构

  • 移除

    1
    2
    $ lipo -remove i386 ProjectFramework_SDK -o ProjectFramework_SDK 
    $ lipo -remove x86_64 ProjectFramework_SDK -o ProjectFramework_SDK
  • 瘦身

    1
    $ lipo ProjectFramework_SDK -thin armv7 -o ProjectFramework_SDK

    瘦身为只保留 armv7 架构


查看 framework 动态库 or 静态库

参考: https://www.jianshu.com/p/77343def4574


第三方 动态库/静态如 引入

使用 pod 方式都可以指定构建 动态库 (use_frameworks!) 或者静态库. (参考: ios-第三方库引入之CocoaPods.md)

  • 动态库/静态库u 引入都需要加入头文件, 在 build settings -> framework search paths 中加入搜索路径, 如: ThirdSdk/google_signin_sdk_5_0_2
  • 还有个区别就是 动态库 中有 Info.plist, 而 静态库 中没有

动态库引入

  • 需要在 build phaseslink binary with librariesembed frameworks 中都加入库


静态库引入

  • 需要在 build phaseslink binary with libraries

    如果静态库也在 embed frameworks 中引入了, 编译没问题, run 到真机时会报错 无法安装 app.


第三方库

AFNetworking

单元测试

测试用例方法必须以 test 开头, 如:

1
- (void)testExample { ... }
执行测试用例
  • 执行 全部 测试用例: cmd + U

  • 执行 单个 测试用例, 点击测试方法左边的按钮

测试按钮消失的话, 重启 xcode 试试 (卧槽)


快捷键

  • 编译: cmd + B
  • 运行: cmd + R
  • 执行 全部 测试用例: cmd + U
  • 显示/隐藏 控制台: cmd + shift + Y
  • 格式化代码: 1. 选中代码块, 2. ctrl + i
  • 保存所有文件: cmd + opt + S

光标移动

  • 上一单词: option + ←
  • 下一单词: option + →
  • 上一次光标: ctrl + cmd + ←
  • 下一次光标: ctrl + cmd + →
  • 跳转到 定义: ctrl + cmd + J

查找编辑

  • 当前文件中查找: cmd + F
  • 项目中查找: cmd + shift + F

object-c 语法相关

@property指示符

在声明属性的时候一般会带上几个指示符,常用指示符有

属性参数主要可以分为三类:

  • 原子性: 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, 否则出警告.


编译有先后顺序

编译有先后顺序, 不是有声明就可以. 比如

1
2
3
4
@interface CHttpJsonRsp : NSObject // 先声明之后
@end

typedef void (^HttpCb)(CHttpJsonRsp* rsp); // 才能使用 CHttpJsonRsp

一样的道理, import 也是有先后顺序


扩展

Category 类

  1. 创建一个 Category 类型的 oc file

    会生成 NSString+Category.hNSString+Category.m

  2. 然后就可以 扩展 类/实例 方法 以及 重写已有方法.

    作用:

    • 可以将类的实现分散到多个不同文件或多个不同框架中(扩充新的方法);
    • 可以创建对私有方法的前向引用;
    • 可以向对象添加非正式协议;

    局限性:

    • 类别只能向原类中添加新的方法,且只能添加而不能删除或修改原方法,不能向原类中添加新的属性;
    • 类别向原类中添加的方法是全局有效的而且优先级相对最高,如果和原类的方法重名,会无条件覆盖掉原来的方法,造成难以发现的潜在危险,因此使用类别添加方法一定注意保证是单纯的添加新方法,避免覆盖原来的方法(可以通过添加该类别的方法前缀来防止冲突),否则原方法被类别覆盖了,团队中其他成员不知情的情况下用到这个被覆盖的方法会出现意想不到的问题而难以察觉纠正。

关于 -ObjC 宏

设置在 build settings -> other linker flags,

踩过一个坑就是 接入 阿里云 oss sdk 是, 一直 sdk 里的一个 +xx 扩展类无效, 原因就是没有加入 -ObjC 宏, 导致 Category 类无法编译进去 (参考:https://github.com/aliyun/aliyun-oss-ios-sdk/issues/205).


控件使用

显示控件窗口


添加按钮

  • 添加事件

    回到【Main.storyboard】上,点击登录按钮,
    按住【Control】键,这时候会出现带箭头的线,把箭头指向【View Controller】,然后放开。

  • 移除事件


对齐方式


加载 xib ui 布局文件

流程

  1. 创建继承 UIView 的类 MyView

  2. 创建 UIView 布局文件 MyView.xib

    1. MyView.xib 的绑定类修改为刚创建的 *MyView
  3. 拖入控件到 MyView.h 中, 作为成员变量引用

  4. 加载 MyView.xib

    1. 右键 ui 成员, 删除 outlet. 不然会闪退, 报错: ``. 参考: https://blog.csdn.net/wojiaoweide/article/details/51509478

    2. 先把 xib 文件转换为 nib 文件

      1
      $ ibtool --errors --warnings --output-format human-readable-text --compile MyView.nib MyView.xib
      • 如果不转换, 加载是会闪退, 报错: Could not load NIB in bundle. 参考:
    3. sd

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      NSString *path = [[NSBundle mainBundle] pathForResource:@"res" ofType:@"bundle"];
      NSBundle *resBundle = [NSBundle bundleWithPath:path];
      NSLog(@"--- resBundle: %@", resBundle);
      NSArray *nibContents = [resBundle loadNibNamed:@"MyView" owner:nil options:nil];
      NSLog(@"--- arr: %@", nibContents);
      UIView *plainView = [nibContents objectAtIndex:0];
      MyView* mv = (MyView*) plainView;
      NSLog(@"--- mv: %@", mv);
      // [mv.mylabel setTitle:@"hello world" forState:UIControlStateNormal]; // 闪退, 应该是删了 ui outlet 的原因, 导致类成员没有初始化.
      [self.view addSubview:mv];

UIViewController 全屏/禁止下滑关闭

  • 全屏: 将的 UIViewController 成员 modalPresentationStyle = UIModalPresentationFullScreen
  • 禁止禁止下滑关闭: 将的 UIViewController 成员 modalInPresentation = YES

引导用户开启权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)guideUserOpenAuth{
UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"请打开访问权限" preferredStyle:(UIAlertControllerStyleAlert)];
UIAlertAction *alertA = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:nil];
UIAlertAction *act = [UIAlertAction actionWithTitle:@"去设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// 引导用户设置
NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];

if ([[UIApplication sharedApplication] canOpenURL:url]) {

[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
}
}];
[alertC addAction:alertA];
[alertC addAction:act];
[self presentViewController:alertC animated:YES completion:nil];
}

开发时的相关路径

  • 模拟器持久化路径: (不同 app 不一样)

    1
    /Users/wilker/Library/Developer/CoreSimulator/Devices/6EF31FFA-34F1-48F7-86E7-81C585759F8C/data/Containers/Data/Application/3C36B315-5B48-4EC1-A355-D2BCF958F806/Documents
  • pod 构建路径: (不同 项目 不一样)

    1
    /Users/wilker/workplace/its_iosproj/MyIosTest/build/Debug-iphonesimulator
  • 编译时引用第三方库要丢进去的路径:

    1
    /Users/wilker/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphonesimulator

ios 启动流程/生命周期


跳转到相关设置

貌似 ios10 之后不能直接跳转到 详细页面, 比如: 定位, 只能跳转到 系统设置 页面.


iOS 支持的 cpu 架构

目前ios的指令集有以下几种:

  • armv6
    • iPhone, iPhone2, iPhone3G, 第一代和第二代iPod Touch
  • armv7
    • iPhone4, iPhone4S
  • armv7s
    • iPhone5, iPhone5C
  • arm64
    • iPhone5S 及 以后

机器对指令集的支持是向下兼容的,因此armv7的指令集是可以运行在iphone5S的,只是效率没那么高而已~


Archive、ipa 和 App 包


获取手机 UUID

这里获取 UUID 不是 api 获取, 而是为了加入测试设备列表.

  1. 使用 蒲公英: https://www.pgyer.com/udid
    1. 打开该网址会出现下面的界面
    2. 点击右上角的三个点的按钮,点击用Safari打开
    3. 点击获取UDID绿色的按钮
    4. 会出现需要安装配置文件已获取信任,点击右上角的安装
    5. 输入手机的锁屏密码
    6. 点击安装!
    7. 接下来UDID就显示出来了

开发者注册

网页支付会先失败, 然后发邮件告诉你建议手机 APP 支付, 如果无法使用 APP 支付, 回邮件让说没有手机, 不能使用 APP 支付, 他们协助即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Thanks for your email. Daniel here again.

As mentioned in our previous interactions by email and by phone. The payments you submitted for your program enrolment did not process correctly, and were subsequently cancelled.

To expedite the resolution of your payment issue, we suggest resubmitting your enrollment using the Apple Developer app.

Alternate payment options are available only to developers who use the app to enroll.

If you want to reenroll using the app, please reply to let us know as we will need to withdraw your current enrolment.

Learn more about enrolling with the Apple Developer app.

If you can’t use the app or don’t want to use the app also reply to let us know. We won’t be able to assist further without a reply from you in relation to this.

I look forward to hearing from you.

别人经验

  • 注册 Apple id 时就绑定了 微信, 然后开通海外公司开发者 (海外主体, 在 developer app 开通), 支付时直接微信支付, 手机 app 端支付

全局预编译头文件


闪退定位


踩坑

run 到真机报错 证书过期

解决办法, 重新下载证书即可


按指示 <> 引入头文件报错

明明按照 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 模块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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. 然后执行 测试用例 就不会编译报错, 正常执行.


链接报错 Undefined symbols

[可执行/库 编译正常, 单元测试执行时编译报错](#可执行/库 编译正常, 单元测试执行时编译报错) 就是链接报错

参考: https://www.cnblogs.com/sundaysgarden/articles/9128520.html

这种错误可能出现在两种情况

  1. 同模块下链接失败.

    申明了 函数, 但是没有定义.

  2. 跨模块下链接失败.

    也就是调用别的模块情况下, 链接失败. 解决办法是在 模块 -> build phases -> link binary with libraries 下添加一下别的模块


编译报错 Undefined symbols

  • 错误

    1
    2
    3
    4
    5
      Undefined symbols for architecture arm64:
    "_OBJC_CLASS_$_User", referenced from:
    objc-class-ref in HelloItsTests.o
    ld: symbol(s) not found for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
  • 原因

    数据结构申明了 (interface) , 但没有实现 (implementation)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @interface User : NSObject
    @property (nonatomic,strong) NSString *name;
    @property (nonatomic,strong) NSString *icon;
    @property (nonatomic) NSInteger age;
    @end

    // 缺少实现
    @implementation User
    @end

编译报错 有重复的符号

报错: duplicate symbol for architecture x86_64, 有个重复的符号

  1. 可能性 1

    引用某个头文件里面有 const 变量, 如: Enum.h

    1
    const NSInteger HttpTimeout = 30;

    修改为 static 即可

    1
    static NSInteger HttpTimeout = 30;

    因为const声明的是常量,static声明的是静态变量(只声明一次),所以我们在引用的时候,引用一次是没问题的,而引用多次,const声明的对象,会多次创建,从而导致项目中出现重复引用错误的情况。

    字符串声明

    1
    2
    3
    static NSString * _Nonnull NativeGoName = @"GameMgr";
    static NSString * _Nonnull NativeCallFnName = @"OnNativeCall";
    static NSString * _Nonnull NativeCallPerFnName = @"OnNativePersistCall";

    参考: https://www.jianshu.com/p/d6dd379332ce

  2. 可能性 2

    自定义的 oc 类真的与系统重复了, 把报错的类重命名一下. (我的就是自定了 WebViewController 与 unity 的重复了, 卧槽!)


xcode 无法跳转到定义

在command+鼠标可以实现函数的跳转,但是有时会出现Symbol not found,这是因为工程的索引文件被破坏了,

解决方案:/Users/XXX/Library/Developer/Xcode/DerivedData 中把相应的工程的文件夹删除就行了。


设置为 nil 时, 编译警告冲突

警告: Null passed to a callee that requires a non-null argument

一般新建 类 时, 生成的头文件会自动加上 非空的 宏

1
2
3
NS_ASSUME_NONNULL_BEGIN
...
NS_ASSUME_NONNULL_END

在这个宏之内的所有都会自动声明为 nonnull 属性, 如果需要允许为 nil 值的话, 需要显式声明为 nullable, 如:

1
2
3
4
5
@property (nonatomic) BoolFn onShowCb;
@property (nonatomic, nullable) BoolFn onHideCb; // 显示声明允许为 nil 值

self.onShowCb = nil; // 编译警告: Null passed to a callee that requires a non-null argument
self.onHideCb = nil; // 编译正常

启动黑屏, 有未 implement 的属性

报错: The app delegate must implement the window property if it wants to use a main storyboard file.

根据提示打开 AppDelegate.h 文件时候发现确实没有声明 UIWindow 属性

1
2
3
4
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow* window; // 增加这个声明
@end

参考: https://medium.com/@cookiesJ/fixed-ios-%E5%90%AF%E5%8A%A8%E9%BB%91%E5%B1%8F-the-app-delegate-must-implement-the-window-property-if-it-wants-to-use-a-main-6f0304cd179b


编译报错: 找不到 swift 相关文件

报错: Undefined symbol: __swift_FORCE_LOAD_$_

原因是因为 sdk 使用了 swift, 而工程配置里没有配置 swift 头文件搜索的路径.

解决办法很简单: 创建一个 swift 文件即可, xcode 会提示创建桥接文件 Create Bridging Header

参考: https://github.com/facebook/react-native-fbsdk/issues/794


编译报错: extern C

1
2
3
4
extern "C"  // Expected identifier or '('
{
const char* getMessage(const char *str);
}

修改为需要 cpp 宏包住

1
2
3
4
5
6
7
#ifdef __cplusplus
extern "C"{
#endif
const char* getMessage(const char *str);
#ifdef __cplusplus
}
#endif

参考: https://blog.csdn.net/Mediary/article/details/112554947


framework 报错包含了 iOS + iOS Simulator

报错: Building for iOS, but the embedded framework 'GoogleSignIn.framework' was built for iOS + iOS Simulator.


run 到真机报错 无法安装

原因可能是把 静态库 也丢带了 build phases -> embed frameworks 中.

embed frameworks 里只能加 动态库 (有 Info.plist 文件).

参考: 静态库引入


run 到真机报错 keychain 找不到证书

报错: error: The specified item could not be found in the keychain

原因是 keychain 中找不到开发者证书, 可以打开 keychain 搜索一下 开发者账号看有没有.

解决办法:

  1. xcode 登录账号后下载证书
  2. quit 到 xcode, 重新打开项目再 run 一下, 会提示访问 keychain, 输入 登录 密码就行了

python 报错找不到模块

比如找不到 colorama 模块, 报错: ModuleNotFoundError: No module named 'colorama'

可能的原因是安装是没有加上 --user 参数

  1. 先卸载就旧的: sudo pip uninstall colorama
  2. 再次安装, 带上 --user 参数: sudo pip3 install colorama --user

开发者网站 报 503 错误

错误: 503 Service Temporarily Unavailable

可能是开了代理, 去掉代理即可

参考: https://discussionschinese.apple.com/thread/140131919


打 archive 包报错 Mach-O 错误

错误: found an unexpected mach-o header code 0x72613c21

直接 run 到真机没问题, 打 archive 包的时候包了这个错.

原因可能是某个 framework 是 static 的, 但是又把它加入到了 Embedded Binaries 里面.

解决办法: 从 Embedded Binaries 移除那个framework, 把这个 framework 添加在 Link Frameworks and Libraries 里面

参考:


上传 ipa 后报错 api 废弃

archive 打出 iap 后, 使用 Transporter 上传后, 苹果发来邮件说 api 失败, 错误: ITMS-90809: Deprecated API Usage - existing app that use UIWebView are no longer accepted

1
ITMS-90809: Deprecated API Usage - New apps that use UIWebView are no longer accepted. Instead, use WKWebView for improved security and reliability. Learn more (https://developer.apple.com/documentation/uikit/uiwebview).

解决办法, 升级版本, 参考: https://networm.me/2020/01/12/unity-ios-deprecated-uiwebview/


签名的地方显示 找不到注册设备

错误: xxx not found

在后台上添加注册设备即可


编译报错多个命令处理

报错: Multiple commands produce ... Info.plist

是应为把 Info.plist 也丢到了 copy 资源那里

在 target -> Build phase > Copy Bundle Resource 中找到 Info.plist ,移除掉即可

参考: https://www.jianshu.com/p/58e317290c11


加载隐私追踪库失败

报错: dyld: Library not loaded: /System/Library/Frameworks/AppTrackingTransparency.framework/AppTrackingTransparency ... Reason: image not found

Xcode 12中添加后在iOS14的设备和测试机上都没问题,但是运行在iOS14以下设备时候会报如下错误。

解决办法就是, 在 build phases -> link binary with libraries 中加入 AppTrackingTransparency.framework, 并且 status 是 optional.

参考:


xcode 不支持 高版本的手机

报错: Xcode doesn’t support Phone’s iOS 14.7.1

另一种报错: unable to prepare iphone for development

xcode 显示 unsupported OS version

去这两个地方下 zip 包, 解压后丢到这个目录下 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/

参考: https://stackoverflow.com/questions/68549513/xcode-doesn-t-support-phone-s-ios-14-7-1


找不到 认证服务 闪退

报错: Symbol not found: "_ASAuthorizationScopeEmail"

原因是接入了 苹果登录, ios 版本小于 13, 才会出现, 需要加入 AuthenticationServices.framework 框架, status 为 Optional

参考: https://github.com/facebook/facebook-sdk-for-unity/issues/508


new 对象造成卡死

ios13 之前的版本使用 new 关键字实例化对象造成卡死, 原因未知.

解决办法, 修改为使用 alloc init 去实例化对象即可.

1
2
3
CCodeJson* cj = [CCodeJson new];
// 修改为:
CCodeJson* cj = [[CCodeJson alloc] init];

系统版本判断

使用 @available(iOS 14.0, *) 貌似有坑, 直接用 浮点型 判断貌似靠谱一点.

1
2
if (@available(iOS 14.0, *)) // 错误
if ([UIDevice currentDevice].systemVersion.doubleValue >= 14.0) // 正确

原因: 不知为啥在 虚拟机里编译出来的, ios14 之前的机子 @available 也会进入到 14.0 的判断


新建空工程启动黑屏卡死

报错: The app delegate must implement the window property if it wants to use a main storyboard file

打开 AppDelegate.h 文件时候发现确实没有声明 UIWindow 属性, 补上即可

1
2
3
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow * window; // 添加
@end

参考: https://medium.com/@cookiesJ/fixed-ios-%E5%90%AF%E5%8A%A8%E9%BB%91%E5%B1%8F-the-app-delegate-must-implement-the-window-property-if-it-wants-to-use-a-main-6f0304cd179b


第三方库头文件找不到

  1. 查看 scheme 编译的是否一致, 比如 被引用的第三方库 编译的模式是 release, 那么 引用第三方库的模块 编译模式必须是 release 才能找到到第三方库的头文件

编译成功, 运行时报错无法安装

  • 安装完运行时弹窗报错: Unable to install "xxx"

    报错内容关键字:

    1
    2
    3
    The code signature version is no longer supported.
    Domain: com.apple.dt.MobileDeviceErrorDomain
    Code: -402620375
  • 原因是把 静态库 设置成了 embed & sign

  • 解决办法就是把 静态库 设置为 do not embed


http 请求失败

  • 需要在 info.plist 中增加配置, 允许不安全的 http 请求

    1
    2
    3
    4
    5
    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>

    gui 添加如图:


找不到 framework

报错: framework not found

也就是构建出来的 xxx.framework 里面没有二进制文件, 重新构建, 如下图所示包含二进制文件才是正确


strp 报错

报错: strip /xxx/FBSDKCoreKit/FBSDKCoreKit.framework.dSYM/Contents/Resources/DWARF/FBSDKCoreKit: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip exited with 1

原因是 pod 构建出来的 FBSDKCoreKit.framework 里面包含了 FBSDKCoreKit.framework.dSYM 调试符号的内容, 移除掉这个 .dSYM 文件即可


alloc 分配内存后还是 空指针 0

  • 出现这种问题一般是在引入 第三方 framework, 使用了里面的 class, 进行 alloc 分配内存时出现, 如:

  • 解决办法: 引入的第三方 framework 要 embed & sign


运行就闪退


bugly 集成报错

错误: Undefined symbol: _inflateInit2_

缺少相关依赖库

  • 添加依赖库
    • SystemConfiguration.framework
    • Security.framework
    • libz.dyliblibz.tbd
    • libc++.dyliblibc++.tbd

手机版本不兼容

报错: This operation can fail if the version of the OS on the device is incompatible with the installed version of Xcode. You may also need to restart your mac and device in order to correctly detect compatibility.

原因是 xcode 中没有支持 当前手机版本的库


报错代码签名版本不支持

  • 解决方法一:

    Build Setting -> Other Code Signing Flags 添加 –generate-entitlement-der

  • 解决方法二:

    Xcode > Target > General
    找到 “Embedded Framework, Libraries and Embedded Content”, Set all frameworks in the Embedded field to “Do not Embed”


报错重复的库引用

  • 报错: error: Multiple commands produce, error: Unexpected duplicate tasks, duplicate output file

  • 原因是多次引用相同的库, 移除掉即可:


bottom