Xcode常见报错锦囊(二)

作者: 小唐羽锋 | 来源:发表于2016-02-14 19:47 被阅读782次

    中心思想

    这篇文章也是紧接着上一篇继续归纳和总结,在我们日常的开发工作中,Xcode编译器抛出的各种“无理取闹”的异常和错误。
    在每个异常或错误的下方,我会尽可能详细地归纳解决办法,解决方案中涉及网上取材的内容,我会附上网址或者其他大神博客供大家参考。

    如果文中有不当或者错误的地方,劳烦您指正,我会及时修改,以免误导他人及一些iOS开发初学者。
    Xcode编译器头疼脑热的地方远比我们知道的要多,如果您遇到过文中不曾提及的警告或者错误,并且知道如果解决它,请您以简信或者Email的形式发送给我(网页地址栏有我的邮箱地址),我会一并总结更新,我会附上您的信息(例如博客,Github地址)。在此先谢谢了。


    1.Bitcode问题

    XXX does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64

    上面这个问题也是iOS 9SDK发布以后出现在Xcode7中的新问题,Bitcode是Xcode7引入的新特性,旨在为App瘦身,网上对它通俗的解释是在线版安卓ART模式

    下面这段话,是亲身参与2015年WWDC大会的国内一线开发者王巍的总结:Bitcode 是 LLVM 的中间码,在编译器更新时,Apple 可以用你之前提交的 Bitcode 进行优化,这样你就不必在编译器更新后再次提交你的 app,也能享受到编译器改进所带来的好处。Bitcode 支持在新项目中是默认开启的,没有特别理由的话,你也不需要将它特意关掉。

    Apple Watch应用必须打开Bitcode,iOS没有强制,但是Xcode7默认打开了Bitcode。

    解决上述问题的方法:
    1.更新library使包含Bitcode,否则会出现以上问题,陆续都会支持Bitcode。
    2.关闭Bitcode,步骤如下。
    找到工程的target->build settings->直接搜索bitcode->然后在搜索结果的Build Options选项下找到Enable Bitcode->将YES改为NO,如下动态图所示。

    图片取材自网络

    2.升级Xcode7后上传App时报错

    图片取自网络

    解决方案:进入TencentOpenApi_ios_Bundle.bunle 点击显示包内容,把plist文件删除即可

    3.故事板与Masonry混合使用时报错

    原因:如果用的view是storyboard连线而来的,不是自己在代码里创建的。 很可能运行的时候会报错,说IB已经定义的约束和Masonry的约束冲突。即使你拖进去控件后并没有设置约束。

    解决:按以前的方法先用故事版做好约束,然后在每个约束的属性面板设置PlaceHolder : Remove at run time。 这样在运行的时候会自动取消。

    Masonry是一个Objective-C版本的第三方Autolayout库,还有一个叫做snapKit的开源库,它是Masonry的Swift版本。在Swift项目中,如果出现上述错误,解决办法同上。

    4.升级Xcode7后使用JSONKit第三方库崩溃

    出现问题的出处是: void *keyObjectISA = *((void **)keys[idx]);这一段。这个问题我也是从网络搜集的,我没用过JSONKit,一直都是用系统自带的。但是下面的解决办法在我朋友那里得到了验证。如果您有异议,请您指正,我会及时修改。

    解决办法:将原项目中JSONKit.m文件替换成下面链接的实现文件即可
    https://github.com/jcbertin/JSONKit

    5.添加Scheme白名单

    这个问题是引起一些在项目中使用到微信,支付宝或者微博SDK相关功能(支付,收藏,分享)出现错误的原因,它会导致Xcode报如下报错:
    canOpenURL:failedforURL:“weixin://app/wxdaae92a9cfe5d54c/” - error: “This app is not allowed to query for scheme weixin”

    问题描述:在iOS 9下涉及到平台客户端跳转,系统会自动到项目info.plist下检测是否设置平台Scheme。对于需要配置的平台,如果没有配置,就无法正常跳转平台客户端。因此要支持客户端的分享和授权等,需要配置Scheme名单。

    解决办法如下:
    1)在项目的info.plist中添加一LSApplicationQueriesSchemes,类型为Array。
    2)然后给它添加一个需要支持的项目,类型为字符串类型;
    下面是一些项目中常用的白名单,你有用到的你就添加到该数组下面,类型全部为string

    mqqOpensdkSSoLogin
    mqzone
    sinaweibo
    alipayauth
    alipay
    safepay
    mqq
    mqqapi
    mqqopensdkapiV3
    mqqopensdkapiV2
    mqqapiwallet
    mqqwpa
    mqqbrowser
    wtloginmqq2
    weixin
    wechat

    6. directory not found for option

    问题截图

    问题原因:Xcode7将framworks位置改变了

    解决方法:
    1)点击项目,选择 Targets->XXXTests
    2)选择build setting 选项,找到 Frameworks Search Path 或者 Library Search Paths
    3)删除$(SDKROOT)/Developer/Library/Frameworks,
    或者使用$(PLATFORM_DIR)/Developer/Library/Frameworks替换

    7.iOS 9旧状态栏报错

    下图是报错的截图


    取自网络

    出错原因:设置app的状态栏样式使用了旧的方式,在info.plist里面设置了View controller-based status bar appearance为NO,默认为YES,一般式iOS6的时候使用这种方式,iOS7,8也兼容,但是到了iOS9就报了警告。

    解决办法:
    1)删除原先编写的代码
    [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent]

    2)然后在plist文件中添加项View controller-based status bar appearance,类型为Boolean,设置为YES(默认是NO),如下图7-1所示。


    7-1

    3)然后在你自定义的导航控制器里面添加如下代码
    -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; }

    4)在模拟器上删除应用程序并重新运行即可

    8.大部分社交平台接口不支持https协议。

    这个问题也是上一篇中网络请求出错的一个分支。目前还有大量的应用是通过HTTP协议来访问服务器的,而要让所有的应用都转向支持HTTPS,显然是一件耗时的工作。所以下面的方法可以一试,但只是暂时性的。毕竟苹果帮之前提出了App Transport Security(ATS)的概念,它的提出意味着苹果将准备弃用HTTP,转而支持HTTPS。

    上述问题的解决方案就是设置域,可以简单理解成,把不支持https协议的接口设置成http的接口。

    具体方法:

    1)、在项目的info.plist中添加一个Key:NSAppTransportSecurity,类型为字典类型。

    2)、然后给它添加一个NSExceptionDomains,类型为字典类型;

    3)、把需要的支持的域添加給NSExceptionDomains。其中域作为Key,类型为字典类型。

    4)、每个域下面需要设置3个属性:NSIncludesSubdomains、NSExceptionRequiresForwardSecrecy、NSExceptionAllowsInsecureHTTPLoads。均为Boolean类型,值分别为YES、NO、YES。

    以下文章能够帮助你更好的理解ATS的概念
    如何使用ATS提高应用的安全性
    ATS问题

    App Transport Security dictionary primary keys

    摘自官方文档

    9.找不到.dylib文件,换成.tbd文件而又无法运行,请尝试下面的方式来解决。

    拿添加libsqlite3.dylib为例(你可别照本宣科)
    1)在项目Target中的Link Binary With Libraries 手动添加,
    首先点击 “+” ;

    2)显示搜索添加页面,在这里如果搜索之前的libsqlite3.dylib是搜不出来ios9之前的。所以需要点击 Add Other,出现文件目录页面,正常情况这里也是找不到老的libsqlite3.dylib文件的,因为这个文件是隐藏掉的。所以需要按快捷键 CMD+Shift+G (Go to the folder),输入/usr/lib后,进入隐藏的界面;

    3)然后添加你需要的 *.dylib,如libsqlite3.dylib文件.大功告成


    今天先告一段落,我会继续更新,keep moving!给广大无聊的程序员推荐一个小游戏,我最近无聊的时候在玩,叫做okay?(你要是在改Bug,当我没说)。
    另外给大家推荐一个bug收集工具,叫做Bugtags,我也是偶然在资深开发者唐巧的微信公众号看见的,后来在自己的Demo中体验了一下,感觉小巧实用,之后还接到了一个Bugtags开发团队的使用情况回访电话,就算帮助他们推广一下。

    更多有关Bugtags的内容请参考以下链接:
    Bugtags官网
    Bugtags博客


    更新两个使用Swift语言出现的问题

    1.新建playground报错Unable to find execution service for selected run destination

    这个问题参考一下就行了

    解决步骤:
    1.先关闭Xcode
    2.cd到Xcode所在目录,并打开终端输入下面两行命令
    rm-rf~/Library/Developer/CoreSimulator/Devices
    killall -9 com.apple.CoreSimulator.CoreSimulatorService

    关于Playground
    Playground,有人将它称呼为“训练场”,它可以让Swift展示某些脚本语言的特性。实际上,Playground只是提供了一个可实时编译运行并展示的交互式开发环境罢了,类似于著名的REPL。它的这项功能完全借助于LLVM编译器强大的组织能力。
    目前,Playground只支持Swift语言,但是一位歪果仁大神开发出了一个可以运行OC版本的Playground,有兴趣可以去看看。点我喽

    2.dyld: Library not loaded:@rpath/libswiftCore.dylib

    问题描述:真机测试时,出现上述错误
    解决步骤:
    1.在工程的Targets中找到Build Setting选项
    2.搜索Embedded Content Contains Swift Code项,将其设置为YES

    第三次更新

    更新两个问题,也是在网上搜集的,解决办法比较详细

    1. “Unknown class XXViewController in Interface Builder file.” 问题处理

    在静态库中写了一个XXViewController类,然后在主工程的xib中,将xib的类指定为XXViewController,程序运行时,报了上述错误:

    其实这个问题与Interface Builder无关,最直接的原因还是相关的symbol没有从静态库中加载进来。这种问题的处理就是在Target的”Build Setting”–>“Other Link Flags”中加上”-all_load -ObjC”这两个标识位,这样就OK了。

    2.关于Unbalanced calls to begin/end appearance transitions for …问题的处理

    当某个业务有这么一个需求,进入一个列表后需要立马又push一个web页面,做一些活动的推广。在iOS 8上,我们的实现是一切OK的;但到了iOS 7上,就发现这个web页面push不出来了,同时控制台给了一条警告消息,即如下:

    Unbalanced calls to begin/end appearance transitions for ...
    在这种情况下,点击导航栏中的返回按钮时,直接显示一个黑屏。

    我们到stackoverflow上查了一下,有这么一段提示:

    occurs when you try and display a new viewcontroller before the current view controller is finished displaying.
    意思是说在当前视图控制器完成显示之前,又试图去显示一个新的视图控制器。

    于是我们去排查代码,果然发现,在viewDidLoad里面去做了次网络请求操作,且请求返回后就去push这个web活动推广页。此时,当前的视图控制器可能并未显示完成(即未完成push操作)。

    Basically you are trying to push two view controllers onto the stack at almost the same time.
    解释如下:
    当几乎同时将两个视图控制器push到当前的导航控制器栈中时,或者同时pop两个不同的视图控制器,就会出现不确定的结果。所以我们应该确保同一时间,对同一个导航控制器栈只有一个操作,即便当前的视图控制器正在动画过程中,也不应该再去push或pop一个新的视图控制器。

    所以最后我们把web活动的数据请求放到了viewDidAppear里面,并做了些处理,这样问题就解决了。
    原文链接

    第四次更新

    1.手动performSegueWithIdentifier没有生效的问题

    这个问题是因为对视图控制对象的生命周期概念没有深刻理解,比如说当用户打开应用,判断用户是否登陆,如果未登陆,就跳转到登录页面这个情况。

    如果你将判断用户是否登陆的语句放到了视图的viewDidLoad中去,那么这个方法是不会生效的。因为在viewDidLoad中就启动segue的话,依然会被后来填充的视图覆盖,要是在视图加载完成后的viewDidAppear中启动segue,就不会出现错误了。

    转载请注明出处及作者名,谢谢!

    相关文章

      网友评论

      本文标题:Xcode常见报错锦囊(二)

      本文链接:https://www.haomeiwen.com/subject/vcgukttx.html