swift3.0和Objective-C的交互需要注意这些
投稿文章,作者:ZeroJ(Gitbub)
前言:
Swift3.0出来后, 可以看到改变很大, 和cocoa, Foundation...的交互也变得更方便了, 同时Swift编写的应用适配到iOS 7, 所以, 我们可以相信: 在未来使用swift的情况会逐渐增加了, 同时会涉及到OC和Swift在项目中并存的情况, 这里我重新读了官方的'Using swift with Cocoa and Objective-C(swift3)'的文档, 记录了一些个人觉得比较常用的笔记, 请大家选择性阅读(里面的代码 均来自文档)
OC的初始化方法在Swift中被引为
1
2
3
|
init(...) --- 如果初始化不会失败
init?(...) --- 如果初始化可能失败
init!(...) --- 否则
|
oc中的property里的(getter==, setter==)将会被swift忽略
id对应Anyobject 但是所有的Anyobject在swift中是可选值, 如果之前的值为可选值, 在被设置为Anyobject后就是多重可选值了
oc中的属性被标记为
1
2
3
|
nullable -> 在swift中相当于 ?
nonnull -> 在swift中相当于 非可选属性
未标记 -> 在swift中相当于 !
|
oc中的轻量级泛型也是对应与swift中的泛型
1
2
|
@property NSArray *dates
对应于 var dates: [Date]
|
swift 中的闭包默认捕获变量的方式相当于 oc中block中捕获被标记为 __block的变量方式 -> 就是说 闭包捕获到的是变量的指针
swift中只要不是在多线程中, 建议使用[unowned self]来避免循环引用, 多线程中, 建议使用[weak self]
== 操作符相当于oc中的isEqual: --- 即比较内容是否相等;=== 相当于oc中的指针比较
继承自NSObject的子类如果重写了isEquals:方法, 应当提供 hash 这个属性
不能在oc中继承swift的class
如果在swift中遇到oc中不支持的命名 可以利用 @objc(name)为他(属性 枚举, 方法名...)名个别名
@nonobjc 用来标记oc中不支持的
dynamic 将属性或者方法标记为dynamic就是告诉编译器把它当作oc里的属性或方法来使用(runtime),
当需要使用 KVO 或者 runtime的时候需要这样处理
当使用oc的 perform(selector, with:)方法的时候会返回一个可选值(指向AnyObject的指针);但是使用perform(:on:with:waitUntilDone:modes:) and perform(:with:afterDelay:)不会返回可选值
使用 #keyPath() 可以转换为string, #keyPath(class.property) == "property"
可用于KVC 例如person.value(forKey: #keyPath(Person.name)) = person.name
但是测试了下不能修改swift中的只读属性 不知道有什么方便的用处
NSClassFromString("MyFramework.MyClass")
@IBDesignable 用在class(UIView的子类)声明的前面, 然后就可以在storyBoard中的inspector编辑它;@IBInspectable 用在(UIView的子类)的属性前面, 然后就可以在storyBoard中的inspector编辑它 ,就想系统提供的可以设置颜色,字体...
swift中的属性默认是strong类型, 只有可选类型才能被标记为weak
oc中的 copy属性 转换为swift中的@NSCopying 必须遵守NSCoding协议
使用Core Data的时候所有的属性和方法需要标记为 @NSManaged
文档中指出"The corresponding reference types can be accessed with their original NS class name prefix."但是beta版本中不能很好的使用NS开头的
在oc和swift的桥接类型之间 直接使用 as 可以相互转换
因为swift中的String和NSString使用的编码方式不一样,所以在swift中要对string使用索引的时候 不能直接使用 Int 或者NSRange
需要使用String.Index and Range
swift会将Double, Int, Bool, Uint, Float和NSNumber桥接, 所以可以直接将
这些类型的值使用 as NSNumber转换为NSNumber, 但是逆向进行是得到的可选值 as?
Foundation 和Core Foundation 之间的类型有toll-free bridge('免费桥')
Foundation中的常量, 在swift中被换为类嵌套的枚举:NSJSONReadingOptions ----- >> JSONSerialization.ReadingOption
swift中使用 Core Foundation
如果使用swift处理过的函数不用我们手动管理内存分配;否则需要我们处理
区分的方式: 当返回值是 Unmanaged的时候说明需要我们处理
处理方法: 在使用返回的值之前调用他对应的takeUnretainedValue() 或takeRetainedValue()即可
例如let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue()
swift中Core Foundation里的类型 Ref后缀被去掉了 例如 CFTypeRef -> CFType
在oc的方法 使用 NS_SWIFT_NOTHROW , 将不会使用swift的异常抛出机制
swift中直接使用 is 来实现oc中isKindOfClass: 的功能
swift中使用kvo的条件: 1.必须继承自NSObject 2. 被观察的属性 要被标记为 dynamic
swift 中的单例很简单:
1
2
3
|
class Singleton {
static let sharedInstance = Singleton()
}
|
或者
1
2
3
4
5
6
7
|
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
|
swift和C的交互: c的函数在swift中均为全局函数
使用CF_SWIFT_NAME 这个宏可以将c中的属性或者函数转换为swift中
eg:
1
|
Color ColorCreateWithCMYK(float c, float m, float y, float k) CF_SWIFT_NAME(Color.init(c:m:y:k:));
|
对应为swift中
1
2
3
|
extension Color {
init(c: Float, m: Float, y: Float, k: Float)
}
|
c语言中的枚举 如果使用了NS_ENUM定义, 则在swift中被处理为对应的枚举
如果没有使用NS_ENUM定义, 则被处理为结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
};
//对应与
enum UITableViewCellStyle: Int {
case ` default `
case value1
case value2
case subtitle
}
typedef enum {
MessageDispositionUnread = 0,
MessageDispositionRead = 1,
MessageDispositionDeleted = -1,
} MessageDisposition;
|
对应与
1
2
3
4
|
struct MessageDisposition: RawRepresentable, Equatable {}
var MessageDispositionUnread: MessageDisposition { get }
var MessageDispositionRead: MessageDisposition { get }
var MessageDispositionDeleted: MessageDisposition { get }
|
c中的被NS_OPTIONS修饰的枚举, 在swift中是OptionSet类型, -> 即可以使用数组方式选多个值
1
2
3
4
5
6
7
8
9
|
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
|
对应与
1
2
3
4
5
6
7
8
9
|
public struct UIViewAutoresizing : OptionSet {
public init(rawValue: UInt)
public static var flexibleLeftMargin: UIViewAutoresizing { get }
public static var flexibleWidth: UIViewAutoresizing { get }
public static var flexibleRightMargin: UIViewAutoresizing { get }
public static var flexibleTopMargin: UIViewAutoresizing { get }
public static var flexibleHeight: UIViewAutoresizing { get }
public static var flexibleBottomMargin: UIViewAutoresizing { get }
}
|
在swift中直接使用 let resize = [. flexibleLeftMargin, . flexibleWidth...]
在swift中全局变量和存储属性都被保证只初始化一次,所以用来当作OC里面的#define定义的常量。同时swift全局函数可以当作OC里#define定义的复杂宏(类似函数)
swift中的条件编译 自定义编译符的方法(例如: DEBUG_LOGGING)
首先在project 的设置里面设置swift -D DEBUG_LOGGING to set the DEBUG_LOGGING
然后使用 #if DEBUG_LOGGING // 操作 #endif
1
2
3
4
5
6
7
8
9
10
11
|
#if arch(arm) || arch(arm64)
#if swift(>=3.0)
print( "Using Swift 3 ARM code" )
#else
print( "Using Swift 2.2 ARM code" )
#endif
#elseif arch(x86_64)
print("Using 64-bit x86 code.)
#else
print( "Using general code." )
#endif
|
swift中使用指针的方式
使用inout方式 &变量
使用UnsafePointer或者UnsafeMutablePointer
例如这个函数接受的参数可以传许多种
1
2
3
4
5
6
|
let x: Float = 0
func takesAPointer(_ p: UnsafePointer!) {
// ...
}
takesAPointer(&x)
takesAPointer([0.0,1.0])
|
在swift中申明oc中的包含可选实现方法的协议时需要在协议和方法前都标记objc
1
2
3
4
5
|
@objc public protocol MySwiftProtocol {
// 必须实现
func requiredMethod()
@objc optional func optionalMethod()
}
|
将oc的方法或者属性使用NS_SWIFT_NAME()可以为他们在swift中命一个别名
将oc的方法或使用 NS_SWIFT_UNAVAILABLE()可以让他在swift中不可用
swift3.0和Objective-C的交互需要注意这些相关推荐
- Swift3.0语言教程获取C字符串
Swift3.0语言教程获取C字符串 Swift3.0语言教程获取C字符串,为了让Swift和C语言可以实现很好的交互,开发者可以使用NSString的cString(using:)方法在指定编码格式 ...
- swift3.0友盟分享
经过(一)的讲解,大家应该可以按照友盟提供的测试账号可以集成友盟分享了,友盟目前集合了18个APP共27种分享,可以授权的有10个App:微信.QQ.新浪微博.腾讯微博.人人网.豆瓣.Facebook ...
- swift3.0阿里百川反馈
闲言少叙 直接上不熟 1.导入自己工程阿里百川demo中的Util文件,并引用其中的头文件 2.剩余就是swift3.0代码.在自己需要的地方书写 (前提是你已经申请了APPKey) 3.代码 // ...
- Swift3.0带来的变化汇总系列一——字符串与基本运算符中的变化
var string = "Hello-Swift" //获取某个下标后一个下标对应的字符 char="e" //swift2.2 //var char = s ...
- Swift3.0带来的变化汇总
var string = "Hello-Swift" //获取某个下标后一个下标对应的字符 char="e" //swift2.2 //var char = s ...
- swift3.0调用相册
swift3.0调用相册首先需要注意: 1.swift3.0中调用相机和相册会导致崩溃 1.需要在info.plist文件中加入两个键值对,如下: /// 都是String类型,内容任意的字符串即可 ...
- Swift3.0语言教程字符串与URL的数据转换与自由转换
Swift3.0语言教程字符串与URL的数据转换与自由转换 Swift3.0语言教程字符串与URL的数据转换 Swift3.0语言教程字符串与URL的数据转换与自由转换,字符串中的字符永久保存除了可以 ...
- Swift3.0语言教程字符串与文件的数据转换
Swift3.0语言教程字符串与文件的数据转换 Swift3.0语言教程字符串与文件的数据转换,如果想要对字符串中的字符进行永久保存,可以将字符串中的字符写入到文件中.当然,开发者也可以将写入的内容进 ...
- Swift3.0语言教程字符串转换为数字值
Swift3.0语言教程字符串转换为数字值 Swift3.0语言教程字符串转换为数字值,在NSString中,开发者可以将字符串转换为数字值,通过这些数字值可以实现一些功能,如加法运算.减法运算等.数 ...
最新文章
- 关于CVPR 2019投稿的一些感想
- 【C 语言】数组 ( 验证二维数组内存是线性的 | 打印二维数组 | 以一维数组方式打印二维数组 | 打印二维数组值和地址 )
- MySQL数据类型中DECIMAL的作用和用法
- pytorch 笔记:DataLoader 扩展:构造图片DataLoader
- JS滚动条到网页底部自动加载更多内容
- Android—简单路由框架实践
- onmouseover-onmouseout
- Apache Apollo REST API
- Android bootchart分析
- CREO 6.0 - 基础 - 01 - 零件 - 零件的装配 - 零件的移动、偏转、角度角度设定
- 河南城建计算机网络试卷,河南城建计算机网络技术学习心得体会.docx
- python免费课程400节-海口少儿Python编程语言培训机构
- 计算机视觉中的特征提取方式
- Java400 道面试题通关宝典助你进大厂,Java 后端工程师需要掌握的知识
- 「ggplot2练习」画基因结构图
- 那些年陪伴我们搬砖的心灵的音乐
- 半夜撸 flap bird
- 2022-2028全球与中国生物基聚氨酯(PU)市场现状及未来发展趋势
- css flex换行且均匀分布
- hightCharts制作三维立体图