69
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

実装が楽になるSwiftのExtension集(Swift4)

Last updated at Posted at 2018-12-01

はじめに

私が使っているSwiftのエクステンションをまとめて紹介します。
少しでもSwiftを使っている方のご参考になればと思います:relaxed:

環境

  • Swift:4.0.2 or 4.2
    4.0.2と4.2の両方を紹介しています。
    特に記載がないものは共通です。

Storyboard上でUIViewの枠線の色・幅・角の半径を変更する

UIView+Border.swift
import UIKit

/// UIView拡張(枠線)
public extension UIView {
    
    // MARK: Properties
    
    /// 枠線の色
    @IBInspectable public var borderColor: UIColor? {
        get {
            return self.layer.borderColor.map { UIColor(cgColor: $0) }
        }
        set {
            self.layer.borderColor = newValue?.cgColor
        }
    }
    
    /// 枠線の幅
    @IBInspectable public var borderWidth: CGFloat {
        get {
            return self.layer.borderWidth
        }
        set {
            self.layer.borderWidth = newValue
        }
    }
    
    /// 角の半径
    @IBInspectable public var cornerRadius: CGFloat {
        get {
            return self.layer.cornerRadius
        }
        set {
            self.layer.cornerRadius = newValue
            self.clipsToBounds = newValue > 0
        }
    }
    
}

使い方

プロパティに @IBInspectable 属性を付けることで、StoryboardのAttributes inspectorから変更できるようになります。

スクリーンショット 2018-12-01 20.05.59.png

エクステンションでは @IBDesignable 属性を付けられないので、 UIButton などの標準クラスではStoryboard上に反映されないのが残念です。

用途

  • UIの実装をできる限りStoryboard上で完結させる

参考リンク

UIView→UIImageに変換する

UIView+Image.swift
import UIKit

/// UIView拡張(イメージ)
public extension UIView {
    
    // MARK: Public Methods
    
    /// ビュー→イメージに変換する
    ///
    /// サブビューもイメージ化される
    ///
    /// - Returns: 対象ビューのイメージ
    public func toImage() -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0.0)
        guard let context = UIGraphicsGetCurrentContext() else {
            print("現在のコンテキストを取得できませんでした。")
            return UIImage()
        }
        
        self.layer.render(in: context)
        
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
            print("ビューをイメージに変換できませんでした。")
            return UIImage()
        }
        
        UIGraphicsEndImageContext()
        
        return image
    }
    
}

使い方

let view = UIView()
let viewImage = view.toImage()

用途

  • 特定のビューをイメージに変換する
    ビューのスクリーンショットを撮る場合に使えます。

参考リンク

UIImage→Data(PNG, JPEG)に変換する

Swift 4.0.2

UIImage+Data.swift
import UIKit

/// UIImage拡張(データ)
public extension UIImage {
    
    // MARK: Public Methods
    
    /// イメージ→PNGデータに変換する
    ///
    /// - Returns: 変換後のPNGデータ
    public func toPNGData() -> Data {
        guard let data = UIImagePNGRepresentation(self) else {
            print("イメージをPNGデータに変換できませんでした。")
            return Data()
        }
        
        return data
    }
    
    /// イメージ→JPEGデータに変換する
    ///
    /// - Returns: 変換後のJPEGデータ
    public func toJPEGData() -> Data {
        guard let data = UIImageJPEGRepresentation(self, 1.0) else {
            print("イメージをJPEGデータに変換できませんでした。")
            return Data()
        }
        
        return data
    }
    
}

Swift 4.2

UIImage+Data.swift
import UIKit

/// UIImage拡張(データ)
public extension UIImage {
    
    // MARK: Public Methods
    
    /// イメージ→PNGデータに変換する
    ///
    /// - Returns: 変換後のPNGデータ
    public func toPNGData() -> Data {
-       guard let data = UIImagePNGRepresentation(self) else {
+       guard let data = self.pngData() else {
            print("イメージをPNGデータに変換できませんでした。")
            return Data()
        }
        
        return data
    }
    
    /// イメージ→JPEGデータに変換する
    ///
    /// - Returns: 変換後のJPEGデータ
    public func toJPEGData() -> Data {
-       guard let data = UIImageJPEGRepresentation(self, 1.0) else {
+       guard let data = self.jpegData(compressionQuality: 1.0) else {
            print("イメージをJPEGデータに変換できませんでした。")
            return Data()
        }
        
        return data
    }
    
}

Swift 4.2からは UIImagepngData()jpegData(compressionQuality:) メソッドが追加され、このエクステンションはあまり必要がなくなりました。

使い方

let image = UIImage()
let pngData = image.toPNGData()

用途

  • Realmへ画像を保存する
    RealmはUIImageを保存できないので、バイナリのData型に変換してから保存します。

Data(PNG, JPEG)→UIImageに変換する

Data+Image.swift
import UIKit

/// Data拡張(イメージ)
public extension Data {
    
    // MARK: Public Methods
    
    /// データ→イメージに変換する
    ///
    /// - Returns: 変換後のイメージ
    public func toImage() -> UIImage {
        guard let image = UIImage(data: self) else {
            print("データをイメージに変換できませんでした。")
            return UIImage()
        }
        
        return image
    }
    
}

使い方

let image = UIImage()
let pngData = image.toPNGData()
let pngImage = pngData.toImage()

用途

  • Realmに保存した画像データをイメージへ戻す

Date→Stringに変換する

Date+String.swift
import Foundation

/// Date拡張(文字列)
public extension Date {
    
    // MARK: Public Methods
    
    /// 日付→文字列に変換する
    ///
    /// - Parameter format: フォーマット
    /// - Returns: 変換後の文字列
    public func toString(format: String) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: format, options: 0,
                                                        locale: Locale(identifier: "ja_JP"))
        return formatter.string(from: self)
    }
    
}

