Разбор PFSubclassing не работает со Swift

Я скопировал пример Parse Swift для создания подклассов:

class Armor : PFObject, PFSubclassing {

    override class func load() {
        self.registerSubclass()
    }
    class func parseClassName() -> String! {
        return "Armor"
    }
}

Я получаю следующие ошибки:

/Parse/Armor.swift:11:1: error: type 'Armor' does not conform to protocol 'PFSubclassing'
class Armor : PFObject, PFSubclassing {
^
__ObjC.PFSubclassing:15:28: note: protocol requires function 'object()' with type '() -> Self!'
  @objc(object) class func object() -> Self!
                           ^
__ObjC.PFSubclassing:23:52: note: protocol requires function 'objectWithoutDataWithObjectId' with type '(String!) -> Self!'
  @objc(objectWithoutDataWithObjectId:) class func objectWithoutDataWithObjectId(objectId: String!) -> Self!
                                                   ^
__ObjC.PFSubclassing:30:27: note: protocol requires function 'query()' with type '() -> PFQuery!'
  @objc(query) class func query() -> PFQuery!
                          ^
__ObjC.PFSubclassing:35:38: note: protocol requires function 'registerSubclass()' with type '() -> Void'
  @objc(registerSubclass) class func registerSubclass()
                                     ^
/Parse/Armor.swift:14:9: error: 'Armor.Type' does not have a member named 'registerSubclass'
        self.registerSubclass()
        ^    ~~~~~~~~~~~~~~~~

Я видел этот ответ: https://stackoverflow.com/a/24899411/843151 и безуспешно пробовал это решение, Я получаю те же ошибки.

Любые предложения, почему это происходит? Заранее спасибо.


person Michael Wildermuth    schedule 11.08.2014    source источник
comment
Стоит отметить для всех, кто ищет это, что override в начале override class func load() отсутствует в документах Parse.   -  person Andrew Robinson    schedule 28.08.2014


Ответы (5)


Мне нужно было импортировать синтаксический анализ PFObject+Subclass.h в мой соединительный заголовок Objective-C.

#import <Parse/PFObject+Subclass.h>
person Michael Wildermuth    schedule 11.08.2014

С xCode 6.1.1 я смог заставить это работать без заголовка моста. Только что:

import Parse 

в верхней части модуля. Для объявления класса мне нужно было использовать @NSManaged для типов переменных, чтобы заставить их успешно связываться с переменными класса Parse. Как это:

class PSCategory : PFObject, PFSubclassing {
    override class func load() {
        self.registerSubclass()
    }
    class func parseClassName() -> String! {
        return "Category"
    }

    @NSManaged var Name: String
}

Затем в моем запросе все имена динамически связаны:

var query = PSCategory.query() // PFQuery(className: "Category")

query.cachePolicy = kPFCachePolicyCacheElseNetwork // kPFCachePolicyNetworkElseCache
query.maxCacheAge = 60 * 60 * 24  // One day, in seconds.
query.findObjectsInBackgroundWithBlock {
    (categories: [AnyObject]!, error: NSError!) -> Void in
    if error == nil {
        for abstractCategory in categories {
            let category = abstractCategory as PSCategory

            NSLog("Category Name: %@", category.Name)
        }
    } else {
        NSLog("Unable to retrieve categories from local cache or network")
    }
}
person Timothy Tripp    schedule 03.01.2015
comment
У меня аналогичная настройка для вашего кода. единственным исключением являются мои переменные класса: var Name: String? Данные возвращаются с parse.com правильно, но не назначаются при приведении их к PSCategory. Я получаю ноль для NSLog (имя категории: %@, category.Name) - person Nando; 19.02.2015

Parse рекомендует инициализировать() вместо загрузки()

class Armor : PFObject, PFSubclassing {
  override class func initialize() {
    var onceToken : dispatch_once_t = 0;
    dispatch_once(&onceToken) {
      self.registerSubclass()
    }
  }

  static func parseClassName() -> String! {
     return "Armor"
  }
}
person Rahul Katariya    schedule 11.04.2015
comment
Когда я это делаю, я получаю недопустимое повторное объявление parseClassName. Любые идеи, почему это? Я не могу понять написанный протокол PFSubclassing obj-c для переноса на swift: S - person C0D3; 13.01.2016

Похоже, что PFSubclassing в настоящее время работает неправильно в Swift как есть, начиная с версии 1.7.2, выпущенной 27 апреля 2015 года.

Я смог заставить его работать, внедрив пользовательские геттеры и сеттеры для свойств в качестве временного обходного пути, что несколько противоречит цели, но, по крайней мере, этот подход приведет лишь к незначительному рефакторингу после того, как PFSubclassing будет готов для Swift.

Необязательно добавлять #import <Parse/PFObject+Subclass.h> в заголовок моста. Но, как указано в справочнике по протоколу PFSubclassing «Warning: This method must be called before [Parse setApplicationId:clientKey:]», вы должны зарегистрировать все пользовательские подклассы PFObject перед вызовом Parse.setApplicationId(_:, clientKey:).

Вот пример пользовательского подкласса PFObject с именем PFChatLOCMessage:

// In ProjectName-Bridging-Header.h
#import <Parse/Parse.h>

// In AppDelegate.swift
@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    configureParse()
    return true
  }

  func configureParse() {
    registerParseSubclasses()
    Parse.setApplicationId("...", clientKey: "...")
  }

  func registerParseSubclasses() {
    PFChatLOCMessage.registerSubclass()
  }

}

// In PFChatLOCMessage.swift
private let PFChatLOCMessageClassName = "PFChatLOCMessage"
private let userKey = "user"

class PFChatLOCMessage: PFObject {

  var user: PFUser! {
    get { return self[userKey] as! PFUser }
    set { self[userKey] = newValue }
  }

  override init() {
    super.init()
  }

  override init(user: PFUser) {
    super.init()
    self.user = user
  }

}

extension PFChatLOCMessage: PFSubclassing {

  class func parseClassName() -> String {
    return PFChatLOCMessageClassName
  }

}
person Scott Gardner    schedule 01.05.2015
comment
Это все еще единственный способ заставить эту работу работать? У меня проблема со Swift и созданием PFRelations между моими объектами. - person C0D3; 13.01.2016

У меня возникли взаимоблокировки/зависания при использовании override class func initialize, хотя это и рекомендуется в документации по синтаксическому анализу.

Размышляя об этом, не рекомендуется создавать потоки в методах инициализации классов — вы никогда не знаете, когда и в каком контексте они могут быть вызваны.

Это сработало для меня - для всех моих пользовательских подклассов, прежде чем вызывать методы инициализации синтаксического анализа, я явно регистрирую их как подклассы.

Таким образом, порядок, в котором вещи вызываются, хорошо определен. Кроме того, это работает для меня;)

    MyPFObjectSubclass.registerSubclass()
    MyPFObjectSubclass2.registerSubclass()
    MyPFObjectSubclass3.registerSubclass()
    // etc...

    let configuration = ParseClientConfiguration {
        $0.applicationId = "fooBar"
        $0.server = "http://localhost:1337/parse"
    }
    Parse.initializeWithConfiguration(configuration)
person n13    schedule 03.08.2016