Swift: возвращает массив типа self

#ios #arrays #types #swift

#iOS #массивы #типы #swift

Вопрос:

Я хотел бы написать функцию класса, которая вернет массив типа class. Насколько я понял, я могу использовать Self для objective-c instanceType . Моя цель — создать extension для NSManagedObject с fetchObjects помощью метода. Затем этот метод вернет массив NSManagedObject подклассов. Вот пример моего псевдокода, который не компилируется:

 extension NSManagedObject {

    class func fetchObjects(entity: String, context: NSManagedObjectContext, predicate: NSPredicate?, sortDescriptors: NSSortDescriptor[]?) -> Self[] {
        // can't define return type of an array with type Self
        // also var declaration does not work
        var objects : Self[]?

        return objects
    }
}
  

Есть идеи, как я могу определить массив типа Self?

Спасибо за любую помощь!

Комментарии:

1. Вы можете параметризовать функцию следующим образом: class fund fetchObjects<Self>(...) -> Self[]? но я не думаю, что вы можете обобщить переход от ObjC к Swift, чтобы компилятор мог гарантировать, что для каждого NSManagedObject будет соответствующий объект Swift. Хотя это было бы потрясающе, отличный вопрос.

2. Просто для ясности, вы не ищете массив «подклассов», вы ищете массив экземпляров с типами, которые являются подклассом именованного суперкласса?

3. Да, это то, чего я хочу достичь, поэтому, если я вызову его в подклассе NSManagedObject, и он вернет массив экземпляров этого подкласса

4. Но если я объявляю <Self>, разве он не используется как общий, как если бы я написал класс fetchObjects<T>? Или это текущий тип класса?

Ответ №1:

Это суть того, что я использую для аналогичной функции, обратите внимание, что это расширение NSManagedObjectContext , а не NSManagedObject . Что-то подобное, вероятно, можно было бы сделать на NSManagedObject

 protocol NamedManagedObject {

    class func entityName() -> String;

}

extension NSManagedObjectContext {

    func fetchObjects<T:NSManagedObject where T:NamedManagedObject>(entity:T.Type, predicate:NSPredicate? = nil, sortDescriptors:NSSortDescriptor[]? = nil) -> T[]? {
        let request = NSFetchRequest(entityName: entity.entityName())

        request.predicate = predicate
        request.sortDescriptors = sortDescriptors

        var error:NSError? = nil
        let results = self.executeFetchRequest(request, error: amp;error) as? T[]

        assert(error == nil)

        return results
    }

}

extension MyObjectClass : NamedManagedObject {
    class func entityName() -> String {
        return "MyObjectClass"
    }
}
  

Затем использовать его так же просто, как:

 let objects = managedObjectContext.fetchObjects(MyObjectClass)
  

Обратите внимание, что вы также можете реализовать NamedManagedObject для всех NSManagedObjects с:

 extension NSManagedObject : NamedManagedObject {
    class func entityName() -> String {
        return NSStringFromClass(self)
    }
}
  

Если вы также убедитесь, что всем вашим классам явно присвоены имена, понятные для Objective-C.:

 @objc(MyManagedObject)
class MyManagedObject : NSManagedObject { ... }
  

Комментарии:

1. Отлично! «.Type» — это то, что я тоже искал. На самом деле хотел сделать то же самое, что и вы в первую очередь 😉