iOS杂文处世Swift

iOS开发——Swift 4.0 + Xcode9 适配小结

2017-11-29  本文已影响2282人  青苹果园
OC-Swift.jpeg

iOS开发中,我们需要根据用户需要去适配各种各样的版本,特别是苹果爸爸的每一次新版本发布,作为开发者的我们永远是最先知道的,并且奋斗在最前线:

  • Xcode适配
  • Swift版本更新
  • iPhone适配
  • iOS系统适配

这里主要介绍一下最新版 Swift 4.0 适配,并简单的说一下关于Xcode9特性与适配的问题
关于Swift新特性可以参考这里:Swift 4.0 新特性

前言

Xcode 9 中同时集成了 Swift 3.2 和 Swift 4。

总结:

当 Xcode 正式版发布后,现有的 Swift 代码可以直接升级到 Swift 3.2 而不用做任何改动,也可以后续再迁移到 Swift 4。 或者直接迁移到 Swift 4 也可以,Swift 4 相比 Swift 3 的 API 变化还是不大的,很多第三方库都可以直接用 Swift 4 编译。 Swift 1 到 2 和 Swift 2 到 3 的迁移的痛苦在 3 到 4 的迁移上已经大大改善了。

适配

关于Swift 4适配中OC与Swift混编的坑比较多

查看当前版本

我这里已经是最新的版本:


Swift版本

当前环境

升级版本方式

更新Swift版本 updateSwiftVersinTwo.png

升级完成后可能会运行不起来

编译不通过

如果项目中之前有class和extension,有些也给OC调用。在OC的代码中,我们通过#import "ModuleName-Swift.h"导入了Swift文件。如果是Swift3.2,一切都能正常工作,但是在Swift4.0上,编译通不过了。

如果你看了Swift 4特性的话应该知道

swift4.0 最大的特性之一就是 @objc 修饰符的变化了,它主要处理 OC 和 swift 混编时一些方法的调用以及属性获取问题,swift4.0 将在 swift3.x 中一些隐式类型推断的特性去除以后,需要我们来手动管理 @objc 修饰符。

具体解决方案:

注意一点:swift3 使用 #selector 指定的方法,只有当方法权限为 private 时需要加 @objc 修饰符,swift4.0 都要加 @objc 修饰符 swift4.0 不再允许重载 extension 中的方法(包括instance、static、class方法)

运行时找不到属性

如果你有一个Swift类继承自UIViewController,OC中调用或者操作这个类[viewController valueForKey:@"userName"]这一KVC方法去获取这个自定义UIViewController中的userName这一属性的属性值。

这种方式,编译时是无法检查出问题的。但是在运行时,问题就来了,找不到这个属性。因为这个属性没有暴露给OC来进行调用。

解决方案:

(注意:这里可不像上面提到的extension一样,在这个已定义的UIViewController类前面加上@objc修饰符没有任何意义)。

编译警告

运行时警告会打印在控制台:

***Swift runtime: 
ClassName.swift:lineInFile:columnInLine: 
entrypoint -[ClassName methodName] generated by implicit @objc inference is deprecated and will be removed in Swift 4; 
add explicit @objc to the declaration to emit the Objective-C entrypoint in Swift 4 and suppress this message

同样:想要修复运行时警告,需要添加 @objc 修饰符到对应的方法或者符号。

运行时警告的常见原因:

其他修改

NSAttributedStringKey

swift3.x
public init(string str: String, attributes attrs: [AnyHashable : Any]? = nil)

swift4.0
public init(string str: String, attributes attrs: [NSAttributedStringKey : Any]? = nil)

String

废弃characters

swift 3
var count = string.characters.count

error
'characters' is deprecated: Please use String or Substring directly

swift 4
count = string.count

废弃addingPercentEscapes

swift 3
var url = @"http://www.example.com?username=姓名"
url = url.addingPercentEscapes(using: String.Encoding.utf8)!

error
'addingPercentEscapes(using:)' is unavailable: Use addingPercentEncoding(withAllowedCharacters:) instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent since each URL component or subcomponent has different rules for what characters are valid.

swift 4
uri = uri.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!

废弃substring(to:)

swift 3
let index = tagText.index(tagText.startIndex, offsetBy: MPMultipleStyleListItemTagMaxLength)

// 警告:'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range upto' operator.
let b = tagText.substring(to: index)

Swift 4
let a = tagText.prefix(upTo: index) //a 的类型是 Substring,不是 String

pod 引用

添加以下内容到 Podfile

post_install do |installer|
    installer.pods_project.targets.each do |target|
        if ['WTCarouselFlowLayout', 'XSLRevenue', 'OHHTTPStubs/Swift'].include? target.name
            target.build_configurations.each do |config|
                config.build_settings['SWIFT_VERSION'] = '3.2'
            end
        end
    end
end

系统方法

UITableViewDelegate 协议方法名变更,没有错误提示:

// swift3.x
func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: IndexPath) -> CGFloat 

// swift4.0
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 

总结

Swift3.2到Swift4.0的改变:

上一篇 下一篇

猜你喜欢

热点阅读