iOS
Swift
iOS9
Swift2.0

既存コードのSwift2.0とiOS9対応の暫定措置


mapの戻り値の警告

mapをfor文代わりに使っている時の戻り値を受け取らないと警告を受ける。

なお、for文で書かない理由はfilterでヒットしたオブジェクトに対してのみ実行したい等の理由から


1.2

let views:[UIView]

views.filter { $0.tag > 9 }.map { $0.hidden = true }


2.0

let views:[UIView]

_ = views.filter { $0.tag > 9 }.map { $0.hidden = true }

mapをapply代わりに使うのはよろしくないので、下記のように書くのが素直なようです。(コメント指摘反映)


fix?

let views:[UIView]

views.filter { $.tag > 9 }.forEach { $0.hidden = true }


ファクトリメソッドでのself()の使用禁止


1.2

class func create() -> Self {

return self()
}


2.0

class func create() -> Self {

return self.init()
}


値の再代入をしないvarの警告

swift1.2の頃はプロパティを変更するオブジェクトはvarで宣言し、セッター等を用いて変更していたが、swift2.0からはletで宣言してしまった方がいいようだ


1.2

var attributedStr = NSMutableAttributedString()

attributedStr.appendAttributedString(NSAttributedString(string: "hoge"))


2.0

let attributedStr = NSMutableAttributedString()

attributedStr.appendAttributedString(NSAttributedString(string: "hoge"))


NSErrorPointerを要求していたAPIの検査例外化

NSErrorのチェックが不要な場合、try?で成功すれば結果が、失敗した場合はnilが入ってくれるので、結構便利そう。必要な場合はdo { try hoge() } catch { }と書けばいい


1.2

extension String {

func decodeSanitization() -> String? {
let encodedData = dataUsingEncoding(NSUTF8StringEncoding)
let attributedOptions : [String: AnyObject] = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding]
let attributedString = encodedData != nil ? NSAttributedString(data: encodedData!, options: attributedOptions, documentAttributes: nil, error: nil) : nil
return attributedString?.string
}
}


2.0

extension String {

func decodeSanitization() -> String? {
guard let encodedData = dataUsingEncoding(NSUTF8StringEncoding) else { return nil }
let attributedOptions : [String: AnyObject] = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding]
let attributedString = try? NSAttributedString(data: encodedData, options: attributedOptions, documentAttributes: nil)
return attributedString?.string
}
}


一部のメソッドのプロパティ化


1.2

let tableView: UITableView

let indexPath = tableView.indexPathForSelectedRow()


2.0

let tableView: UITableView

let indexPath = tableView.indexPathForSelectedRow


1.2

let view: UIView

view.setTranslatesAutoresizingMaskIntoConstraints(false)


2.0

let view: UIView

view.translatesAutoresizingMaskIntoConstraints = false


guardの導入(途中で処理を切り上げる場合のif)

guardで意識的に処理を抜けていく書き方をした方が、ifのネストが深くならないのでよいかも。


1.2

let hoge: String?

if let fuga = hoge {
// do something
piyo(fuga)
} else { return }


2.0

let hoge: String?

guard let fuga = hoge else { return }
// do something
piyo(fuga)


funcの省略呼び出しの禁止?

そもそも1.2の時に可能だったのかよく知らないのですが、ラベルを省略している呼び方がコンパイル通っていたのが、通らなくなっていたので修正


1.2

