swift4からSwfit4.2へのバージョンアップ実装対応 ①

古いSwift言語で実装されたコードをバージョンアップしなければならないケースはSwiftエンジニアには少なくないでしょう。

この記事には、主にSwift4からSwift4.2にバージョンアップする時、変更しなければならないところをまとめしようと思います。

####１）別名（typealias）を定義してバージョンConvertを実現する

```swift:converter.swift
public typealias UIControlState = UIControl.State
```
上記ように、typealiasを利用して定義すると、元の実装を手をかけなくても、Swift４.２もSwift4も無難にコンパイルに通でしょう。
以下に、typealias（別名）を利用した一部の例を纏めて置きます。

```swift:converter.swift
#if swift(>=4.2)
public typealias UIControlState = UIControl.State
public typealias UIImageOrientation = UIImage.Orientation
public typealias UIImagePickerControllerSourceType = UIImagePickerController.SourceType
public typealias UIControlContentHorizontalAlignment = UIControl.ContentHorizontalAlignment
public typealias UIPageViewControllerNavigationDirection = UIPageViewController.NavigationDirection
public typealias UISearchBarStyle = UISearchBar.Style
public typealias UITableViewCellStyle = UITableViewCell.CellStyle
public typealias UITableViewCellEditingStyle = UITableViewCell.EditingStyle
public typealias UICollectionViewScrollPosition = UICollectionView.ScrollPosition
public typealias NSLayoutRelation = NSLayoutConstraint.Relation
public typealias NSLayoutAttribute = NSLayoutConstraint.Attribute

public typealias UIEventSubtype = UIEvent.EventSubtype

public typealias NSLayoutRelation = NSLayoutConstraint.Relation
public typealias NSLayoutAttribute = NSLayoutConstraint.Attribute
#endif
```

####２）定数変数を定義してバージョンConvertを実現する

Swiftのバージョンより異なく定義された実型に変数らは、以下のように定数変数を定義して使用される個所に代入する事で対応できる

```swift:converter.swift
#if swift(>=4.2)
let kUIViewNoIntrinsicMetric = UIView.noIntrinsicMetric
#else
let kUIViewNoIntrinsicMetric = UIViewNoIntrinsicMetric
#endif
```
以下に、定数変数を定義してバージョン更新した一部の例を纏めて置きます。

```swift:converter.swift
#if swift(>=4.2)
let kNSNotificationNameUIDeviceOrientationDidChange = UIDevice.orientationDidChangeNotification
let kNSNotificationNameUIKeyboardWillShow           = UIResponder.keyboardWillShowNotification
let kNSNotificationNameUIKeyboardWillHide           = UIResponder.keyboardWillHideNotification
let kUIApplicationWillEnterForeground               = UIApplication.willEnterForegroundNotification
let kUIKeyboardFrameBeginUserInfoKey                = UIResponder.keyboardFrameBeginUserInfoKey
let kUIKeyboardFrameEndUserInfoKey                  = UIResponder.keyboardFrameEndUserInfoKey
let kUIApplicationOpenSettingsURLString             = UIApplication.openSettingsURLString

let kUIViewNoIntrinsicMetric                    = UIView.noIntrinsicMetric
let kUIScrollViewDecelerationRateFast           = UIScrollView.DecelerationRate.fast
let kUITableViewAutomaticDimension              = UITableView.automaticDimension
let kUICollectionElementKindSectionHeader       = UICollectionView.elementKindSectionHeader
let kUIImagePickerControllerOriginalImage       = UIImagePickerController.InfoKey.originalImage

let kRunLoopModeCommon = RunLoop.Mode.common

public typealias NSAttributedStringKey = NSAttributedString.Key
let kNSAttributedStringKeyForegroundColor = NSAttributedString.Key.foregroundColor
let kNSAttributedStringKeyUnderlineStyle  = NSAttributedString.Key.underlineStyle
let kNSAttributedStringKeyUnderlineColor  = NSAttributedString.Key.underlineColor
let kNSAttributedStringKeyFont            = NSAttributedString.Key.font
let kNSUnderlineStyleStyleSingle          = NSUnderlineStyle.single
#else
let kNSNotificationNameUIDeviceOrientationDidChange = NSNotification.Name.UIDeviceOrientationDidChange
let kNSNotificationNameUIKeyboardWillShow           = NSNotification.Name.UIKeyboardWillShow
let kNSNotificationNameUIKeyboardWillHide           = NSNotification.Name.UIKeyboardWillHide
let kUIApplicationWillEnterForeground               = NSNotification.Name.UIApplicationWillEnterForeground
let kUIKeyboardFrameBeginUserInfoKey                = UIKeyboardFrameBeginUserInfoKey
let kUIKeyboardFrameEndUserInfoKey                  = UIKeyboardFrameEndUserInfoKey
let kUIApplicationOpenSettingsURLString             = UIApplicationOpenSettingsURLString

let kUIViewNoIntrinsicMetric                    = UIViewNoIntrinsicMetric
let kUIScrollViewDecelerationRateFast           = UIScrollViewDecelerationRateFast
let kUITableViewAutomaticDimension              = UITableViewAutomaticDimension
let kUICollectionElementKindSectionHeader       = UICollectionElementKindSectionHeader
let kUIImagePickerControllerOriginalImage       = UIImagePickerControllerOriginalImage

let kRunLoopModeCommon = RunLoopMode.commonModes

let kNSAttributedStringKeyForegroundColor = NSAttributedStringKey.foregroundColor.rawValue
let kNSAttributedStringKeyUnderlineStyle  = NSAttributedStringKey.underlineStyle.rawValue
let kNSAttributedStringKeyUnderlineColor  = NSAttributedStringKey.underlineColor.rawValue
let kNSAttributedStringKeyFont            = NSAttributedStringKey.font.rawValue
let kNSUnderlineStyleStyleSingle          = NSUnderlineStyle.styleSingle
#endif
```


