顯示具有 swift 標籤的文章。 顯示所有文章
顯示具有 swift 標籤的文章。 顯示所有文章

2015年12月17日 星期四

一個關於遵循多個Swift 2.0 protocol extension的問題

問題

最近練習用Protocol-Oriented Programming實做可移動以及縮放的View,遇到一個很有趣的問題,假設有以下兩個protocol

protocol Draggable: class {
    var view: UIView { get }
    var initialLocation: CGPoint { get set }
}

extension Draggable where Self: UIView {
    var view: UIView { get { return self } }
    var parentView: UIView? { get { return self.view.superview } }
}
protocol Scalable: class {
    var view: UIView { get }
}

extension Scalable where Self: UIView {
    var view: UIView { get { return self } }
    var parentView: UIView? { get { return self.view.superview } }
}

然後實做一個View遵循這兩個protocol

public class VWView: UIView, Draggable, Scalable {
    var initialLocation: CGPoint = CGPointZero
}

這時候會發生compile error,告訴你
Type 'VWView' does not conform to protocol 'Scalable'
Type 'VWView' does not conform to protocol 'Draggable'

怎麼一回事呢?

原來是因為兩個protocol都有var view: UIView { get { return self } }的default implementations,編譯器不曉得該用哪一個,乾脆來一個編譯錯誤。

解法

其實解決方法很簡單,就是在class裡實做這個值,這樣編譯器就知道該用class裡面的這個了。

public class VWView: UIView, Draggable, Scalable {
    var view: UIView { get { return self } }
    var initialLocation: CGPoint = CGPointZero
}

Reference:
http://stackoverflow.com/questions/31586864/swift-2-0-protocol-extensions-two-protocols-with-the-same-function-signature-c

2015年12月4日 星期五

Swiftlint - 維護coding style的好工具

https://github.com/realm/SwiftLint

在多人協作開發專案時,遵守團隊訂出的coding style是一個好習慣,可以讓其他協作者更容易看懂我們產出的程式碼。Realm釋出的這個tool就可以幫助我們將專案中不符合coding style的地方用warning甚至是error標出,利用Xcode幫我們自動把關,節省其他協作者幫我們檢查coding style的時間。目前Swiftlint是遵照GitHub’s Swift Style Guide 做檢查。

安裝

brew install swiftlint

設定

lint

在target的run script加入

if which swiftlint >/dev/null; then
  swiftlint
else
  echo "SwiftLint does not exist, download from https://github.com/realm/SwiftLint"
fi

然後在Xcode裡Build專案,哇,怎麼連Pod裡面的code都檢查了呢?

在專案root path新建一個 .swiftlint.yml 檔案,輸入

included:
  - YourProjectSourceDirectiryName

把YourProjectSourceDirectiryName替換成你的專案原始碼資料夾名稱就可以只檢查自己專案的coding style囉。

2015年11月26日 星期四

Swift Optionals

在swift中使用Optional來處理值缺失的狀況,如果看見一個variable是Optional類型,只有兩種可能,要嘛有值,要嘛就是nil。

宣告方式

var coffee:String?

等於下面這種宣告方式

var coffee: Optional<String>

由此可知 ? 其實是syntactic sugar。

看看Optional的原始宣告

public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
    case None
    case Some(Wrapped)
    /// Construct a `nil` instance.
    public init()
    /// Construct a non-`nil` instance that stores `some`.
    public init(_ some: Wrapped)
    /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
    @warn_unused_result
    public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
    /// Returns `nil` if `self` is nil, `f(self!)` otherwise.
    @warn_unused_result
    public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
    /// Create an instance initialized with `nil`.
    public init(nilLiteral: ())
}

如果沒有賦值的話,Optional的預設值是nil。在Objective-C中,nil是一個0指標,在swift中nil是一個確定的值,任何Optioanl都可以設為nil。關於瞭解空值,可以參考悟空。

其他關於Optional chaining以及一些更深度的剖析,可以參考喵神的文章或是玉令天下的Blog。

另外有一種情況是如果Optional呼叫的function需要傳入Optional本身,像

class ViewController: UIViewController {

    let finishedMessage = "Network call has finished"
    let messageLabel = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()

        someNetworkCall { [weak self] in
            self?.finished(self?.finishedMessage)
        }
    }

    func finished(message: String) {
        messageLabel.text = message
    }
}

這一段是編譯不過的,因為self?.finishedMessage是Optional chaining,而Optional chaining回傳的一定是Optional值。那麼應該怎麼解呢?

可以直接使用!,因為當self?為nil時不會繼續呼叫function,所以一旦呼叫了function就代表有值。

someNetworkCall { [weak self] in
            self?.finished(self!.finishedMessage)
}

詳情可以參考http://blog.xebia.com/swift-optional-chaining-and-method-argument-evaluation/ 。

2014年11月10日 星期一

Xcode 6.1拿掉class prefix

http://scottberrevoets.com/2014/07/25/objective-c-prefixes-a-thing-of-the-past/

從Xcode 6.1之後Apple拿掉了class prefix的選項,目前只有framework需要class prefix,剩下的app code以及新的swift都不需要。

2014年11月8日 星期六

iOS app development tools

Third-Party Library Management

CocoaPods

Crash Report

Crashlytics

Test framework

objective-c: Specta+Expecta、kiwi
swift: Quick

UI Test

FBSnapShots

Version Control

Gilt

Issue tracking

Redmine、Jira、Taiga

Continuous Integration

Jenkins via virtualbox
http://blog.hsatac.net/2014/06/install-osx-mavericks-on-virtualbox/

Server Deployment

Docker

Xcode Plugin Management

Alcatraz

Debug

Faux Pas 、Deploymate