Swift2.xからSwift3.0へ移行する際のプロトタイプ関連エラー

某プログラミングQAサイトで回答したものをいくつか集めてみました。大抵は定義をチェックして型を合わせてやれば解決するものがほとんどですがswiftの厳しい型チェックは初学者の方にはなかなか悩ましいようです。参考になれば良いと思い掲載します。（質問者さまのコードは改変して掲載してます）



## プロトタイプ関連のエラーその１

エラーメッセージ
```Cannot invoke initializer for type 'URL' with no arguments
```

改修前

```swift

webView = UIWebView(frame:CGRect(x: 50,y: 100,width: 150,height: 200))
webView.load(gifData,mimeType:"image/gif",textEncodingName:"utf-8",baseURL:URL())

```

改修後　

```swift
// swift 3.0

webView = UIWebView(frame:CGRect(x: 50,y: 100,width: 150,height: 200))
webView.load(gifData,mimeType:"image/gif",textEncodingName:"utf-8",baseURL:NSURL() as URL)

```

URL → NSURL() as URL


## プロトタイプ関連のエラーその2

エラーメッセージ
```argument labels do not match any available overloads timestamp
```

改修前

```swift

let timestamp: NSNumber = NSNumber(Int(Date().timeIntervalSince1970))

```

NSNumberのイニシャライザの定義を確認("NSNumber"を[option] + [command] + クリック)してみると...

```
public init(value: Int)
```

改修後

```swift
// swift 3.0

let timestamp: NSNumber = NSNumber(value:Int(Date().timeIntervalSince1970))

```

swift3.0で、外部引数名不要は明示的に「 _ 」が必要になりました。今回の場合はvalue:が必要です。


## プロトタイプ関連のエラーその3

エラー : キャスト箇所で落ちる

改修前

```swift

motionManager.startAccelerometerUpdates(to: OperationQueue.main, withHandler: {(accelerometerData:CMAccelerometerData?, error:NSError?) -> Void in

	// なんか処理

        } as! CMAccelerometerHandler)
//(略)

```

CMAccelerometerHandlerの定義を確認("CMAccelerometerHandler"を[option] + [command] + クリック)してみると...

```
public typealias CMAccelerometerHandler = (CMAccelerometerData?, Error?) -> Swift.Void
```

改修後

```swift
// swift 3.0

motionManager.startAccelerometerUpdates(to: OperationQueue.main, withHandler: {(accelerometerData:CMAccelerometerData?, error:Error?) -> Void in

	// なんか処理

        } // as! CMAccelerometerHandler)
//(略)
```

強制キャストでランタイム時にコケるケース。NSxxxはSwift3になってから大抵がNSなしになってます。(NSData → Data etc)

## プロトタイプ関連のエラーその4

エラーメッセージ
```Cannot convert  value of type ’Data’  to  closure result type ’NSData’```


改修前

```swift

    let dataImages: [NSData] = photos.map { (image) -> NSData in 
        UIImagePNGRepresentation(image)!
    }

```

UIImagePNGRepresentationの定義を確認("UIImagePNGRepresentation"を[option] + [command] + クリック)してみると...

```
public func UIImagePNGRepresentation(_ image: UIImage) -> Data?
```

改修後

```swift
// swift 3.0

    let dataImages: [Data] = photos.map { (image) -> Data in
        UIImagePNGRepresentation(image)!
    }
```

戻り値がData?です。その３と同じですね。


## プロトタイプ関連のエラーその5

エラー : デリゲートメソッドがコールされない

改修前

```swift

    private func centralManager(central: CBCentralManager,
                        didDiscoverPeripheral peripheral: CBPeripheral,
                        advertisementData: [String : AnyObject],
                        RSSI: NSNumber)
    {
        print("コールされました")
    }
```

改修後

```swift
// swift 3.0

    func centralManager(central: CBCentralManager,
                        didDiscoverPeripheral peripheral: CBPeripheral,
                        advertisementData: [String : AnyObject],
                        RSSI: NSNumber)
    {
        print("コールされました")
    }
```

Xcodeの補完機能にまかせてると、privateをつけられることがありますので注意が必要です。privateがつくと他のインスタンスからアクセスできなくなります。

## プロトタイプ関連のエラーその6

エラーメッセージ
```'CGRectMake' is unavailable in Swift```


改修前

```swift
let rect = CGRectMake(30, 60, 100, 100)
```
改修後

```swift
// swift 3.0
let rect = CGRect(x:30, y:60, width:100, height:100)
```

プロトタイプというより関数名そのものが変更になってます。ちなみに`CGRectZero`は`CGRect.zero`になりました。

## プロトタイプ関連のエラーその７

エラーメッセージ 1
```Type 'PageViewController' does not conform to protocol 'UIPageViewControllerDataSource'```

エラーメッセージ 2
```Value of type 'UIViewController' has no member 'isKindOfClass'```

改修前

```swift
extension PageViewController : UIPageViewControllerDataSource {

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {

        if viewController.isKindOfClass(ThirdViewController) {
            return getSecond()

        } else if viewController.isKindOfClass(SecondViewController) {
            return getFirst()
        } else {
            return nil
        }
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {

        if viewController.isKindOfClass(FirstViewController) {
            return getSecond()

        } else if viewController.isKindOfClass(SecondViewController) {
            return getThird()
        } else {
            return nil
        }
    }
}
```

ひとつ目のエラーは`UIPageViewControllerDataSource`の定義を確認します。上２つのファンクションは実装がマストであることが分かりますが、改修前のソースで定義されているものと微妙にシグニチャが違うので「実装されてないよ」とエラーになっているわけです。

#### UIPageViewControllerDataSourceプロトコル

```swift
public protocol UIPageViewControllerDataSource : NSObjectProtocol {

    @available(iOS 5.0, *)
    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?

    @available(iOS 5.0, *)
    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?

    @available(iOS 6.0, *)
    optional public func presentationCount(for pageViewController: UIPageViewController) -> Int // The number of items reflected in the page indicator.

    @available(iOS 6.0, *)
    optional public func presentationIndex(for pageViewController: UIPageViewController) -> Int // The selected item reflected in the page indicator.
}
```

ふたつ目のエラーは「メソッドがない」というもの。メソッドの「has no member」は名前が変更されたと思ってまず間違いないです。Swift3.0では、Objective-Cからの慣例を捨てるような動きがあり、以下のような変更ルールが採用されています。

`ex1 . 【Swift2.x】 xxxxWith(〜 →  【Swift3.0】 xxxx(with: 〜 `
`ex2 . 【Swift2.x】 xxxxOf(〜 → 【Swift3.0】 xxxx(of: 〜 `
`ex3 . 【Swift2.x】 xxxxFor(〜 → 【Swift3.0】 xxxx(for: 〜 `

第一引数であっても外部引数名の省略に「 _ 」が必要になったのはおそらくこのルールに伴うものなのでしょう。

改修後

```swift
extension PageViewController : UIPageViewControllerDataSource {

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

        if viewController.isKind(of: ThirdViewController.self) {
            return getSecond()
        } else if viewController.isKind(of: SecondViewController.self) {
            return getFirst()
        } else {
            return nil
        }
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {

        if viewController.isKind(of: FirstViewController.self) {
            return getSecond()
        } else if viewController.isKind(of: SecondViewController.self) {
            return getThird()
        } else {
            return nil
        }
    }
}
```