####３）メソットは主にExtensionを書くことでバージョンConvert実現する
この実装方針のメリットは元のソースを触らなくても良いことでしょう。
例えCGRectのUIEdgeInsetsInsetRectメソットは以下のようにExtensionを作る

```swift:converter.swift
#if swift(>=4.2)
extension CGRect {
    public static func UIEdgeInsetsInsetRect(rect: CGRect, insets: UIEdgeInsets) -> CGRect {
        return rect.inset(by: insets)
    }
}
#else
extension CGRect {
    public func inset(by insets: UIEdgeInsets) -> CGRect {
        return UIEdgeInsetsInsetRect(self, insets)
    }
}
#endif
```

UIImageのファイルコンバートメソットは

```swift:converter.swift
#if swift(>=4.2)
extension UIImage {
    public func UIImagePNGRepresentation() -> Data? {
        return self.pngData()
    }
    public func UIImageJPEGRepresentation(compressionQuality: CGFloat) -> Data? {
        return self.jpegData(compressionQuality:compressionQuality)
    }  
}
#else
extension UIImage {
    func pngData() -> Data? {
        return  UIImagePNGRepresentation(self)
    }
    
    func jpegData(compressionQuality: CGFloat) -> Data? {
        return  UIImageJPEGRepresentation(self,compressionQuality)
    }
}
#endif
```
UIViewのbringSubviewToFrontメソットは

```swift:converter.swift
#if swift(>=4.2)
extension UIView {
    func bringSubview(toFront: UIView) {
        bringSubviewToFront(toFront)
    }
}
#else
extension UIView {
    func bringSubviewToFront(_ toFront: UIView) {
        bringSubview(toFront: toFront)
    }
}
#endif
```

UIViewControllerに変更されたメソットらは以下のように

```swift:converter.swift
#if swift(>=4.2)
extension UIViewController {
    var childViewControllers : [UIViewController] {
        return children
    }
    func addChildViewController(_ vc: UIViewController) {
        addChild(vc)
    }
    func removeFromParentViewController() {
        removeFromParent()
    }
    func didMove(toParentViewController: UIViewController?) {
        didMove(toParent: toParentViewController)
    }
    func willMove(toParentViewController: UIViewController?) {
        willMove(toParent: toParentViewController)
    }
}
#else
extension UIViewController {
    var children: [UIViewController] {
        return childViewControllers
    }
    func addChild(_ vc: UIViewController) {
        addChildViewController(vc)
    }
    func removeFromParent() {
        removeFromParentViewController()
    }
    func didMove(toParent: UIViewController?) {
        didMove(toParentViewController: toParent)
    }
    func willMove(toParent: UIViewController?) {
        willMove(toParentViewController: toParent)
    }
}
#endif
```

メソットではなく、変数名が変わった場合、例えUIActivityIndicatorViewのstyleは
以下のようにExtensionをかけば良いでしょう

```swift:converter.swift
#if swift(>=4.2)
extension UIActivityIndicatorView {
    public var activityIndicatorViewStyle: UIActivityIndicatorView.Style {
        get {
            return self.style
        }
        set(value) {
            self.style = value
        }
    }
}
#else
extension UIActivityIndicatorView {
    public var style: UIActivityIndicatorViewStyle {
        get {
            return self.activityIndicatorViewStyle
        }
        set(value) {
            self.activityIndicatorViewStyle = value
        }
    }
}
#endif
```

この以上纏めた方法なら、大部のSwiftバージョンアップ作業に助けになる感じですが、
残りの部分については次回の記事に引き続きしたいと思います。

上記の記述に何か問題点がございましたら、気軽くコメントくださったら大変ありがたいです。

>iOS、Androidアプリの制作なら、hq7781@gmail.comまで、
>法人並みに、信頼且つ満足できる製品を納品いたします