2016-05-15 18 views
18

Eğerjenerik Swift uzantısına tipinde Geçiş veya ideal olarak bu

class Fancy:UIView 

tüm kardeş Fancy görüşlerini bulmak istiyorum olduğunu varsayalım anlaması. No problem ...

for v:UIView in superview!.subviews 
     { 
     if let f = v as? Fancy 
      { f.hungry = false } 
     } 

Yani, bir uzantısı deneyin Müthiş

public extension UIView 
    { 
    internal func fancySiblings()->([Fancy]) 
     { 
      return (self.superview! 
       .subviews 
       .filter { $0 != self } 
       .flatMap { $0 as? Fancy } 
       ) 
     } 
    } 

, artık

for f:Fancy in self.fancySiblings() 
     { f.hungry = false } 

Fantastik.

Ama

Nasıl herhangi UIView alt tipi ile çalışmak için bu uzantıyı genellemek?

İdeal olarak, uzantısı, türünü bile alabilir mi? Bir tür almanın yanı sıra? Kullanmak türü genel bir uzantısı "anlatmak" nasıl Yani

, gibi bir şey ...

public extension UIView 
    { 
    internal func siblings<T>(something T)->([T]) 
     { 
      return (self.superview! 
       .subviews 
       .filter { $0 != self } 
       .flatMap { $0 as? T } 
       ) 
     } 

ve sonra böyle bir şey diyebiliriz ...

for f in self.siblings(Fancy) 
    for p in self.siblings(Prancy) 
    for b in self.siblings(UIButton) 

, bunun gibi??

O size "Tersten anlaması" olabilir şaşırtıcı ama diğer şekilde çalışmıyor

public extension UIView 
    { 
    internal func incredible<T>()->([T]) 
     { 
     return (self.superview! 
     .subviews 
     .filter { $0 != self } 
     .flatMap { $0 as? T } 
     ) 
     } 


    for f:Fancy in self.incredible() 

    for p:Prancy in self.incredible() 

görünüyor. Hatta ...

self.siblings().forEach{ 
     (f:Fancy) in 
     d.hasRingOn = false 
     } 

Yani ben hala istiyorum yapabilirsiniz

bile ayrıca bunu anlaması, ideal olarak, for f in self.siblings(Fancy) gibi bir tür şeye "geçmek" ve nasıl bilmek.

+0

Benzer soru: http://stackoverflow.com/questions/37216240/generic-function-taking-a-type-name-in-swift (Sorunuzu yanıtlayamadığını düşünüyorsanız, sorun değil - aynı temel sorun). – Hamish

cevap

18

Basitçe .Type kullanın: beklendiği gibi

internal func siblings<T>(something : T.Type)->([T]) { 
    ... 
} 

Ardından for f in self.siblings(Fancy) tam çalışmalıdır.

Tam çalışma örneği:

class Fancy : UIView {} 

public extension UIView { 
    internal func siblings<T>(_ : T.Type)->([T]) { 
     return (self.superview! 
      .subviews 
      .filter { $0 != self } 
      .flatMap { $0 as? T } 
     ) 
    } 
} 

let superView = UIView() 
let view = UIView() 
superView.addSubview(view) 
superView.addSubview(UIView()) 
superView.addSubview(Fancy()) 

print(view.siblings(Fancy)) 

doğru bir Fancy görünümü gösterir!


isteğe açık tip parametresini kullanarak veya derleyici tür kesmesi etkisini almak için istenen ek ele almak.Aynı uzantısında ikinci yöntem oluşturabilir

internal func siblings<T>()->([T]) { 
    return siblings(T) 
} 

bir açık türü parametresi sağlayan Böylece o anlaşılır hale getirmek için gerekecektir ve bakımından ilkini çağıran ikinci işlevi arayacak atlayarak, yöntem tek tek çağırması içten.


Ya da bu kadar swifty şekilde kullanabilirsiniz ve varsayılan nil ile açık tip argüman isteğe bağlı yapabilirsiniz. Yani, dikkat çekici, tür bağımsız değişkeni ihmal durumunda çıkarım zorlar: sağlayacaktır

// power extension, it provides both infered or stated typing 
internal func siblings<T>(_ : T.Type? = nil) -> ([T]) { 
    return (self.superview! 
     .subviews 
     .filter { $0 != self } 
     .flatMap { $0 as? T } 
     ) 
} 

aramaya yöntem ya aracılığıyla

for f in self.siblings(Fancy) 

hatta

for f : Fancy in self.siblings() 

İkisi Sadece bir fonksiyonu tanımlarken çalışacak.

+0

@JoeBlow evet yapabilirsin. Sadece daha fazla kodu değiştirmek istemedim;) – luk2302

+2

@JoeBlow Türü argümanını isteğe bağlı olarak 'nil' ('_: T.Type? = Nil') varsayılan değeriyle yapabilirsiniz. Bu, yöntemle veya yazı yazmadan yöntemi çağırmanıza izin verir. Standart çıkarım normal olarak çalışmalıdır. – Hamish

+0

@Fun fact: Bu sadece benim xcode çöktü ... – luk2302

2
önceden bahsedilen, ama biraz daha akıcı oldu Gerek ve subviews aşacak herhangi geçmesi veya yineleme zorunda kalmadan

Benzer cevap kereden fazla:

extension UIView { 
    internal func siblings<T: UIView>() -> [T] { 
     return superview?.subviews.flatMap {return ($0 == self) ? nil : ($0 as? T) } ?? [] 
    } 
} 

ya da benim tercihi kullanarak opsiyoneller:

internal func siblings<T: UIView>() -> [T]? { 
     return superview?.subviews.flatMap {return ($0 == self) ? nil : $0 as? T } 
} 

Örnek Kullanım:

class ExampleView: UIView { 

    func getMatchingSiblings(){ 
     let foundSiblings: [ExampleView] = siblings() 
    } 

    //or with the for loop in the question: 
    for item: ExampleView in siblings() { 

    } 
} 

jenerik ile ilgili, Yöntemin imzalanmasında jenerik türün bir örneğine ihtiyacınız vardır. Yani ya bir parametreniz varsa veya jenerik kullanan bir dönüş türü varsa, bu türden geçiş yapmanız gerekmez.

+0

çok güzel .......... – Fattie

+0

Ayrıca inanılmaz bilgilendirici. Ben de bu cevap için bir lütuf * tıkladım * - tekrar teşekkürler! – Fattie