A Day In The Life

とあるプログラマの備忘録

今から始める Swift 3 対策

Xcode 7.3 から Swiftのバージョンが 2.2 になりました。このバージョンから Swift 3 に向けた deprecated(非推奨)警告が出るようになったのでその対策です。

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

結構話題になったインクリメント(デクリメントも)演算子の廃止の対策です。+=使えってことらしいです。Python もインクリメント演算子ないので、案外無くても困らないのかもしれませんね。

修正前
var i = 0
i++
修正後
var i = 0
i += 1

「--」も同じで「-=」を使いましょう。

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

C言語風の for 文が廃止になりました。下記の例だとはじめに「'++' is deprecated: it will be removed in Swift 3」の警告が出ます。インクリメント演算子を修正したあとにこの警告が出るので一気に修正してちゃいましょう。

修正前
for var i = 0; i < 10; ++i {
  //
}
修正後
for i in 0 ..< 10 {
  //
}

「i」は宣言しなくても良いみたいです。少し気持ち悪いけど慣れれば大丈夫です。

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

セレクタの渡し方が変わりました。Objective-c に近くなった印象です。個人的にも文字列でいいんかいなと思ってたのでまぁ妥当な変更だと思います。

修正前
class HogeViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    let button = UIButton()
    button.addTarget(self,
      action: "RespondToButton:",  // 警告
      forControlEvents: .TouchUpInside)
  }
  func RespondToButton(sender: UIButton) {
  }
}
修正後
class HogeViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    let button = UIButton()
    button.addTarget(self,
      action: #selector(HogeViewController.RespondToButton(_:))
      forControlEvents: .TouchUpInside)
  }
  func RespondToButton(sender: UIButton) {
  }
}

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

文字列の代わりにセレクタ関数を使ってた場合も同じです。

修正前
class HogeViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    let button = UIButton()
    button.addTarget(self,
      action: Selector("RespondToButton:"),  // 警告
      forControlEvents: .TouchUpInside)
  }
  func RespondToButton(sender: UIButton) {
  }
}
修正後
class HogeViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    let button = UIButton()
    button.addTarget(self,
      action: #selector(HogeViewController.RespondToButton(_:))
      forControlEvents: .TouchUpInside)
  }
  func RespondToButton(sender: UIButton) {
  }
}

'init()' is deprecated: init() will be removed in Swift 3. Use nil

init()が非推奨になりました。C言語で開発されたライブラリを使ってると遭遇確率が高いと思います。

修正前
var musicTrack = MusicTrack()
MusicSequenceGetIndTrack(musicSequence, 0, &musicTrack)
修正後
var musicTrack: MusicTrack = nil
MusicSequenceGetIndTrack(musicSequence, 0, &musicTrack)

アドレス渡しする前にコンストラクタ呼び出しするのは確かにおかしいので納得です。

UnsafeMutablePointerを使う場合

UnsafeMutablePointer を使ってる場合も同じ警告がでます。

修正前
let packetListPtr: UnsafeMutablePointer<MIDIPacketList> = UnsafeMutablePointer.alloc(1)
var packet = UnsafeMutablePointer<MIDIPacket>() //警告
packet = MIDIPacketListInit(packetListPtr)
修正後
let packetListPtr: UnsafeMutablePointer<MIDIPacketList> = UnsafeMutablePointer.alloc(1)
var packet: UnsafeMutablePointer<MIDIPacket> = nil
packet = MIDIPacketListInit(packetListPtr)

別の関数で Init するのに宣言時にコンストラクタ呼び出しするのはおかしいですね、これも納得です。

参考