func newTopics(topics: [Topic], range: NSRange) -> [Topic] { // do something }

let topics: [Topic]
let range: NSRange
let newTopics = newTopics(topics, range)


2.0

func newTopics(topics: [Topic], range: NSRange) -> [Topic] { // do something }

let topics: [Topic]
let range: NSRange
let newTopics = newTopics(topics, range: range)


nilチェック代わりの束縛構文の警告


1.2

let error: NSError?

if let e = error { // do something }


2.0

let error: NSError?

if let _ = error { // do something }


count関数がCollectionTypeのextensionとして実装


1.2

let str: String = "hoge"

let length = count(str.utf16)


2.0

let str: String = "hoge"

let length = str.characters.count


クラス宣言に@objcを付与する場合はNSObjectを継承する必要がある


1.2

@objc class Hoge {

}
@objc(Fuga) class Fuga {
}


2.0

@objc class Hoge : NSObject {

}
@objc(Fuga) class Fuga : NSObject {
}


一部のプロパティの非Optional化


  • NSURLのabsoluteStringの非Optional化

  • NSURLのschemeの非Optional化


1.2

let url: NSURL

let str: String = url.absoluteString ?? ""


2.0

let url: NSURL

let str: String = url.absoluteString


StringのstringByReplacingOccurrencesOfStringにdefault引数導入


1.2

let orig: String

let converted = orig.stringByReplacingOccurrencesOfString("\r\n", withString: "\n", options: nil, range: nil)


2.0

let orig: String

let converted = orig.stringByReplacingOccurrencesOfString("\r\n", withString: "\n")


join関数がSequenceTypeのextensionとして実装


1.2

let strs = ["hoge", "fuga", "piyo"]

let result = join(",", strs)


2.0

let strs = ["hoge", "fuga", "piyo"]

let result = strs.joinWithSeparator(",")


sorted関数がsortに


1.2

class Hoge {

var order: Int
}
let hoges: [Hoge]
let sorted = hoges.sorted { (lhs, rhs) in return lhs.order < rhs.order }


2.0

class Hoge {

var order: Int
}
let hoges: [Hoge]
let sorted = hoges.sort { (lhs, rhs) in return lhs.order < rhs.order }


enumerate関数/map関数がSequenceTypeのextensionとして実装


1.2

let strs: [String]

map(enumerate(strs)) { (index, str) in // do something }


2.0

let strs: [String]

strs.enumerate().map { (index, str) in // do something }


find関数がCollectionTypeのextensionのindexOfとして実装


1.2

let strs: [String]

let target: Strng
let index = find(strs, target)


2.0

let strs: [String]

let target: Strng
let index = strs.indexOf(target)


distance関数がForwardIndexTypeのexteinsionのdistanceToとして実装


1.2

let startIndex: Index

let endIndex: Index
let distance = distance(startIndex, endIndex)


2.0

let startIndex: Index

let endIndex: Index
let distance = startIndex.distanceTo(endIndex)


advance関数がBidirectionalIndexTypeのextensionのadvanceByとして実装


1.2

let startIndex: Index

let targetIndex = advance(startIndex, 20)


2.0

let startIndex: Index

let targetIndex = startIndex.advanceBy(20)


StringのtoInt関数がなくなった><

代わりにIntのinitを使う


1.2

let idStr: String = "1234"

let id = idStr.toInt()


2.0

let idStr: String = "1234"

let id = Int(idStr)


#availableの導入

WKWebViewを使う場合にWKWebViewのclassが存在するかどうかして分岐するコードが一般的でしたが、#available(iOS 8.0, *)が使えるようになっています


1.2

if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {

// WKWebViewを使う
}


2.0

if #available(iOS 8.0, *) {

// WKWebViewを使う
}


required init(coder: NSCoder) -> required init?(coder: NSCoder)

NSCodingを継承しているクラスのinit(coder:)を実装する時にsuperがinit?になっているために、init?で実装する必要があるようです


1.2

required init(coder: NSCoder) {

super.init(coder: coder)
// do something
}


2.0

required init?(coder: NSCoder) {

super.init(coder: coder)
// do something
}


LazyMapCollectionのarray関数がなくなった><

代わりにArrayのinitを使う


1.2

let dict: [Int:Int]

let values: [Int] = dict.values.array


2.0

let dict: [Int:Int]

let values: [Int] = Array(dict.values)


NSError()で適当にエラー設定しとくのができなくなった


1.2

let error = NSError()



2.0

let errorDomain = "domain"

let errorCode = 1
let localizedDescription = "ネットワークエラーだよ"
let localizedRecoverySuggestion = "回線確かめてー"
let error = NSError(domain: errorDomain, code: errorCode, userInfo: [NSLocalizedDescriptionKey:localizedDescription, NSLocalizedRecoverySuggestionErrorKey:localizedRecoverySuggestion])


Objective-Cでweakで宣言しているpropertyはoptionalとして扱う

@interface Hoge : NSObject

@property (weak, nonatomic) id delegate;
@end

swift1.2ではHogeクラスのdelegateはAnyObject型になるが、swift2.0ではAnyObject?型となる


#を用いた関数の内部パラメータと外部パラメータの共通化ができなくなってる?


1.2

func hoge(#fuga:Int) {

}
func hoge(#piyo:Int) {
}


2.0

func hoge(fuga fuga:Int) {

}
func hoge(piyo piyo:Int) {
}


App Transport Security 対策

iOS9からApp Transport Securityが導入されたために、http通信ができなくなっています。


Info.plist

Information Property List

- NSAppTransportSecurity <- Dictionaryとして追加
- - NSAllowsArbitraryLoads <- Booleanとして追加し、YESを指定
- - NSExceptionDomains <- Dictionaryとして追加
- - - 自分のドメイン(ex. example.com) <- Dictionaryとして追加
- - - - NSExceptionAllowsInsecureHTTPLoads <- Booleanとして追加し、YESを指定
- - - - NSExceptionMinimumTLSVersion <- Stringとして追加し、TLSv1.0を指定
- - - - NSExceptionRequiresForwardSecrecy <- Booleanとして追加し、NOを指定
- - - - NSIncludesSubdomains <- Booleanとして追加し、YESを指定
- - - - NSTemporaryExceptionAllowsInsecureHTTPLoads <- Booleanとして追加し、YESを指定

これだけの設定をすれば、iOS8の頃と同じ程度に通信はできるはずです。ただ、せっかくApple様が導入してくれたらセキュリティ機構なので、不要であればオプションは削除していきましょう♪


その他


  • NSKeyValueCodingのdictionaryWithValuesForKeysの引数

  • NSKeyValueCodingのsetValuesForKeysWithDictionaryの引数

  • UIWebViewのloadHTMLString

  • UIWebViewDelegateのwebView:didFailLoadWithErrorの引数

  • UICollectionViewのscrollToItemAtIndexPathの引数

  • UIVNavigationControllerのsetViewControllersの引数