一、Widget入门简介
widget 工程创建开发简介
http://www.jianshu.com/p/ca3e11d7686c
widget简介及证书配置
http://www.cocoachina.com/ios/20161114/18078.html
适配、展开、折叠
http://www.jianshu.com/p/9b3d06236d19
上线后无widget功能
http://blog.csdn.net/baidu_31683691/article/details/53115690
如果不需要引入第三方库的话,由以上帖子就可以入门基本的Widget开发了,只需要简单注意下
1、证书的配置:
需要新建Identifiers以及后续的开发和发布两个证书,注意在Identifiers里的Application Services需要打开App Groups(两个相同App Groups的应用可以共用某沙盒里的数据),而在Xcode中需要在Targets-项目-Capabilities里打开。
2、iOS8/iOS10 Widget的适配(iOS8和iOS9的应该没有区别):
①、iOS8下没有折叠和展开功能,默认的Widget高度为self.preferredContentSize设置的高度。
②、iOS8下所有组件默认右移30单位。
③、iOS8下Widget的默认背景为黑色的磨砂效果,所以文字基本为浅白色,而iOS10则为白色磨砂效果,文字则需要改为深黑色。有些应用未作适配,所以在Widget列表里挺违和的。
二、Widget通过cocoapods导入第三方库
由之前证书的创建和App Groups的新增权限,隐约可以猜到我们App的主体Target和新建的Today Extension似乎是独立的两个应用,由于之前未做过Extension的开发,当我发现这点的时候,也使我在开发Widget时遇到的一系列问题有了合理的解释,因为这就是俩应用啊。
本来就是俩独立的应用,这就导致上线打包的时候,你会发现应用包的大小会增加不少,我简单测了下,我们的原始程序打包后的ipa大小为19.6M,添加widget后的ipa包大小为20.2M,这还是未添加第三方组件的大小(当然这只是我自己的测试,如果有在不增加ipa包大小的前提下导入第三方包的方法,欢迎补充和讨论)。
所以如果公司需要上Widget的功能,同时又对ipa包的大小有着严格的要求,那么最好提前跟项目负责人说清,因为两个基本独立的应用,Widget显然无法使用主项目已导入的第三方Lib库。AFNetworking、Masonry这类还好,地图类SDK的包大小太过惊人,导入后的ipa包至少增加了3M。而我们知道在AppStore里显示的应用大小,是解压后来看的,这就导致到达用户手中的应用大小会增加不少。
顺便安利个 iOS安装包瘦身指南:
http://www.zoomfeng.com/blog/ipa-size-thin.html
回到主线,即通过cocoapods,在Widget里添加第三方SDK,在百度、stackoverflow了众多已经无效(cocoapods2.0或者Xcode8已修改)的方法后
我使用的办法就是:
其中use_frameworks! 是因为导入的SDK中包含了swift3.0的第三方库,猜测这也是我们项目在类扩展中无法像其他帖子里介绍的那样简单导入第三方库且不出任何bug的原因。
其中XXX需要改为你们项目的targets名称,widget改为你们today extension的target名称
有细心的吃瓜群众可能发现了,为何在 def end 里只添加了BaiduMapKit和UMengAnalytics呢,前面不是说了AFNetworking和Masonry吗。
在我的测试过程中,发现在像百度和友盟这种打好包的.framework库,通过def end可以轻松导入,如果新增AF或者Masonry 则程序会各种报错,包括但不限于 image not found等问题。
例如:
dyld: Library not loaded: @rpath/AFNetworking.framework/AFNetworking
Referenced from: /private/var/containers/Bundle/Application/016F51DF-7F1F-4702-9098-5B4E4D354677/Air.app/PlugIns/widget.appex/widget
Reason: image not found
根据关键词我在stackoverflow里搜到了这个问答(http://stackoverflow.com/questions/30053144/dyld-library-not-loaded-with-cocoapods-0-37-and-xcode-6-3/30166310#30166310),github里有这个(https://github.com/CocoaPods/CocoaPods/issues/3903)然而根据回答一个一个试,其中包括:
1、设置Optional
2、修改bitcode
3、重启cocoapods
4、证书配置
5、重启xcode 电脑 s+command+k
6、清理derivedData(注意这一项可能会导致友盟线上统计的本地崩溃定位失效)
7、修改always_embed_swift_standard_libraries
8、添加@executable_path/Frameworks
然而并没有解决该问题,反而跟滚雪球一样引起了各种其他的问题,所以也建议大家在开发Widget时,一定要注意备份。
所以我的解决办法就是.....直接把AF或者Masonry文件拖进Widget里,恩,世界突然安静了,程序也没问题了。
三、Widget开发异常总结
最后做个Widget开发过程中遇到的各种异常的总结吧,也欢迎大家提出自己遇到的问题和建议。
1、
- xxxx (3.0) and widget () do not use the same Swift version.
这个问题是项目使用swift版本不一致产生的,每次打开项目时也会遇到Alert提示,在Xcode-Edit-Convert-To Current Swift Syntax里升级swift就行,记得提前备份。
2、
Undefined symbols for architecture arm64
"_OBJC_CLASS_$_MyRequest", referenced from:
objc-class-ref in TodayViewController.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这是未引入相关文件的问题,如果没有导入主target的所有pods,建议直接新建文件,并重新命名。
3、直接导入主target的所有pods(也能在widget里使用第三方库)
直接在project-info-configurations里的debug和release里增加widget的相关lib库,即把None改为主项目的pods,猜测为直接导入主项目的pods库,此时cocoapods里的Podfile可以不用def end。而widget可以直接使用主项目的pods库(无论有没有.framework),此时打出的包也稍小(小于1m),问题就在于每次pod install / update 都需要重新设置,但是这个设置超出了我的理解范围,不知道原因,所以发出来大家可以讨论下
step1:
step2:
而通过def end 导入的pods库设置为:
4、
no such module
http://stackoverflow.com/questions/39569743/errors-after-updating-to-xcode-8-no-such-module-and-target-overrides-the-em
5、
[!] The `widget [Debug]` target overrides the `OTHER_CFLAGS` build setting defined in `Pods/Target Support Files/Pods-widget/Pods-widget.debug.xcconfig'. This can lead to problems with the CocoaPods installation
这是xcode的设置问题,一般会成对出现(主target和extension)相关的还有
'ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'
其中修改的地方只有两处
待续....
--------
由于xcode版本、iOS版本、swift版本、cocoapods版本、不同第三方库的设置的不同,造成一开始觉着很轻松的widget开发,遇到的问题也越来越多,需要完善和优化的地方也有不少。