今までの経験上、 DateFormatter を隠蔽すると実装が楽になります。

使い方

let now = Date()
let nowString = now.toString(format: "yMd") // 2018/12/14

用途

  • 日付をラベルなどのUIに表示する

String→Dateに変換する

String+Date.swift
import Foundation

/// String拡張(日付)
public extension String {
    
    // MARK: Public Methods
    
    /// 文字列→日付に変換する
    ///
    /// - Parameter format: フォーマット
    /// - Returns: 変換後の日付
    public func toDate(format: String) -> Date {
        let formatter = DateFormatter()
        formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: format, options: 0,
                                                        locale: Locale(identifier: "ja_JP"))
        guard let date = formatter.date(from: self) else {
            return Date()
        }
        
        return date
    }
    
}

こちらも DateFormatter を隠蔽します。

使い方

"2018-12-14".toDate(format: "yyyy-MM-dd")

用途

  • テキストフィールドに入力した文字列を日付に変換する

Boolの値を反転する

Swift 4.0.2

Bool+Toggle.swift
/// Bool拡張(トグル)
public extension Bool {

    // MARK: Public Methods

    /// 値を反転させる
    public mutating func toggle() {
        self = !self
    }

}

Swift 4.2

標準で実装されたのでエクステンション不要です。

使い方

var isEmpty = true

// before
isEmpty = !isEmpty

// after
isEmpty.toggle()

ちょっとしたエクステンションですが、より関数型っぽく書けるようになります。

用途

  • Boolの値を反転する

文字列をカタカナやひらがなに変換する

String+Transform.swift
import Foundation

/// String拡張(変換)
public extension String {
    
    // MARK: Public Methods
    
    /// ひらがな→カタカナに変換する
    ///
    /// - Returns: 変換後の文字列(変換に失敗した場合は空を返す)
    public func toKatakana() -> String {
        return transform(transform: .hiraganaToKatakana, reverse: false)
    }
    
    /// カタカナ→ひらがなに変換する
    ///
    /// - Returns: 変換後の文字列(変換に失敗した場合は空を返す)
    public func toHiragana() -> String {
        return transform(transform: .hiraganaToKatakana, reverse: true)
    }
    
    // MARK: Private Methods
    
    private func transform(transform: StringTransform, reverse: Bool) -> String {
        guard let string = self.applyingTransform(transform, reverse: reverse) else {
            print("文字列を変換できませんでした。")
            return ""
        }

        return string
    }
    
}

使い方

"あいうえお".toKatakana() // "アイウエオ"
"カキクケコ".toHiragana() // "かきくけこ"

用途

  • ひらがなやカタカナを区別せずに検索する

文字列を半角や全角に変換する

String+Transform.swift
import Foundation

/// String拡張(変換)
public extension String {
    
    // MARK: Public Methods

    /// 全角→半角に変換する
    ///
    /// - Returns: 変換後の文字列(変換に失敗した場合は空を返す)
    public func toHalfwidth() -> String {
        return transform(transform: .fullwidthToHalfwidth, reverse: false)
    }
    
    /// 半角→全角に変換する
    ///
    /// - Returns: 変換後の文字列(変換に失敗した場合は空を返す)
    public func toFullwidth() -> String {
        return transform(transform: .fullwidthToHalfwidth, reverse: true)
    }
    
    // MARK: Private Methods
    
    private func transform(transform: StringTransform, reverse: Bool) -> String {
        guard let string = self.applyingTransform(transform, reverse: reverse) else {
            print("文字列を変換できませんでした。")
            return ""
        }

        return string
    }
    
}

使い方

"ABCDE".toFullwidth() // "ABCDE"
"アイウエオ".toHalfwidth() // "アイウエオ"

用途

  • 半角や全角を区別せずに検索する

おわりに

上記のコードはGitHubに上げています。(Swift 4.2のみ)
https://github.com/uhooi/SwiftExtensions/tree/swift4.2/SwiftExtensions/Extensions

もっといい書き方や他にオススメのエクステンションなどがありましたら、コメントなどで教えていただけると嬉しいです:bow:

他のエクステンション

他にも単体で記事にしているエクステンションがあるので、リンクを貼ります。

69
57
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
69
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?