Swiftのenumがイイ。
Swift-enumの特徴
Swiftはenum(列挙型)が非常に強力な言語で以下のような特徴を持っています。
- 列挙型自体を値型としてオブジェクトのように扱うことができます。またメソッドの定義ができます。
- 他の多くの言語(Objective-C含む)メンバーに具体的な値を入れる必要がなく、メンバーそのものを値として扱えます。
- 各メンバーに付随した型を入れられます。どのような型でもOK。
- メンバーに具体的な値を入れた場合はObjective-Cの列挙型(NS_ENUM)のように扱えます。
SampleEnum.swift
enum FruitsEnum : FruitsProtocol { // プロトコル準拠
case Orange // メンバー
case GrapeAssociated(String) // メンバーに値を付随させる
func printMember() { // インスタンスメソッド
switch self {
case .Orange: print("Orange")
case .GrapeAssociated: print("GrapeAssociatedMember")
}
}
static func staticPrintEnum() { // staticタイプのメソッド
println("staticEnum")
}
}
こちらの記事のenumの使い方が分かりやすくまとめられており非常に参考になります。
Swift初心者を卒業するためのTips(enum編)
Swiftのプログラミング戦略はこの強力なEnumをいかに使っていけるかが鍵になるのかなと思います。
ただの直感ですが。
実際にログイン画面での実装時に使ってみました。
今回は、ログインの仕方が複数ある場合の実装で試します。
サンプルプログラムの前提はこんな感じ
- 前提としてAPIが用意されておらず、ウェブサイトの該当ページへNSURLSessionを使ってPOSTもしくはGETでログインする
- メアドログインとFacebookログインがある(サンプルではメアドログイン部分のみ)
処理内容
-
enum ConfigurationOfURLSession
- ログイン方法それぞれのメンバーを用意
-
func getNSURLSessionWithConfig
でログイン方法に適したNSURLSessionConfigを返す
-
enum LoginURL:String
- ログイン方法それぞれのメンバーを用意し、各メンバーにURLを設定。
-
func getNSMutableURLRequest
でログイン方法に適したNSURLRequestを返す
-
1, 2で取得したそれぞれのインスタンスでログインする
- ローダーを設定していますが、サンプルでの雰囲気のために書きました。
LoginViewController.swift
import UIKit
class TopViewController: UIViewController, UITextFieldDelegate, NSURLSessionDelegate {
@IBOutlet weak var emailTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
@IBOutlet weak var registrationButton: UIButton!
@IBOutlet weak var loginButton: UIButton!
enum ConfigurationOfURLSession {
case Facebook
case EmailAddress
func getNSURLSessionWithConfig()-> NSURLSession {
let session = NSURLSession.sharedSession()
session.configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicy.Always
session.configuration.HTTPShouldSetCookies = true
session.configuration.HTTPCookieStorage?.cookieAcceptPolicy = NSHTTPCookieAcceptPolicy.Always
session.configuration.requestCachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
if (self == .EmailAddress) {
let cookieStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage()
for obj in cookieStorage.cookies! {
cookieStorage.deleteCookie(obj)
}
}
return session
}
}
enum LoginURL : String {
case Facebook = "https://mydomain.com/facebookConnect/user/"
case EmailAddress = "https://mydomain.com/account/login"
func getNSMutableURLRequest(postData: String?)-> NSMutableURLRequest {
let request = NSMutableURLRequest(URL: NSURL(string: self.rawValue)!)
if (self == .EmailAddress) {
request.HTTPMethod = "POST"
} else {
request.HTTPMethod = "GET"
}
if var _ = postData {
request.HTTPBody = postData!.dataUsingEncoding(NSUTF8StringEncoding)
}
return request
}
}
// MARK: - IBAction
@IBAction func pushedLoginButton(sender: AnyObject) {
SVProgressHUD.showWithStatus("ログイン中")
// NSURLSessionのインスタンスを取得する
let session = ConfigurationOfURLSession.EmailAddress.getNSURLSessionWithConfig()
let postData = "email=" + emailTextField.text!+ "&password=" + passwordTextField.text!
// NSMutableURLRequestのインスタンスを取得する
let request = LoginURL.EmailAddress.getNSMutableURLRequest(postData)
// ログイン処理
let task = session.dataTaskWithRequest(request, completionHandler: {
(data, resp, err) in
let responseData = NSString(data: data!, encoding:NSUTF8StringEncoding)! as String
if var _ = responseData.rangeOfString("Success") {
isSuccess = true
}
})
if (isSuccess) {
SVProgressHUD.showSuccessWithStatus("成功")
} else {
SVProgressHUD.showSuccessWithStatus("失敗")
}
}
}
使ってみた感想。
- シンプルになった。ログイン方式によって微妙なインスタンスのプロパティを変えたい時はenumとメソッドを使っていたところをEnum一つでかけるのは可読性も上がるから良い。
- 設定周りの値を使って処理を書きたい場合に、func/enumと分離できるので可読性はもちろん汎用性も高そう。
少し試した感想ですが、列挙型とロジックの一体感が思ったよりも便利でした。
Objective-Cからありがちな煩雑なプロジェクトの量産という負のループから脱出できる希望の星かと思っています。