便利一言メモ Swift 


#Dictionary union（連合）

~~~Swift
import Foundation

extension Dictionary {
    func union(other: Dictionary?) -> Dictionary {
        guard let otherDic = other else { return self }
        var tmp = self
        otherDic.forEach { tmp[$0.0] = $0.1 }
        return tmp
    }
}
~~~

#String isAllHalfWidthCharacter（半角・全角の判定）

~~~Swift
import Foundation

extension String {
    var isAllHalfWidthCharacter: Bool {
        // 半角も全角も1文字でカウント
        let nsStringlen = self.count
        let utf8 = (self as NSString).utf8String
        // Cのstrlenは全角を2で判定する
        let cStringlen = Int(bitPattern: strlen(utf8))
        if nsStringlen == cStringlen {
            return true
        }
        
        return false
    }
~~~
その他にも　参考 https://qiita.com/yusuga/items/f182fa7a60c3f8c774ea


#String deleteLastSpace（末尾の空白を除去する）

~~~Swift
    func deleteLastSpace() -> String {
        if self == "" {
            return ""
        }
        var text = self
        var lastCharcter = text.substring(from: text.index(before: text.endIndex))
        while (lastCharcter == " " || lastCharcter == "　"){
            text = text.substring(to: text.index(before: text.endIndex))
            if text == "" {
                break
            }
            lastCharcter = text.substring(from: text.index(before: text.endIndex))
        }
        return text
    }
}
~~~

#UIColor 共通化へ

~~~Swift

import UIKit
import Foundation

extension UIColor {
    class func loginViewBgColor() -> UIColor {
        return UIColor.rgb(r: 247, g: 181, b: 0, alpha: 1.0)
    }

    class func loginButtonColor() -> UIColor {
        return UIColor.rgb(r: 247, g: 181, b: 0, alpha: 1.0)
    }
    
    class func loginBackWhiteViewShadowColor() -> UIColor {
        return UIColor.rgb(r: 26, g: 20, b: 6, alpha: 0.08)
    }
    
    class func loginTextFieldColor() -> UIColor {
        return UIColor.rgb(r: 248, g: 246, b: 243, alpha: 1.0)
    }
    
    class func loginTextFieldBorderColor() -> UIColor {
        return UIColor.rgb(r: 234, g: 231, b: 226, alpha: 1.0)
    }
    
    class func commentViewBgColor() -> UIColor {
        return UIColor.rgb(r: 241, g: 238, b: 234, alpha: 1.0)
    }

    class func submitButtonColor() -> UIColor {
        return UIColor.rgb(r: 247, g: 181, b: 0, alpha: 1.0)
    }
    
    class func validationViewBorderColor() -> UIColor {
        return UIColor.rgb(r: 238, g: 20, b: 47, alpha: 1.0)
    }
    
    class func normalButtonGradationTopColor() -> UIColor {
        return UIColor.rgb(r: 248, g: 185, b: 0, alpha: 1.0)
    }
    
    class func normalButtonGradationBottomColor() -> UIColor {
        return UIColor.rgb(r: 238, g: 170, b: 0, alpha: 1.0)
    }
    
    class func reLoadButtonGradationTopColor() -> UIColor {
        return UIColor.rgb(r: 126, g: 125, b: 124, alpha: 1.0)
    }
    
    class func reLoadButtonGradationBottomColor() -> UIColor {
        return UIColor.rgb(r: 117, g: 116, b: 114, alpha: 1.0)
    }
    
    class func customButtonTextShadowColor() -> UIColor {
        return UIColor.rgb(r: 26, g: 26, b: 26, alpha: 0.08)
    }
    
    class func customButtonShadowColor() -> UIColor {
        return UIColor.rgb(r: 26, g: 26, b: 26, alpha: 0.16)
    }

    class func registerTableBorderColor() -> UIColor {
        return UIColor.rgb(r: 229, g: 225, b: 219, alpha: 1.0)
    }
    
    class func areaLightGrayFontColor() -> UIColor {
        return UIColor.rgb(r: 208, g: 205, b: 200, alpha: 1.0)
    }

    class func areaBlackFontColor() -> UIColor {
        return UIColor.rgb(r: 26, g: 20, b: 6, alpha: 1.0)
    }
    
    class func backButtonColor() -> UIColor {
        return UIColor.rgb(r: 161, g: 159, b: 156, alpha: 1.0)
    }

    class func blackFontColor() -> UIColor {
        return UIColor.rgb(r: 50, g: 48, b: 42, alpha: 1.0)
    }   
}
~~~

#UIColor １６進数指定のカラー
~~~Swift
    class func rgbColor(rgbValue: UInt) -> UIColor {
        return UIColor(
            red:   CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
            green: CGFloat((rgbValue & 0x00FF00) >>  8) / 255.0,
            blue:  CGFloat( rgbValue & 0x0000FF)        / 255.0,
            alpha: CGFloat(1.0)
        )
    }
~~~

#UIViewController getTopViewController（トップで表示しているビューコントローラー取得）
~~~Swift
import Foundation
import UIKit

extension UIViewController {
    class func getTopViewController() -> UIViewController? {
        var topController = UIApplication.shared.keyWindow?.rootViewController
        
        if var tc = topController {
            while tc.presentedViewController != nil {
                if let present = tc.presentedViewController {
                    tc = present
                }
            }
            topController = tc
        }
        return topController
    }
}
~~~

#UIApplication topViewController（トップで表示しているビューコントローラー取得）
~~~Swift
import Foundation
import UIKit

extension UIApplication {
    class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }
        return controller
    }
}
~~~

#UIImage resize（リサイズ）
~~~Swift
import UIKit

extension UIImage {
    
    func resize(size: CGSize) -> UIImage {
        let widthRatio = size.width / self.size.width
        let heightRatio = size.height / self.size.height
        let ratio = (widthRatio < heightRatio) ? widthRatio : heightRatio
        let resizedSize = CGSize(width: (self.size.width * ratio), height: (self.size.height * ratio))
        UIGraphicsBeginImageContext(resizedSize)
        draw(in: CGRect(x: 0, y: 0, width: resizedSize.width, height: resizedSize.height))
        let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return resizedImage!
    }
    
}
~~~

#UIView top,bottom,right,left（リサイズ）
~~~Swift
import UIKit

extension UIView {
    var top : CGFloat{
        get{
            return self.frame.origin.y
        }
        set{
            var frame       = self.frame
            frame.origin.y  = newValue
            self.frame      = frame
        }
    }
    var bottom : CGFloat{
        get{
            return frame.origin.y + frame.size.height
        }
        set{
            var frame       = self.frame
            frame.origin.y  = newValue - self.frame.size.height
            self.frame      = frame
        }
    }
    var right : CGFloat{
        get{
            return self.frame.origin.x + self.frame.size.width
        }
        set{
            var frame       = self.frame
            frame.origin.x  = newValue - self.frame.size.width
            self.frame      = frame
        }
    }
    var left : CGFloat{
        get{
            return self.frame.origin.x
        }
        set{
            var frame       = self.frame
            frame.origin.x  = newValue
            self.frame      = frame
        }
    }
}

~~~

##BaseTextField カスタムテキスト

~~~Swift
import UIKit

class BaseTextField: UITextField, UITextFieldDelegate {
    var parentScrollView:UIScrollView?                 = nil
    var parentScrollViewDelegate:UIScrollViewDelegate? = nil
    var doEditExec:(()->Void)                          = {_ in }
    
    func setup(parentScrollView:UIScrollView, parentScrollViewDelegate:UIScrollViewDelegate, didEditExec:@escaping ()->Void = {_ in }) {
        self.delegate = self
        self.parentScrollView = parentScrollView
        self.parentScrollViewDelegate = parentScrollViewDelegate
        self.doEditExec = didEditExec
    }
    
    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        Util.enableScrollview(viewDelegate:self.parentScrollViewDelegate!, scrollview: self.parentScrollView!)
        self.parentScrollView?.contentOffset = CGPoint(x: 0, y: 0)
        return true
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool{
        textField.resignFirstResponder()
        self.parentScrollView?.contentSize = CGSize(width: AppConfig.screenWidth, height: 0)
        doEditExec()
        return true
    }
}

@IBDesignable class CustomTextField: BaseTextField {
    
}
~~~
今更ながらIBDesignableとIBInspectableについて
https://qiita.com/stastaahaha/items/e45e7559255fb7666fd8

##PickerTextField カスタムピッカーテキストフィールド

~~~Swift
import UIKit

class PickerTextField: UITextField, UIPickerViewDelegate, UIPickerViewDataSource {
    var dataList = [String]()
    var isInit = false
    private let leftViewWidth: CGFloat = 15
    
    override func layoutSubviews() {
        super.layoutSubviews()
        commonInit()
    }
    
    func setup(dataList: [String]) {
        self.dataList = dataList
        
        let picker = UIPickerView()
        picker.delegate = self
        picker.dataSource = self
        picker.showsSelectionIndicator = true
        
        let toolbar = UIToolbar(frame: CGRect(x:0, y:0, width:0, height:40))
        let spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: target, action: nil)
        let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(PickerTextField.done))
        toolbar.setItems([spacer, doneItem], animated: true)
        self.text = dataList[0]
        
        self.inputView = picker
        self.inputAccessoryView = toolbar
    }
    
    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return dataList.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return dataList[row]
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        self.text = dataList[row]
    }
    
    func cancel() {
        self.text = ""
        self.endEditing(true)
    }
    
    func done() {
        self.endEditing(true)
    }
    
    func commonInit() {
        
        if isInit { return }
        
        let leftView = UIView(frame: CGRect(x: 0, y: 0, width: leftViewWidth, height: self.frame.size.height))
        self.leftView = leftView
        self.leftViewMode = UITextFieldViewMode.always
        
        isInit = true
    }
}
~~~

#Protocols Response / Parameters

~~~Swift
import Foundation

protocol Response {
    var data: AnyObject { get }
    
    init(data: AnyObject?) throws
}
~~~

~~~Swift
import Foundation

protocol Parameters {
    init(values: [String:AnyObject])
    func toDictionary() -> [String:AnyObject]
}

protocol Parameter {
    init(value: AnyObject)
    func toAny() -> AnyObject
}
~~~

#Responses Responses

~~~Swift
import Foundation

class BaseResponse: Response {
    // レスポンスデータ保持用
    var data: AnyObject
    
    /**
     コンストラクタ     - parameter data: レスポンスデータ
     */
    required init(data: AnyObject?) throws {
        self.data = data!
    }
}
~~~

#Requests Requests

~~~Swift
import Foundation

class BaseRequest: Parameters {
    
    required init(values: [String : AnyObject]) {
    }
    
    func toDictionary() -> [String:AnyObject] {
        return [:]
    }
}
~~~

---


## 関連記事

【About】(http://qiita.com/sunstripe) - サンストライプ

---

## 制作チーム：サンストライプ

[![sunstripe_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/322f2d60-f19d-af9e-2b6f-7290ca546848.png)](http://sunstripe.main.jp/)
http://sunstripe.main.jp/

(月１WEBコンテンツをリリースして便利な世の中を作っていくぞ！！ボランティアプログラマー/デザイナー/イラストレーター/その他クリエイター声優募集中！!)

### 地域情報 THEメディア
THE メディア 地域活性化をテーマに様々なリリース情報も含め、記事をお届けしてます！！
https://the.themedia.jp/

### ゼロからはじめる演劇ワークショップ
多様化の時代に向けて他者理解を鍛える

https://workshop.themedia.jp/

### プログラミングワークショップ・ウェブ塾の開講！！！
様々なテーマでプログラミングに囚われずに取り組んでいきます。
詳しくはこちら　↓　↓　↓　↓　↓　↓　↓　↓
[プログラミングサロン 月１だけのプログラミング学習塾](https://workshop.themedia.jp/posts/7057553?fbclid=IwAR32CfRQ7RvDOhvuogoSwqxDLMOU7Jvuzljlnx-TMc27qBPX1BnWsfLcBR8
)

### 協力応援 / 支援者の集い
## チーム：サンストライプ
#### プログラミングラボ
https://twitter.com/sunstripe2011

一緒にポートフォリオを作りませんか？現場の体験やそれぞれの立場から年齢関係なく作品を作りたい方々と一緒にチームを作って、作品を作っています。現場に行きたい人には、職場紹介や職場の体験や悩み相談なども受けております。
様々な職種からプログラミングの知識を得たい、デザインの知識を得たい、データーベースの知識を得たいという人が集まっております。
週１のミーティングにそれぞれの近況と作業報告して、たまにリモート飲み会などをしております！！

興味がある方は、DMに話しかけてみてください。

## トラストヒューマン
http://trusthuman.co.jp/
私たちは何よりも信頼､人と考えてます｡

｢コンサルティング｣と｢クリエイティブ｣の両角度から｢人材戦略パートナー｣としてトータル的にサポートします！！

キャリア教育事業
広域学習支援プラットフォーム『のびのび日和』
https://slc-lab.amebaownd.com/

#スポンサー募集