你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> Swift 開發 Uther 小記

Swift 開發 Uther 小記

編輯:IOS開發基礎

blob.png

作者:@請叫我汪二 授權本站轉載。

前陣子做了一個簡單地蠢萌機器人 Uther ,主要實現以下功能:

  • 收到消息後解析情感並返回對應情感的顏文字

  • 使用動畫切換顏文字

  • 顯示並可編輯歷史消息

花了一周時間做了 1.0 然後上線,現在 1.2 版本剛剛審核通過。簡單分享一下 Uther 從誕生到上線的過程。

代碼開源在 Github: Uther。比較粗糙,沒有仔細整理,各位見笑啦。

AppStore 下載地址: Uther。

Project

對於一個全新的 iOS 的項目,我的流程主要分為以下幾步。

Xcode

這就不啰嗦了,直接創建一個 Swift 項目即可。不過我一般不會勾選 Xcode 自帶的 git 選項,而會在後面手動配置。

Git

通過 git init 初始化倉庫,然後在 gitignore.io 找上對應的配置,填入 .gitignore 文件。至此, git 初始化完畢。可以提交一次 commit 保存。注意,個人習慣把 Pods 文件夾目錄也放到 .gitignore 中,如果使用自動生成的配置文件,取消那一行注釋即可。

Cococapods

創建 Podfile 文件,然後通過 def 按照模塊定義,然後再配置各個 target :

platform :ios, '8.0'
use_frameworks!
def import_networking
    pod 'Alamofire'
    pod 'Moya'
end
target '__placeholder__' do
    import_networking
end

Font

字體我以前一直用的是 Consolas ,後來在微博看到了湯哥的推薦從此成了 Monoid 的忠實粉絲。

Develop

Folder

開發過程中,我的文件夾目錄一般如下:

General
    |- Macro
    |- Models
    |- Tools
        |- LOG.swift
        |- GCD.swift
    |- Models
Sections
    |- Main
        |- Preview
        |- Setting
    |- User
Resources

Tool

接下來聊一聊項目中的通用工具類。

GCD

項目中使用 GCD 這個庫,封裝了一些常見操作。然後定義了一個簡單的 struct 封裝一下常用的兩個方法:

struct GCD {
    static func async_in_worker(closure: GCDClosure) {
        gcd.async(.Default, closure: closure)
    }
    static func async_in_main(closure: GCDClosure) {
        gcd.async(.Main, closure: closure)
    }
}

LOG

項目中使用 XCGLogger 作為 Log 工具,配置起來十分方便,聲明一個全局常量即可:

let log: XCGLogger = {
    let log = XCGLogger.defaultInstance()
    let logPath : NSURL = cacheDirectory.URLByAppendingPathComponent("XCGLogger.Log")
    log.setup(logLevel: .Debug, showThreadName: true, showLogLevel: true, showFileNames: true, showLineNumbers: false, writeToFile: logPath, fileLogLevel: .Info)
    log.xcodeColorsEnabled = true
    log.xcodeColors = [
        .Verbose: .lightGrey,
        .Debug: .darkGrey,
        .Info: .darkGreen,
        .Warning: .orange,
        .Error: .red,
        .Severe: .whiteOnRed
    ]
    return log
}()

DB

數據庫方面,我使用的是 SQLite.swift 。可以用泛型方便的拼接各種 SQL 語句:

typealias Pid = Int64
struct DB {
    private static let db = SQLite.Database(documentsDirectory.URLByAppendingPathComponent("uther.db").absoluteString!)
    struct MessageDB {
        static let table = db["message"]
        // 唯一索引,主鍵
        static let pid = Expression("pid")
        // 消息創建的時間
        static let createdTime = Expression("created_time")
        // 消息的內容
        static let content = Expression("content")
    }
    static func setupDatabase() {
        db.create(table: MessageDB.table, ifNotExists: true) { t in
            t.column(MessageDB.pid, primaryKey: true)
            t.column(MessageDB.createdTime)
            t.column(MessageDB.content)
        }
    }
}

Flurry

使用 Flurry 做一些簡單的統計,通過 extension 添加了一些代碼。

比如一個全局配置的靜態方法:

extension Flurry {
    static func start() {
        Flurry.setUserID(Keychain.userId);
        Flurry.startSession("YOUR_SESSION_ID");
    }
}

比如通過 enum 打一些 error log :

// ERROR
extension Flurry {
    enum Error: String {
        case Setup   = "SetupError"
        case Wenzhi  = "WenzhiError"
        func logError(message: String) {
            let error = NSError(domain: "com.callmewhy.uther", code: 1001, userInfo: ["Message": message])
            Flurry.logError(self.rawValue, message: message, error: error)
            log.error(message)
        }
    }
}

比如內嵌個 struct 來統計 Message 相關的行為數據:

// MESSAGE
extension Flurry {
    struct Message {
        private static let send     = "Send Message"
        private static let receive  = "Receive Positive"
        static func sendMessage(l: Int) {
            Flurry.logEvent(send, withParameters: ["MessageLength": l])
        }
        static func receivePositive(p: Double) {
            Flurry.logEvent(receive, withParameters: ["MessagePositive": p])
        }
    }
}

Localization

我們可以通過 extension 給 string 加上 Localization 的屬性,返回本地化之後的字符串:

extension String {
    var localized: String {
        let s = NSLocalizedString(self, tableName: nil, bundle: NSBundle.mainBundle(), value: "", comment: "")
        return s
    }
}

使用的時候直接調用 "LOCALIZATION_KEY".localized 即可。

Network

網絡方面使用 Moya 作為業務和 Alamofire 的中間層。以前是自己做了個 WhyEngine 封裝了 Task 和 Request ,後來有了 Moya 就簡單多了:

// MARK: - MoyaProvider
let endpointResolver = { (endpoint: Endpoint) -> (NSURLRequest) in
    let request: NSMutableURLRequest = endpoint.urlRequest.mutableCopy() as! NSMutableURLRequest
    request.timeoutInterval = 2.0
    return request
}
let SentimentProvider = MoyaProvider(endpointResolver: endpointResolver)
// TODO: extension MoyaTarget to handle respose
extension MoyaProvider {
    typealias positiveHandler = PositiveValue? -> Void
    func requestPositive(endpoint: T, completion: positiveHandler) -> Cancellable {
        ...
    }
}
// MARK: - MoyaTarget
extension Sentiment: MoyaTarget {
    public var baseURL: NSURL {
        return NSURL(string: "https://wenzhi.api.qcloud.com")!
    }
    public var path: String {
        return "api/sentiment/"
    }
}

後面等上了 Swift2.0 可以擴展協議,就可以直接用 MoyaTarget 直接處理 Response 了。想直接把返回結果封裝成 JSON 也很簡單:

extension MoyaProvider {
    func requestJSON(endpoint: T, completion: (JSON?) -> Void) -> Cancellable {
        return self.request(endpoint) { (data, status, response, error) in
            if let d = data {
                let json = JSON(data: d)
                log.debug("\(json)")
                completion(json)
            } else {
                log.error("\(error)")
                completion(nil)
            }
        }
    }
}

小結

前面做過幾個 Swift 項目,不過都是練練手的 Demo 級別。 Uther 算是第一個完全的 Swift 項目,沒有任何 objc 的代碼。這感覺真是爽,干淨利落。

Swift 的最佳實踐還在探索中,Uther 項目有很多可以繼續改進的地方。接下來的項目准備融入一些函數式編程的元素,進一步感受各種有趣的編程范型。

歡迎討論,多多指教~

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved