詳解Swift(14)〜C/Objective-Cとのデータ受け渡し

2016. 11. 13
この記事は詳解 Swift(初版第1刷)を元に、Xcode 7.3.1(Swift 2.2)下における差異を記述しています。



CHAPTER 14 C/Objective-Cとのデータ受け渡し



●14.1 データ型の互換性


・返されたポインタから値を取り出す

List14-3 において、本文中ではプレイグラウンドで動作しないとありますが、現在は問題なく動作します。

関数 ctime() の返り値は UnsafeMutablePointer<Int8> ですが、

let p = ctime(&current)
p.dynamicType        // UnsafeMutablePointer<Int8>.Type

その返り値 p を(本書にあるように UInt8 ではなく)Int8 に変換し、UnicodeScalar に更に変換しようとするとエラーになります。

print(UnicodeScalar(Int8(p[i])), terminator:"")        // error: cannot invoke initializer for type 'UnicodeScalar' with an argument list of type '(Int8)'

これは UnicodeScalar のイニシャライザが Int、UInt16、UInt32、UInt8 に対応しているものの Int8 には対応していないからかもしれません。
(「Apple Developer Documentation/Swift Standard Library/UnicodeScalar」参照)

もちろん定数 p を UnsafeMutablePointer で初期化する際も <Int8> ではなく本書にある通り <UInt8> で初期化する必要があります。

let p = UnsafeMutablePointer<UInt8>(ctime(&current))
for i in 0..<25 {
    print(UnicodeScalar(p[i]), terminator:"")        // Thu Nov 10 23:57:13 2016 など
}


・コマンドラインの引数リストにアクセスする

C_ARGC と C_ARGV は、iOS 8.3(Xcode 6.3(Swift 1.2)?)で削除されたようです。
(「Swift Changes/iOS 8.3 API Diffs」参照)


・Cの標準関数と文字列

プレイグラウンドで Resources に output.dat ファイルを作成して試そうとしましたが、書き込みや追加書き込みモードではファイルが開けなかったので断念しました。

let path = (NSBundle.mainBundle().pathForResource("output", ofType: "dat"))!
var fp: UnsafeMutablePointer<FILE> = fopen(path, "r")        // 成功
var fp: UnsafeMutablePointer<FILE> = fopen(path, "w")        // 失敗
var fp: UnsafeMutablePointer<FILE> = fopen(path, "a")        // 失敗


・T**型の引数の扱い

List14-7 は著者の目的と少々離れる修正が必要となります。

まず変数 err は変更されないので定数にしてはどうかという警告が出ます。

var err: NSError? = nil        // warning: variable 'err' was never mutated; consider changing to 'let' constant

let err: NSError? = nil

ただし最終的に err は使用しません。

次に変数 cont ですが入力補完で気付くように contentsOfFile:encoding:error は使用できません。

var cont = NSString(contentsOfFile: path, encoding: NSASCIIStringEncoding, error: &err)
// error: argument labels '(contentsOfFile:, encoding:, error:)' do not match any available overloads

これに関しては「teratail/CSV - CSVファイルを読み込む実装でString型に変換する時処理が止まる(30501)」にあるように、Swift 2.0 で contentsOfFile:encoding:error が廃止になり、代わりに try? 演算子を使用したオプショナル束縛構文に書き換える必要があるようです。

その場合 try? 演算子はエラーが発生した場合に nil を返すため、エラー内容を保持する定数 err が不要になり、cont が nil かどうかを判定する if 文は文字列 "error" を返すだけになるので、オプショナル束縛構文に組み込んだ方が良いでしょう。

またファイルの読み込みに成功した場合の cont は String 型の定数に、失敗した場合は単に文字列 "error" を返すだけになりますので、関数 readfile の返り値は NSString 型にします。

以上の修正を行った関数 readfile は以下のようになります。

func readfile(path:String) -> NSString {
    if let cont = try? NSString(contentsOfFile: path, encoding: NSASCIIStringEncoding) {
        return cont
    }else {
        return "Error"
    }
}

したがって存在しないファイルパス "nobody" を指定して実行した場合、残念ながらエラー内容を出力できず単に "Error" という文字列が返ります。

readfile("nobody")        // Error


Resources に適当な文字列を入れたテキストファイル(ここでは output.dat )を追加した場合は以下のようになります。

let path = (NSBundle.mainBundle().pathForResource("output", ofType: "dat"))!
readfile(path)        // Where do we come from? What are we? Where are we going?



●14.2 対応付けられたデータ型


・配列

詳解Swift(8)〜クラスと継承」で述べたように、現在は AnyObject 型の定数・変数を as 演算子でダウンキャストすることはできませんので、as? 演算子でオプショナル型として返すか、as! 演算子で強制ダウンキャストすることになります。

AnyObject 型配列の定数 elm の要素が全て文字列の場合、as? ならオプショナル String 型配列、as! なら String 型配列が返りますが、文字列以外の要素が混在している場合は前者は nil が返り、後者では致命的エラーが発生します。

let elm: [AnyObject] = ["スノードロップ", "カトレア", "ナイトフロックス", 2]
var strelm0 = elm as [String]        // error: '[AnyObject]' is not convertible to '[String]'; did you mean to use 'as!' to force downcast?
var strelm1 = elm as? [String]       // nil
var strelm2 = elm as! [String]      // fatal error: array cannot be bridged from Objective-C

また AniyObject 型配列 elm から高速列挙で String 型の要素を取り出した場合は String 型配列になりますが、クロージャの場合は AniyObject 型配列になります。

var strelm_ = elm.filter{ $0 is String }
strelm_.dynamicType        // Array<AnyObject>.Type
print(strelm_)        // [スノードロップ, カトレア, ナイトフロックス]


・辞書

配列と同様に、as 演算子ではエラーになるので as? 演算子または as! 演算子を使用することになります。

let pinfo = info as [String:Int]        // error: 'NSDictionary' is not convertible to '[String : Int]'; did you mean to use 'as!' to force downcast?

let pinfo = info as? [String:Int]        // ["Level": 5, "Height": 161, "Grade": 2]


・NSValue

プレイグラウンドで試してみます。
(「Stack Overflow/ios - How to convert CGPoint in NSValue in swift?」参照)

var size = CGSize(width: 2, height: 3)
size.dynamicType        // __C.CGSize.Type
var val = NSValue(CGSize: size)        // NSSize: {2, 3}
val.dynamicType        // NSConcreteValue.Type

var sz = CGSize()
val.getValue(&sz)
print(sz)        // (2.0, 3.0)

NSConcreteValue クラスは NSValue クラスのサブクラス(コンクリートクラス)です。
(「こたつつきみかん/見えないクラス群」、「マイナビニュース/ダイナミックObjective-C (32) 抽象クラスとクラスクラスタ」参照)



Apple Developer Documentation/Swift Standard Library/UnicodeScalar

Swift Changes/iOS 8.3 API Diffs

teratail/CSV - CSVファイルを読み込む実装でString型に変換する時処理が止まる(30501)

Stack Overflow/ios - How to convert CGPoint in NSValue in swift?

こたつつきみかん/見えないクラス群

マイナビニュース/ダイナミックObjective-C (32) 抽象クラスとクラスクラスタ

詳解 Swift 改訂版(Amazon)
 

詳解Swift(13)〜ジェネリクス

2016. 11. 08
この記事は詳解 Swift(初版第1刷)を元に、Xcode 7.3.1(Swift 2.2)下における差異を記述しています。



CHAPTER 13 ジェネリクス



●13.3 ジェネリクスによる型定義


・要素の重複がない配列の定義

List13-4において、要素を探す関数 find は現在エラーが出ます。

if find(elems, key) == nil {        // error: 'find' is unavailable: call the 'indexOf()' method on the collection

これに関しては「詳解Swift(5)〜基本的なデータ型」の「5.3 配列/配列のメソッド」で解説したように、Xcode 7.0 でfind() が indexOf() に改名されたためですので、修正する必要があります。
(「Qiita/[Swift] 配列と辞書」参照)

if elems.indexOf(key) == nil {

ちなみに関数 indexOf() はジェネリック関数ではありません。

extension CollectionType where Generator.Element : Equatable {
    /// Returns the first index where `value` appears in `self` or `nil` if
    /// `value` is not found.
    ///
    /// - Complexity: O(`self.count`).

    @warn_unused_result
    public func
indexOf(element: Self.Generator.Element) -> Self.Index?
}

関数 indexOf() はプロトコル CollectionType の条件付き拡張定義です。


・型パラメータの書き方

プロトコル CollectionType は( _CollectionType ではなく)Indexable と SequenceType を継承しており、また付属型として GeneratorType も使っています。

public protocol CollectionType : Indexable, SequenceType {
    (中略)
    associatedtype Generator : GeneratorType = IndexingGenerator<Self>
    (中略)
    associatedtype SubSequence : Indexable, SequenceType = Slice<Self>
    (中略)
}

public protocol Indexable {
    (中略)
    associatedtype Index : ForwardIndexType
    (中略)
}

public protocol SequenceType {
    (中略)
    associatedtype Generator : GeneratorType
    (中略)
    associatedtype SubSequence
    public subscript (position: Self.Index) -> Self.Generator.Element { get }
    (中略)
}

public protocol GeneratorType {
    (中略)
    associatedtype Element
    (中略)
    public mutating func next() -> Self.Element?
}


・プロトコルの付属型

詳解Swift(10)〜プロトコル」で述べたように、Xcode 7.3 から付属型の宣言には typealias の代わりに associatedtype を使うようになっています。


・パラメータと付属型のマッチ

現在、構造体 Array は CollectionType と MutableCollectionType、_DestructorSafeContainer を継承しています。

public struct Array<Element> : CollectionType, MutableCollectionType, _DestructorSafeContainer {
    public var startIndex: Int { get }
    public var endIndex: Int { get }
    public subscript (index: Int) -> Element
    public subscript (subRange: Range<Int>) -> ArraySlice<Element>
}

そして CollectionType では、startIndex と endIndex の型は Index になっています。

extension CollectionType where Self : _CollectionWrapperType, Self.Index == Self.Base.Index {
    public var startIndex: Self.Index { get }
    public var endIndex: Self.Index { get }
    public subscript (position: Self.Index) -> Self.Base.Generator.Element { get }
    (中略)
}

また Array のsubscript の返り値は T ではなく Element になっています。

List13-7 において、要素の重複がない配列を出力する際、MySet のインスタンス内のプロパティ elems に直接アクセスするなら List13-4 での構造体 MySet の定義で sucscript を設定する必要はありません。
プロパティが1つだけなのに subscript を設定しているのは、インスタンス名[添字]でアクセスしたかったからと思われます。

print(" \(set[i])", terminator:"")        // インスタンス名[添字]でアクセスするにはsubscriptが必要

print(" \(set.elems[i])", terminator:"")        // インスタンス内のプロパティに直接アクセスするならsubscriptは不要


・プロトコルSequenceTypeに適合させる

List13-8 の構造体 MySetGenerator において、配列 array を定数として定義していますが、「詳解Swift(3)〜構造体」で述べたように定数プロパティへの割り当ては一度のみとなったため変数に修正します。

private let array:[T] = []        // error: immutable value 'self.array' may only be initialized once

private var array:[T] = []

また関数 next() で array の添字 index を後置インクリメントしていますが、インクリメント/デクリメント演算子は Swift 3.0 で削除するため廃止になったので修正します。

return index >= array.count ? nil : array[index++]        // '++' is deprecated; it will be removed in Swift 3

if index >= array.count {
    return nil
}else {
    let index_ = index
    index += 1
    return array[index_]

}



Qiita/[Swift] 配列と辞書

詳解 Swift 改訂版(Amazon)
 

詳解Swift(12)〜クロージャ

2016. 11. 04
この記事は詳解 Swift(初版第1刷)を元に、Xcode 7.3.1(Swift 2.2)下における差異を記述しています。



CHAPTER 12 クロージャ



●12.1 クロージャの宣言


・クロージャの仮引数と返り値の型宣言

定数 c5 の例において、本書では単一文での return 文は返り値の型推論は行われないのでエラーが出るとありますが、現在エラーは出ません。

let c5 = { return 10.0 / 2.5 }        // エラーなし

これに関しては「Xcode 6 Release Notes(Xcode 6.3 Release Notes/Changes, Enhancements, and Notes/Swift Language Enhancements)」に、Swift 1.2 での機能強化で単一式のクロージャの型推論が改善されたと記述があります。

「単一式のクロージャにおける型推論は、いくつかの点で改善されました。

・単一の return 文から成るクロージャは、現在は単一式のクロージャとして型チェックされています。

・非 Void の返り値の型を持つアノテーションの無い単一式のクロージャは、現在は Void コンテキストで使用することができます。

・戻り値の型のアノテーションが見つからないため複数文から成るクロージャの型が推論できなかった状況が、現在は適切に診断されます。」



・クロージャと関数の型

クロージャ式を変数に代入する例で、本書では変数の型を調べるためターミナル上でクロージャの定義を対話的に実行していますが、プレイグラウンドでは dynamicType で型を知ることができます。

let c1 = { (a:Int, b:Int) -> Double in
    return Double(a) / Double(b) }
c1.dynamicType        // ((Int, Int) -> Double).Type


・クロージャの複雑な型宣言

クロージャに対してオプショナル型の変数を定義する例は本書の通りです。

var cp1: (Int, Int) -> Double!
cp1.dynamicType        // ((Int, Int) -> ImplicitlyUnwrappedOptional<Double>).Type

var cp2: ((Int, Int) -> Double)!        // nil
cp2.dynamicType        // ImplicitlyUnwrappedOptional<(Int, Int) -> Double>.Type

クロージャのインスタンスを要素とする空配列の定義では () で優先順位を付けてもエラーになります。

var ca3 = [(Int, Int) -> Double]()        // エラー
var ca3 = [((Int, Int) -> Double)]()        // エラー

typealias MyClosure = (Int, Int) -> Double
var ca3 = [MyClosure]()
ca3.dynamicType        // Array<(Int, Int) -> Double>.Type

また簡略記法ではエラーが出るものでも、パラメータ付き型指定による本来の記法なら問題が解消されます。
(暗黙的開示オプショナル型の例では別のエラーが出ますが…)

var ca4 = (() -> ())!        // エラー

var ca4 = ImplicitlyUnwrappedOptional<() -> ()>()        // 'init()' is deprecated; Parameterless initializer will be removed in Swift 3. Use nil literal instead.
ca4.dynamicType        // ImplicitlyUnwrappedOptional<() -> ()>.Type


var ca5 = [() -> ()]        // エラー

var ca5 = Array<() -> ()>()
ca5.dynamicType        // Array<() -> ()>.Type



●12.2 変数のキャプチャ


・クロージャが参照型の変数をキャプチャする場合

List12-3 において、関数 makerZ のローカル変数 localvar はクラス MyInt のインスタンスであり、更新されないので定数にしたらどうかと警告が出ますので定数にしましょう。

またクロージャ内で localvar.value を前置インクリメントしていますが、インクリメント/デクリメント演算子は Swift 3.0 で削除するため廃止になったので修正します。

func makerZ(a:MyInt, s:String) -> () -> () {
    var localvar = a        // Variable 'localvar' was never mutated; consider changing to 'let' constant
    return { print("\(s): \(++localvar.value)") }        // '++' is deprecated; it will be removed in Swift 3
}


func makerZ(a:MyInt, s:String) -> () -> () {
    let localvar = a
    return { localvar.value += 1; print("\(s): \(localvar.value)") }
}


・メソッドとクロージャ

本書では列挙型や構造体のインスタンスメソッドはクラスのように扱うことができないと記述されていますが、列挙型や構造体のインスタンスメソッドでもクロージャのように扱えキャプチャすることができます。

// 列挙型

enum Direction : String {
    case Up = "上", Right="右", Down="下", Left="左"
    func drcString(drc:String) {
        print("\(drc):\(self.rawValue)")
    }
}

var d:Direction! = Direction.Down
var clo_0:((String)->())! = d.drcString
d = nil
clo_0("向き")        // 向き:下


// 構造体

struct Person {
    let name: String
    init(_ s:String) { name = s }
    func greet(msg:String) {
        print("\(msg), \(name)さん")
    }
}

var p: Person! = Person("朝子")
var clo_1:((String)->())! = p.greet
p = nil
clo_1("おはようございます")        // おはようございます, 朝子さん

ただし参照型のクラスと違い列挙型や構造体は値型なので、参照の循環などを考慮する必要はありません。



●12.3 クロージャの使い方と記法


・配列の整列

配列の要素を並べ替えて新しい配列を作るメソッド sorted は現在エラーが出ます。

let slist = list.sorted( { (a:String, b:String) -> Bool in a < b } )        // error: 'sorted' is unavailable: call the 'sort()' method on the array

これに関しては「詳解Swift(5)〜基本的なデータ型」の「5.3 配列/配列のメソッド」で解説したように、Xcode 7.0 でsorted() が sort() に改名されたためです。

let slist = list.sort( { (a:String, b:String) -> Bool in a < b } )        // ["OLD", "fig.pdf", "filelist1.swift", "sample.swift"]

また演算子 > の場合、記述の仕方によってエラーが出るとありますが現在はエラーが出ません。
(ちなみに「詳解 Swift 改訂版」ではこの件に触れられていません。)

let slist0 = list.sort( { $0 > $1 } )
print("slist0:\(slist0)")        // slist0:["sample.swift", "filelist1.swift", "fig.pdf", "OLD"]

let slist1 = list.sort( { (a:String, b:String) -> Bool in a > b } )
print("slist1:\(slist1)")        // slist1:["sample.swift", "filelist1.swift", "fig.pdf", "OLD"]

let slist2 = list.sort( > )
print("slist2:\(slist2)")        // slist2:["sample.swift", "filelist1.swift", "fig.pdf", "OLD"]

let slist3 = list.sort( { return $0 > $1 } )
print("slist3:\(slist3)")        // slist3:["sample.swift", "filelist1.swift", "fig.pdf", "OLD"]


・配列要素の選択

List12-6 の実行例で、フィルタの for-in 文でエラーが出ます。

for ch in $0 {        // error: type 'String' does not conform to protocol 'SequenceType'

これに関しては「詳解Swift(1)〜Swiftでプログラミング」の「1.2 制御構文/for-in文」で解説したように、Xcode 7.0 で String が SequenceType に準拠しなくなったためです。

したがって、文字列から文字を取り出すには .characters プロパティを使用する必要があります。

for ch in $0.characters {


・配列要素に対する操作

配列 dat から10以上のデータを昇順に並べて文字列に変換する例において、上記の「配列の整列」で述べたように sorted は sort に修正する必要があります。

let str_ = dat.filter{ $0 >= 10 }.sort( < ).map{ "\($0)" }        // ["13", "45", "80"]


また1から10までの和を求める例の2つ目において、reduce は関数なので「詳解Swift(2)〜関数」の「外部引数名」の項で述べたように第2引数以降は外部引数名を指定する必要があります。

let sum_ = numbers.reduce(0, +)        // error: missing argument label 'combine:' in call


let sum_ = numbers.reduce(0, combine: +)        // 55


・関数のカリー化と部分適用

関数 timesCurried などのカリー化関数構文は警告が出るようになりました。

func timesCurried_(a: Double)(b: Double) -> Double {        // Curried function declaration syntax will be removed in a future version of Swift; use a single parameter list

これに関しては「Xcode 7 Release Notes(Xcode 7.3 Release Notes/New Features/Swift)」に、Swift 3 でカリー化関数構文は廃止するためとの記述があります。

「カリー化関数構文は Swift 3 で削除される予定なので廃止されました。(23364870)」

したがってカリー化を止めるか専用構文を使用しない記述に修正する必要があります。
(「Qiita/Swift 初心者がまとめる Xcode 7.3 で Warning になった Swift の文法」、「Qiita/Swift 2.2 で変わったところ」参照)

func timesCurried_(a: Double, b: Double) -> Double {        // Fix-it   Replace ")(" with ","



●12.4 クロージャと強い参照の循環


・キャプチャによる強い参照

List12-7 において、関数 meter のクロージャ式で引数 distance を変数に指定していますが、Swift 3 で廃止になるとのエラーが出るので修正する必要があります。

return { (var distance:Int) in        // 'var' parameters are deprecated and will be removed in Swift 3


return { (dis:Int) in
        var distance = dis

また実行例において、「詳解Swift(1)〜Swiftでプログラミング」で述べたように do-while 文は repeat-while に名称変更、C 言語様式の for 文は非推奨になったため stride 型を使った for-in 文に修正する必要があります。

do {        // 'do-while' statement is not allowed; use 'repeat-while' instead
    (中略)
    for var d = 1000; d <= 5000; d += 1000 {        // C-style for statement is deprecated and will be removed in a future version of Swift
    (中略)
}while false


repeat {
    (中略)
    for var d in 1000.stride(through: 5000, by: 1000) {
    (中略)
}while false



Qiita/Swift 初心者がまとめる Xcode 7.3 で Warning になった Swift の文法

Qiita/Swift 2.2 で変わったところ

詳解 Swift 改訂版(Amazon)
 

詳解Swift(11)〜拡張

2016. 10. 17
この記事は詳解 Swift(初版第1刷)を元に、Xcode 7.3.1(Swift 2.2)下における差異を記述しています。



CHAPTER 11 拡張



●11.1 拡張の宣言


・システムの既存の型に対する拡張定義の例

List11-1において、「詳解Swift(5)〜基本的なデータ型」で述べたように文字列の文字数を数える countElements() は廃止になったので .characters.count に修正する必要があります。

return countElements(self)        // error: use of unresolved identifier 'countElements'


return self.characters.count



●11.2 拡張定義とプロトコルへの適合



・プロトコルへの適合

詳解Swift(8)〜クラスと継承」で説明したように、プレイグラウンドで Sources フォルダに Ounce.swift や Ounce+Ext.swift などのソースファイルを追加して試そうとしても、可視性の問題でうまくいかないのでご注意ください。


・プロトコルに適合するための定義が既に存在する場合

前述の通り、プレイグラウンドでは DayOfMonth+Printable.swift など個別ファイルに分けての実行はできません。

また「詳解Swift(10)〜プロトコル」で説明したように、プロトコル Printable はプロトコル名が CustomStringConvertible に変更されています。

なお本書の実行例では変数 d2 の出力が「1992/07/19 (Wed)」となっていますが、1992年7月19日は日曜日です。
(実際にプログラムを実行すると「1992/07/19 (Sun)」となります。)



詳解 Swift 改訂版(Amazon)
 

詳解Swift(10)〜プロトコル

2016. 10. 14
この記事は詳解 Swift(初版第1刷)を元に、Xcode 7.3.1(Swift 2.2)下における差異を記述しています。



CHAPTER 10 プロトコル



●10.1 プロトコルの宣言


・プロトコルの概要と例

List10-2 において、クラス Date にプロトコル Printable を採用しようとするとエラーが出ます。

class Date : Printable {        // error: 'Printable' has been renamed to 'CustomStringConvertible'

これは「Swift 1.2からSwift 2への移行 #cocoa_kansai」で示されているように、Swift 2.0 からプロトコル名が Printable から CustomStringConvertible に変更されたためのようです。

また List10-3 において、列挙型 Sex のメンバ Male、Female を switch 文で分岐する際、本書では「.」無しで指定していますが正常に動作します。
ただしプレイグラウンドの入力補完では「.」が入るので、「.」を入れた方が良いでしょう。

enum Sex : CustomStringConvertible {
    case Male, Female
    var description: String {
        switch self {
        case Male: return "男"             // 「.」が無くても正常に動く
        case .Female: return "女"        // 本来は「.」付きでメンバを指定する(入力補完では「.」が入る)
        }
    }
}


・プロトコルの使用例

本文での説明が少々分かり難いのですが、プロトコル Foretellable を採用したクラス Monthology の実行では以下のようにファイルを作成しています。

Person.swift:List10-2(クラス Date)+List10-3(列挙型 Sex)+List10-4(構造体 Person)
Foretellable.swift:List10-5(プロトコル Foretellable)
Monthology.swift:List10-6(変数 oracles・initFlag、クラス Monthology)
Rand.swift:List1-9(クラス Rand)+ List10-7(関数 shuffleArray)
main.swift:実行例(定数 she、変数 teller)

ちなみに「SBクリエイティブ/詳解 Swift サンプルダウンロード」には、本書中では中略されている変数 oracles のメッセージが略さずに載っています。

なお「詳解Swift(8)〜クラスと継承」で説明したように、プレイグラウンドで Sources フォルダにこれらのソースファイルを追加して試そうとしても、可視性の問題でうまくいかないのでご注意ください。

全ての定義を1つのプレイグラウンドファイル上に記述して試す場合、クラス Randや関数 shuffleArrayの定義については前方参照を考慮する必要はありませんが、乱数生成に使う種変数 seedの定義は(shuffleArray を呼び出す)クラス Monthology の定義より前に記述する必要があります。
Monthology の定義の後に seed の定義を記述した場合、shuffleArray の呼び出し時に「Use of unresolved identifier 'shuffleArray'」とエラーが出ます。

またクラス Monthology のインスタンスメソッド predict 内で使用している変数 s は、変更されないようなので定数にしたらどうかと警告が出ますので定数にしていいでしょう。

var s = "\(mon)月生まれの\(person.name)さんの\(subject)は、"        // Variable 's' was never mutated; consider changing to 'let' constant


let s = "\(mon)月生まれの\(person.name)さんの\(subject)は、"



●10.2 プロトコルと型


・プロトコルの継承

関数 predict の宣言でエラーが出ますが、これは「詳解Swift(2)〜関数(2.1 関数定義の基本/外部引数名)」で述べたように、関数の内部引数名と外部引数名を同じにするための # は使用できなくなったためで、第1引数の外部引数名は明示する必要があります。

func predict(#date: Date) -> String        // エラー


func predict(date date: Date) -> String



●10.4 プロトコルと付属型


・ネスト型とプロトコル

List10-10において、typealias を使って付属型を宣言すると警告が出るようになりました。

protocol Vector2D {
    typealias DataType        // Use of 'typealias' to declare associated types is deprecated; use 'associatedtype' instead
    var x : DataType { get set }
    var y : DataType { get set }
}

これに関しては「Xcode 7 Release Notes(Xcode 7.3 Release Notes/New Features/Swift)」に、typealias の代わりに associatedtype を使うようにと記述があります。(「Qiita/Swift 2.2の新機能: SE-0011: 付属型を宣言するための typealias キーワードを associatedtype に置き換える」参照)

「プロトコルにおける付属型は宣言に typealias を使用していましたが、新たに associatedtype で指定できるようになりました。

protocol P {
        associatedtype Ty
}

typealias キーワードは Swift 2.2 では許可されていますが、非推奨であり警告が発生します。
この警告は Swift 3 ではエラーになります。

詳細については Swift Evolution proposal SE-0011 を参照してください。(24159196)」


したがって以下のように修正する必要があります。

protocol Vector2D {
    associatedtype DataType
    var x : DataType { get set }
    var y : DataType { get set }
}



●10.5 プロトコルに適合する型の定義方法


・継承のあるクラス定義でSelfを使う

List10-18 において、「詳解Swift(3)〜構造体」で述べたように定数プロパティへの割り当ては一度のみとなったため、プロパティ latitude と longitude を定数として定義しているとエラーが出ます。

let latitude: Double = 0.0
let longitude: Double = 0.0
required init(lat:Double, lon:Double) {
        self.latitude = lat        // error: immutable value 'self.latitude' may only be initialized once
        // note: initial value already provided in 'let' declaration
        self.longitude = lon        // error: immutable value 'self.longitude' may only be initialized once
        // note: initial value already provided in 'let' declaration
}

したがってプロパティ latitude と longitude を変数にするか初期値を未設定にする必要があります。

var latitude: Double = 0.0
var longitude: Double = 0.0

またメソッド copy では、メタタイプ値からの初期化では明示的に「init」を参照しなければならないというエラーと、変数 nw が変更されないことから定数にすべきではないかと警告が出ますので修正する必要があります。

func copy() -> Self {
        var nw = self.dynamicType(lat:latitude, lon:longitude)
        // error: initializing from a metatype value must reference 'init' explicitly
        // warning: variable 'nw' was never mutated; consider changing to 'let' constant
        return nw
}


func copy() -> Self {
        let nw = self.dynamicType.init(lat:latitude, lon:longitude)
        return nw
}

List10-19 においても同様に、定数プロパティ name を定数から変数に、メソッド copy に .init を追加する必要があります。

class ViewPoint : GeoPoint {
    let name: String = ""
    required init(lat: Double, lon: Double) {
        self.name = "(none)"    // error: immutable value 'self.name' may only be initialized once
        // note: initial value already provided in 'let' declaration
        // note: change 'let' to 'var' to make it mutable
        super.init(lat: lat, lon: lon)
    }
    override func copy() -> Self {
        var nw = self.dynamicType(name:name, lat:latitude, lon:longitude)
        // error: initializing from a metatype value must reference 'init' explicitly
        // warning: variable 'nw' was never mutated; consider changing to 'let' constant
        return nw
    }


class ViewPoint : GeoPoint {
    var name: String = ""
    required init(lat: Double, lon: Double) {
        self.name = "(none)"
        super.init(lat: lat, lon: lon)
    }
    override func copy() -> Self {
        let nw = self.dynamicType.init(name:name, lat:latitude, lon:longitude)
        return nw
    }



Swift 1.2からSwift 2への移行 #cocoa_kansai

Qiita/Swift 2.2の新機能: SE-0011: 付属型を宣言するための typealias キーワードを associatedtype に置き換える

詳解 Swift 改訂版(Amazon)
 






Bose QuietComfort 20
Calendar
08 | 2017/09 | 10
Sun Mon Tue Wed Thu Fri Sat
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

Bose QuietComfort 20
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR