2017-07-14 51 views
1

函數參數類型,我想通過擴展編寫一個函數,讓我們UIView說。該函數應具有與獲取所調用函數的對象相同類型的參數,例如,可以在塊實施,當然其實際類型的可以使用UIButtonUIImageView使用自給作爲擴展

一如往常,代碼可以解釋最好:

extension UIView { 
    func performOnMe<T>(_ block: (_ obj: T) -> Void) -> T { 
     block(self) 
     return self 
    } 
} 

let button = UIButton(frame: CGRect.zero) 
button.performOnMe { $0.alpha = 1 } 
     .performOnMe { $0.setTitle("Title", for: .normal) } 
     .performOnMe { $0.backgroundColor = UIColor.red } 

let image = UIImageView(frame: CGRect.zero) 
image.performOnMe { $0.alpha = 1 } 
    .performOnMe { $0.image = nil } 

當然,這片斷不編譯,因爲斯威夫特不能推斷T的類型,那就是challange中。我將如何解決這個問題?它有可能嗎?

+0

你大概意思'的UIImageView '在第二個例子... –

+0

你說得對,對不起,拼寫錯誤,在StackOverflow的編輯器。 – Funkybit

回答

2

的「絕招」是在擴展定義了默認實現 的協議,和使UIView符合該協議:

protocol PerformOnMe { } 

extension PerformOnMe { 
    @discardableResult func performOnMe(_ block: (Self) -> Void) -> Self { 
     block(self) 
     return self 
    } 
} 

extension UIView: PerformOnMe {} 

@discardableResult屬性被添加以避免 「表達的結果是未使用」調用鏈中的警告:

let button = UIButton(frame: CGRect.zero) 
button.performOnMe { $0.alpha = 1 } 
    .performOnMe { $0.setTitle("Title", for: .normal) } 
    .performOnMe { $0.backgroundColor = UIColor.red } 

let imageView = UIImageView() 
image.performOnMe { $0.alpha = 1 } 
    .performOnMe { $0.image = nil } 
+0

非常感謝!這幾乎是我所期待的。我只是認爲擴展+泛型就足夠了。 – Funkybit

1

如果我理解正確你想擴展的UIView的一個特定的子類?

在這種情況下,我建議你定義一個協議,並把它擴展你希望的類,像這樣:

protocol Perform {} 

// This extension is only available to UIViews (you can replace with Any or AnyObject to have it available on everything or all objects) 
extension Perform where Self: UIView { 

    func performOnMe(_ block: (Self) -> Void) -> Self { 
     block(self) 
     return self 
    } 

} 

// Apply protocol to all UIViews 
extension UIView: Perform {} 

// Usage 
UIView().performOnMe { (view) in 
    // Do something 
} 
1

稍微不同的方法,將與任何對象合作,不僅UIViews

infix operator <~: AdditionPrecedence 

@discardableResult public func <~ <T>(obj: T, block: (T) ->()) -> T { 
    block(obj) 
    return obj 
} 

let button = UIButton(frame: CGRect.zero) 
    <~ { $0.alpha = 1 } 
    <~ { $0.setTitle("Title", for: .normal) } 
    <~ { $0.backgroundColor = UIColor.red } 
+0

哇,感謝您的建議。一個完全不同的方式來解決這個問題我從未想過這件事。 – Funkybit

1

可以使用運營商實現這一目標的所有類:

infix operator <-< : AdditionPrecedence 
func <-<<T>(left:T, right:(T)->()) -> T 
{ 
    right(left) 
    return left 
} 

let button = UIButton(frame: CGRect.zero) 
      <-< { $0.alpha = 0.3 } 
      <-< { $0.setTitle("Title", for: .normal) } 
      <-< { $0.backgroundColor = UIColor.blue } 

or 

let button = UIButton(frame: CGRect.zero) <-< { 
       $0.alpha = 0.3  
       $0.setTitle("Title", for: .normal) 
       $0.backgroundColor = UIColor.blue 
      }