Поле класса Swift типа var Array преобразуется в неизменяемый NSArray вместо NSMutableArray
Простой класс Swift имеет поле типа var Array. Когда класс адаптирован к Objective-C, тип поля отображается как NSArray (неизменный), в то время как он должен быть NSMutableArray (изменчивым)
class Categoryy: NSObject {
var items = Array<Item>()
}
Класс Quicky Categoryy адаптирован к Objective-C в сгенерированном Xcode заголовке файла MODULE_NAME-swift.h следующим образом:
SWIFT_CLASS("_TtC8waiterio9Categoryy")
@interface Categoryy : NSObject
@property (nonatomic, copy) NSArray * items;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
Есть ли способ для элементов var: Поле массива, которое должно быть преобразовано в изменяемый NSMutableArray в Objective-c?
Ответы
Ответ 1
Это потому, что свойство items
на самом деле неизменный.
Как вы знаете, из-за характера struct
на основе реализации Array
в Swift, следующий код не влияет на cat.items
.
let cat = Categoryy()
var _items = cat.items
_items.append(item)
Вместо этого вам нужно позвонить так:
cat.items.append(item)
С другой стороны, в Objective-C, [cat.items addObject:item]
точно такая же, как и следующая:
id _items = [cat items];
[_items addObject:item];
Это очень похоже на нерабочий код Swift.
Скажем, Objective-C не имеет эквивалентного свойства/метода, вызывающего семантику как cat.items.append(item)
в Swift.
Это похоже на:
// Objective-C
CGRect frame = view.frame;
view.frame = CGRectMake(frame.origin.x, 50, frame.size.width, frame.size.height)
// Swift
view.frame.origin.y = 50
-
Возможно, Apple может реализовать это как NSMutableArray
(или частный подкласс), конечно, вы можете запросить это.
Я сомневаюсь, что Apple это сделает, потому что это разрывает безопасность типа времени компиляции Generics.
В любом случае, я думаю, вы должны реализовать Categoryy
следующим образом:
class Categoryy: NSObject {
var items:[Item] = []
func addItem(item:Item) {
items.append(item)
}
func setItem(item:Item, atIndex:Int) {
items[atIndex] = item;
}
// and so on ..
}
Ответ 2
Если вы хотите NSMutableArray
, самый простой способ - просто использовать NSMutableArray
в Swift. Array<T>
не может (и не может) одновременно вести себя как (неизменяемый) NSArray
и NSMutableArray
в одно и то же время - прямо сейчас, то, что он ведет, является как неизменным NSArray
. Swift может использовать встроенный тип класса, который соответствует NSMutableArray
тем, что Array<T>
соответствует NSArray
.
Другой альтернативой является использование класса Swift для обтекания NSMutableArray
с @objc
открытых методов для доступа к NSMutableArray
. Это также позволяет использовать generics для ограничения элементов до T
.
Ответ 3
В качестве обходного пути вы можете вызвать append
в файле Swift с помощью метода вместо доступа к массиву Swift непосредственно в Objective-C.
Swift:
func addItem(item:Item)
{
items.append(item)
}
Objective-C:
[yourSwiftObject addItem:item];