Xcode预编译开关宏命令简化去除警告及优化代码结构思路
2024-02-13 04:32:02
Swift 语言跟 OC 语言的代码相互转换,特别是直接读取 OC 代码,在 Xcode 会报很多警告,其中 Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified) 警告可能是比较多的。
如果不修改代码,可以试一下下面方法:
- 命令行打开项目目录:
open <#path of workspace#>
- 打开命令工具,执行下面命令:
xcrun swiftc -emit-library -O -module-name <#projectName#> -I $(find. -name *.h) -I $(find. -name *.pch) -I $(find. -name *.m) -Xfrontend -warn-missing-module-import -D OBJC_OLD_DISPATCH_PROTOTYPE=1 $(find. -name *.mm | grep -v Modules)
Tips: 执行后,会自动在桌面生成 so 文件,注意需要将 so 文件放到 Application/Frameworks 中。
如果想手动修改代码的话:
在 Xcode 中,修改 OC 中的方法,增加类型标记即可,以这个方法为例:
- (NSString *)string;
改成:
- (nonnull NSString *)string;
因为只是修改了OC代码,所以在使用OC代码的地方就会报警告:
Using the Objective-C method '_Nonnull NSString *string' on a Swift type.
解决方法是在 OC 代码的引入处添加 @objc
:
@objc interface UserInfo : NSObject
这里,我们只是把 String 类型加了非空标记,换做其他类型也一样,如果是类,可以直接用 nonnull
替换之前的 class
。
另外:
Xcode 预编译开关也很方便,比如增加 __has_feature(objc_arc)
来判断是否支持 ARC,结构如下:
#if __has_feature(objc_arc)
@interface Student : NSObject {
}
@property (nonnull, strong) NSString *name;
@property int age;
- (void)sayHello;
- (void)sayGoodbye;
@end
#else
@interface Student {
NSString *_name;
int _age;
}
@property (nonnull) NSString *name;
@property int age;
- (void)sayHello;
- (void)sayGoodbye;
@end
#endif
如果项目中使用到了 ARC,__has_feature(objc_arc)
为真,就会自动编译第一部分,否则,就编译第二部分。
或者用 #if __IPHONE_OS_VERSION_MIN_REQUIRED
来判断是哪个版本以上,结构如下:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_12_0
// for iOS 12 and later
#elif __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_11_0
// for iOS 11 and later
#else
// for iOS 10 and earlier
#endif
还可以使用 __TYPEOF__(type)
来判断某一个类型是否存在,如果存在,就会自动编译这一部分,否则,这一部分代码就不会被编译,结构如下:
#if __TYPEOF__(Foundation.NSLog)
NSLog(@"hello world!");
#else
printf("hello world!");
#endif
最后,如果不想手动修改代码,不想使用宏指令,或者想提高代码可读性,也可以使用 if #available
结构,结构如下:
if #available(iOS 10.0, *) {
// Use iOS 10 APIs
} else {
// Fallback to earlier iOS APIs
}
无论你是想消除警告,还是想优化代码结构,Xcode 提供了很多预编译开关宏命令,都可以满足你的需求。