ios开发——开发总结篇&开发中常见错误和警告总结
开发中常见错误和警告总结(七)
CGPoint randomPoint()
{
int half = 32;
int freesize = 240 - 2 * half;
return CGPointMake(random() % freesize + half, random() % freesize + half);
}
warning:No previous prototype for function "randomPoint"。如何取消这个警告错误呢?方法尝试了这两种都可以:
- 1.方法上加修饰符static
- 2.或者Project-Info -> TARGETS ->Build Settings -> LLVM GCC4.2 - Warnings组 -> Missing Function Prototypes Yes->No
2:使用Reachability的问题) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
做ios网络开发的肯定会用到苹果的官方库Reachability。warning:
1 + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
中
Declaration of ‘struct sockaddr_in‘ will not be visible outside of this function
解决办法很简单,Reachability.h中最前面添加头文件:#import <netinet/in.h>
开发中常见错误和警告总结(八)
Swift中”[AnyObject]?does not have a member named generator”处理
有个小需求,需要遍历当前导航控制器栈的所有ViewController。UINavigationController类自身的viewControllers属性返回的是一个[AnyObject]!数组,不过由于我的导航控制器本身有可能是nil,所以我获取到的ViewController数组如下:
var myViewControllers: [AnyObject]? = navigationController?.viewControllers
获取到的myViewControllers是一个[AnyObject]?可选类型,这时如果我直接去遍历myViewControllers,如下代码所示
for controller in myViewControllers {
...
}
编译器会报错,提示如下:
[AnyObject]? does not have a member named "Generator"
实际上,不管是[AnyObject]?还是其它的诸如[String]?类型,都会报这个错。其原因是可选类型只是个容器,它与其所包装的值是不同的类型,也就是说[AnyObject]是一个数组类型,但[AnyObject]?并不是数组类型。我们可以迭代一个数组,但不是迭代一个非集合类型。
在stackoverflow上有这样一个有趣的比方,我犯懒就直接贴出来了:
To understand the difference, let me make a real life example: you buy a new TV on ebay, the package is shipped to you, the first thing you do is to check if the package (the optional) is empty (nil). Once you verify that the TV is inside, you have to unwrap it, and put the box aside. You cannot use the TV while it‘s in the package. Similarly, an optional is a container: it is not the value it contains, and it doesn‘t have the same type. It can be empty, or it can contain a valid value.
用Xcode 7 beta 3在真机(iOS 8.3)上运行一下我们的工程,结果发现工程编译不过。看了下问题,报的是以下错误:
ld: ‘/Users
/**/
Framework/SDKs/PolymerPay/Library/mobStat/lib**SDK.a(**ForSDK.o)’ 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
bitcode是被编译程序的一种中间形式的代码。包含bitcode配置的程序将会在App store上被编译和链接。bitcode允许苹果在后期重新优化我们程序的二进制文件,而不需要我们重新提交一个新的版本到App store上。
- 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
要么让第三方库支持,要么关闭target的bitcode选项。
实际上在Xcode 7中,我们新建一个iOS程序时,bitcode选项默认是设置为YES的。我们可以在”Build Settings”->”Enable Bitcode”选项中看到这个设置。
开发中常见错误和警告总结(十)
混编常见错误:
-
把 Swift 和 Objective-C 文件看作相同的代码集合,并注意命名冲突。
-
如果你使用了框架,确保在Packaging下的Defines Module编译设置被设置为 Yes。
-
如果你使用了 Objective-C 桥接头文件,确保 Swift 编译器中 Objective-C 桥接头文件的编译设置Code Generation有一个与项目相关的头文件的路径。这个路径必须是头文件自身的路径,而不是它所在的目录。
-
Xcode 使用你的工程模块名,而不是以target的名称来命名 Objective-C 桥接头文件以及为 Swift 代码 自动生成的头文件。详见 Naming Your Product Module。
-
为了在 Objective-C 中可用, Swift 类必须是 Objective-C 类的子类,或者用 @objc 标记。
-
当你将 Swift 导入到 Objective-C 中时,记住 Objective-C 不会将 Swift 独有的特性转化成 Objective-C 对应的特性。详见列表 Using Swift from Objective-C。
-
如果你在 Swift 代码中使用你自己的 Objective-C 类型,确保先将对应的 Objective-C 头文件导入到你的 Swift 代码中,然后才将 Swift 自动生成的头文件导入到 Objective-C .m 源文件中来访问 Swift 代码。
-
用private修饰符标记的 Swift 声明不会出现在自动生成的头文件中。私有声明不会暴漏给 Objective-C,除非它们被明确标记有@IBAction,@IBOutlet或者@objc等。
-
对于应用 targets 而言,如果有 Objective-C 桥接头文件时,被internal修饰符标记的声明会出现在自动产生的头文件中。
-
对于框架 targets 而言,只有被public修饰符标记的声明才会出现在自动生成的头文件中。你仍然可以在框架中的 Objective-C 部分使用被internal修饰符标记的 Swift 方法和属性,只要它们声明所在的类继承自 Objective-C 类。关于访问级别修饰符的更多信息,请查看The Swift Programming Language中的访问控制(Access Control)
开发中常见错误和警告总结(十一)
iOS资源按需加载:
启用按需加载资源
对于支持iOS 9.0及以后的app,按需加载资源是默认开启的。你也可以在target的build settings中手动更改。
启用或关闭按需加载资源:
-
在project navigator中选择工程文件。
-
在project editor中选择对应的target。
-
选择Build Settings选项卡。
-
展开Assets分类。
提示:可以在Build Settings选项卡右上角的搜索框中输入“Assets”,来快速定位到Assets分类。
-
设置Enable On-Demand Resources的值。
-
-
Yes为这个target开启按需加载资源。
-
No为这个target关闭按需加载资源。
-
开发中常见错误和警告总结(十二)
混编总结
Swift与Objective-c的代码相互调用,并不像Objective-c与C/C++那样方便,需要做一些额外的配置工作。无论是Swift调用Objective-c还是Objective-c调用Swift,Xcode在处理上都需要两个步骤:
Swift调用Objective-c代码
Xcode对于Swift调用Objective-c代码,除宏定义外,其它支持相对完善。
使用Objetvie-c的第一步
告诉Xcode、哪些Objective-c类要使用,新建.h头文件,文件名可以任意取,建议采用“项目名-Bridging-Header.h”命令格式。
Tips
Swift之IOS项目,在Xcode6创建类文件,默认会自动选择OS X标签下的文件,这时一定要选择iOS标签下的文件,否则会出现语法智能提示不起作用,严重时会导致打包出错。
第二步,Target配置,使创建的头文件生效
设置Objective-C Bridging Header时,路径要配置正确,例如:创建的名为“ILSwift-Bridging-Header.h”文件,存于ILSwift项目文件夹的根目录下,写法如下:
ILSwift/ILSwift-Bridging-Header.h
当然,在新项目中,直接创建一个Objective-c类,Xcode会提示:
直接选择Yes即可,如果不小心点了其它按钮,可以按照上面的步骤一步一步添加。
开发中常见错误和警告总结(十三)
混编总结
Objective-c调用Swift代码
Objective-c调用Swift代码两个步骤
第一步告诉Xcode哪些类需要使用(继承自NSObject的类自动处理,不需要此步骤),通过关键字@objc(className)来标记
1 import UIKit
2 @objc(ILWriteBySwift)
3 class ILWriteBySwift {
4 var name: String!
5 class func newInstance() -> ILWriteBySwift {
6 return ILWriteBySwift()
7 }
8 }
第二步引入头文件,Xcode头文件的命名规则为
示例如下:
#import "ILSwift-Swift.h"
不清楚SWIFT_MODULE_NAME可通过以下步骤查看
找不到$(SWIFT_MODULE_NAME)-Swift.h
1.遇到此问题可按以下步骤做常规性检查
-
确定导入SWIFT_MODULE_NAME)-Swift.h头文件的文件名正确
-
SWIFT_MODULE_NAME)-Swift.h在clean后没有重新构建,执行Xcode->Product->Build
2.头文件循环
在混合编程的项目中,由于两种语言的同时使用,经常会出现以下需求:在Swift项目中需要使用Objectvie-c写的A类,而A类又会用到Swift的一些功能,头文件的循环,导致编译器不能正确构建$(SWIFT_MODULE_NAME)-Swift.h,遇到此问题时,在.h文件做如下处理
//删除以下头文件
//#import "ILSwift-Swift.h"
//通过代码导入类
@class ILSwiftBean;
在Objevtive-c的.m文件最上面,添加
#import "ILSwift-Swift.h"
出现Use of undecalared identifier错误或者找不到方法,如下:
引起的原因有以下几种可能:
-
使用的Swift类不是继承自NSObject,加入关键字即可
-
SWIFT_MODULE_NAME)-Swift.h没有实时更新,Xcode->Product->Build
-
此Swift文件中使用了Objective-c不支持的类型或者语法,如private
出现部分方法找不到的问题,Xcode无智能提示:
-
此方法使用了Objective-c不支持的类型或者语法
苹果官方给出的不支持转换的类型
-
Generics
-
Tuples
-
Enumerations defined in Swift
-
Structures defined in Swift
-
Top-level functions defined in Swift
-
Global variables defined in Swift
-
Typealiases defined in Swift
-
Swift-style variadics
-
Nested types
-
Curried functions