LoginSignup
148
147

More than 5 years have passed since last update.

既存アプリの Xcode 7.3 + Swift 2.2 対応

Last updated at Posted at 2016-03-22

概要

Xcode7.3にアップデートしたことで、Swiftのバージョンが2.2になりました。
これにより既存プロジェクトに大量にWarning, Errorが出たので対応したものをまとめました。

WarningのほとんどがSwift 3に向けてdeprecatedになったものの警告でした。
ここにある以外のWarningについても、GitHubのapple/swift-evolution をチェックすると原因がわかる思います。

Warning

'var' parameters are deprecated and will be removed in Swift 3

swift-evolution: SE-0003

修正前

func sayHelloTo(var name: String) {
    name = "Hello, \(name)."
    print(name)
}

修正後

func sayHelloTo(name: String) {
    var name = name
    name = "Hello, \(name)."
    print(name)
}

'++' is deprecated: it will be removed in Swift 3

swift-evolution: SE-0007

修正前

var index: Int = 0
index++

修正後

var index: Int = 0
index += 1

--についても同様。

C-style for statement is deprecated and will be removed in a future version of Swift

swift-evolution: SE-0007

修正前

// 昇順ループ
let array1: [Int] = [10, 20, 30, 40, 50]
for var i = 0; i < array1.count; i++ {
    print("\(i): \(array1[i])")
}


// 降順ループ
var array2: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for var i = array2.count - 1; i >= 0; i -= 1 {
    array2.removeAtIndex(i)
}
print(array2)   // []

修正後

対応方法はたくさんあります。

// 昇順ループ
let array1: [Int] = [10, 20, 30, 40, 50]

// 0 ..< array1.count の Rangeに対して for-in
for index in 0 ..< array1.count {
    print("\(index): \(element)")
}

// array1.enumerate()に対して for-in
for (index, element) in array1.enumerate() {
    print("\(index): \(element)")
}

// array1.enumerate()に対して forEach
array1.enumerate().forEach { (index, element) in
    print("\(index): \(element)")
}


// 降順ループ
var array2: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in (0 ..< array2.count).reverse() {
    array2.removeAtIndex(i)
}
print(array2)   // []

// 配列のインデックス配列を逆順にforEach
var array3: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
array3.indices.reverse().forEach {
    array3.removeAtIndex($0)
}
print(array3)   // []

Use '#selector' instead of explicitly constructing a 'Selector'

Use of string literal for Objective-C selectors is deprecated; use '#selector' instead

swift-evolution: SE-0022

NSNotificationCenter や UIControl などにメソッド名を渡す方法が変更になりました。

修正内容

文字列で指定されていたメソッド名を#selector(<Class>.<MethodName>)を使って指定します。
今までは文字列だけで参照されていたメソッドは、Xcode上でメソッドが呼び出されていることが捕捉できませんでしたが、#selector()に変わることで、メソッドが呼び出されていることがわかるようになります。

修正前

class SomeTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        refreshControl = UIRefreshControl()
        refreshControl.addTarget(
            self,
            action: "refresh",
            forControlEvents: .ValueChanged)
        tableView.addSubview(refreshControl)
    }

    func refresh() {
    }

修正後

class SomeTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        refreshControl = UIRefreshControl()
        refreshControl.addTarget(
            self,
            action: #selector(SomeTableViewController.refresh),
            forControlEvents: .ValueChanged)
        tableView.addSubview(refreshControl)
    }

    func refresh() {
    }

__FILE__ is deprecated and will be removed in Swift 3. please use #file

__LINE__ is deprecated and will be removed in Swift 3. please use #line

__FUNCTION__ is deprecated and will be removed in Swift 3. please use #function

swift-evolution: SE-0028
デバッグ用識別子の呼び出しが変わった。

This proposal renames the following identifiers:

__FILE__ -> #file
__LINE__ -> #line
__COLUMN__ -> #column
__FUNCTION__ -> #function (Added during review)
__DSO_HANDLE__ -> #dsohandle

修正前

print("\(__FILE__), \(__FUNCTION__), \(__LINE__)")

修正後

print("\(#file), \(#function), \(#line)")

Error

Use of unresolved identifier 'SomeEnumType'

Objective-Cの .h ファイルで定義している enum が Swiftファイルから参照できなくなりました。

@interfaceの内側で定義していたものを、外側に移動させるとエラーがなくなりました。

修正前

@interface Feedback : NSObject

typedef NS_ENUM(NSInteger, SomeEnumType) {
    SomeEnumTypeNone = 0,
    SomeEnumTypeA    = 1,
    SomeEnumTypeB    = 2,
    SomeEnumTypeC    = 3,
}

修正後

typedef NS_ENUM(NSInteger, SomeEnumType) {
    SomeEnumTypeNone = 0,
    SomeEnumTypeA    = 1,
    SomeEnumTypeB    = 2,
    SomeEnumTypeC    = 3,
}

@interface Feedback : NSObject

'(name: String, size: CGSize) -> UIFont' is not convertible to '(name: String, size: CGFloat) -> UIFont?'

UILabelfontプロパティにUIFontオブジェクトを代入しているところでエラーが発生しました。
原因は不明。

修正前

let label = UILabel()
if let font = UIFont(name: "AvenirNext-Medium", size: 12.0) { // UIFontのイニシャライザでエラー
    label.font = font
}

修正後

let label = UILabel()
let descriptor = UIFontDescriptor(name: "AvenirNext-Medium", size: 12.0)
label.font = UIFont(descriptor: descriptor, size: 12.0)
148
147
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
148
147