swift3.0和Objective-C的交互需要注意这些

来源:互联网 发布:js正则判断是否是数字 编辑:程序博客网 时间:2024/06/06 12:44

投稿文章,作者: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中不可用

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 流产了怀不上宝宝怎么办 产妇脸上长斑怎么办 宝贝肚子涨气怎么办 七个月宝宝便秘怎么办 宝宝功能性便秘怎么办 苹果x手机卡了怎么办 宝宝不吃水果蔬菜怎么办 小宝宝不拉粑粑怎么办 小宝宝个子不高怎么办 孩子不开口说话怎么办 孩子吹空调发烧怎么办 孩子上学不想上怎么办 孩子上学想留级怎么办 孩子口算太慢怎么办 孩子浮躁没耐心怎么办 如果孩子打妈妈怎么办 孩子英语成绩不好怎么办 小孩说话发音不准怎么办 小孩gk发音不准怎么办 大学无英语基础怎么办 孩子应用题理解不透怎么办 嫉妒一个人好痛苦怎么办 爱嫉妒别人怎么办心理 总有人嫉妒我怎么办 从小嫉妒闺蜜怎么办 怕闺蜜比我好怎么办 孩子不会做应用题怎么办 当你嫉妒别人怎么办 单位社保发票丢失怎么办 单位医保发票丢失怎么办 图书明细没有给怎么办 拼音拼不到一起怎么办 孩子不会拼拼音怎么办 小孩子不会拼拼音怎么办 小孩拼音发音不准怎么办 孩子声调不会标怎么办 孩子拼音发音不准怎么办 孩子学拼音不会怎么办? 孩子不会拼生字怎么办? 对数字不敏感怎么办 孩子说话不算数怎么办