Edited at

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


はじめに

私が使っている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から変更できるようになります。

エクステンションでは @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: