2015-02-10 3 views
0

У меня проблема в swift, где я хочу проверить соответствие протокола в классе func, а затем использовать некоторое статическое свойство, когда проверка завершится успешно. Вот код площад:Swift cast self in class func

import UIKit 

@objc protocol SearchableObject { 
    static var sortDescriptors: [NSSortDescriptor] { get } 
} 

class Test: NSObject { 

} 

extension Test { 
    class func loadData() { 
     if self is SearchableObject { 
      println(valueForKey("sortDescriptors")) 
     } 
     else { 
      println("not searchable") 
     } 
    } 
} 

class SearchableTest: Test, SearchableObject { 
    class var sortDescriptors: [NSSortDescriptor] { 
     return [NSSortDescriptor(key: "property", ascending: true)] 
    } 
} 

Test.loadData() // prints "not searchable" 
SearchableTest.loadData() // prints "Optional((\n "(property, ascending, compare:)"\n))" 

проблема я могу проверить для протокола соответствия, но я не могу бросить себя, поэтому я использую valueForKey().

(self as SearchableObject).sortDescriptors 
    ^'SearchableObject' does not have a member named 'sortDescriptors' 

ставит себя на экземпляр соответствующего SearchableObject сделать статический вар недоступным. Поскольку мне не нравится подход valueForKey(), я хочу спросить, есть ли лучший способ достичь этого?

Заранее спасибо :)

ответ

3

В методах класса, self является классом, не экземпляр. Таким образом, право - но не рабочий - путь:

class func loadData() { 
    if let cls = self as? SearchableObject.Type { 
    //         ^^^^^ 
     println(cls.sortDescriptors) 
     // ^[!] error: accessing members of protocol type value 'SearchableObject.Type' is unimplemented 
    } 

Как вы можете видеть, это никогда не реализовано :(

Не беспокойтесь, есть обходной Пока протокол объявлен. @objc, AnyClass имеет свойства, что можно заливать self к AnyClass, а затем вызвать .sortDescriptors:.

class func loadData() { 
    if self is SearchableObject.Type { 
     println((self as AnyClass).sortDescriptors) 
    } 

по существу, это временное решение т он такой же, как valueForKey, но он не использует строки как минимум.

+1

хорошо прохладно. все еще немного плохо выглядящий, но не нужно использовать кавычки и избавиться от кастинга (когда я использую request.sortDescriptors = valueForKey («sortDescriptors») vs. (self as AnyClass). sortDescriptors) как определенный плюс для этого ответа :) спасибо – warly

+0

не может быть помечен \ @objc, потому что тип параметра 1 не может быть представлен в объективе-C. метод не может быть помечен \ @objc, потому что тип параметра 2 не может быть представлен в объективе-C. метод не может быть помечен \ @objc, поскольку тип параметра 4 не может быть представлен в объективе-C. Свифт знает, как тролль .. – bubakazouba

2

self as SearchableObject возвращает SearchableObject экземпляр. Но вы хотите класс. Это SearchableObject.Type.

Так вы имели в виду это:

extension Test { 
    class func loadData() { 
     if let s = self as? SearchableObject.Type { // <<=== 
      println(s.sortDescriptors) 
     } 
     else { 
      println("not searchable") 
     } 
    } 
} 

Но "доступ к членам значения типа протокола ... является невыполненным" Поэтому компилятор знает об этом и, в частности, не может его обрабатывать в настоящее время. Конечно, все это хорошо, если вы используете экземпляры:

import Foundation 

protocol SearchableObject { 
    var sortDescriptors: [NSSortDescriptor] { get } 
} 

class Test {} 

extension Test { 
    func loadData() { 
     if let s = self as? SearchableObject { 
      println(s.sortDescriptors) 
     } 
     else { 
      println("not searchable") 
     } 
    } 
} 

class SearchableTest: Test, SearchableObject { 
    static var sharedSortDescriptors = [NSSortDescriptor(key: "property", ascending: true)] 
    var sortDescriptors: [NSSortDescriptor] { return self.dynamicType.sharedSortDescriptors } 
} 


Test().loadData() // prints "not searchable" 
SearchableTest().loadData()