2014-09-19 18 views
11

Prosta klasa Swift ma pole typu var Array. Gdy grupa jest przystosowana do celu C typ pola jest narażony NSArray (niezmiennej), podczas gdy powinna być NSMutableArray (zmienny)Pole klasy Swift typu var Array jest konwertowane na niezmienny NSArray zamiast NSMutableArray

class Categoryy: NSObject { 

    var items = Array<Item>() 

}

Categoryy szybki klasa jest przystosowana do celu C w nagłówku Xcode generowane plik module_name-swift.h następująco:

SWIFT_CLASS("_TtC8waiterio9Categoryy") 
@interface Categoryy : NSObject 
@property (nonatomic, copy) NSArray * items; 
- (instancetype)init OBJC_DESIGNATED_INITIALIZER; 
@end

czy istnieje sposób na pozycje var: pole Array być konwertowane na zmienny NSMutableArray w Objective-C?

+0

nie są w stanie zmienić nagłówek do NSMutableArray? – erdekhayser

+0

To nie jest wykonalne rozwiązanie :(Wygenerowany przez Xcode nagłówek Swift o nazwie MODULE-swift.h jest wymazywany i ponownie tworzony przez Xcode za każdym razem, gdy jeden z plików SWIFT zmienia podpis pola lub metody. Możesz zmienić ręcznie typ pola od NSArray do NSMutableArray, ale gdy tylko zmienisz podpisy pól lub metod pliku swift, wszystkie twoje zmiany zostaną utracone – Giorgio

+0

Czy zgłosiłeś w tym celu radar? –

Odpowiedz

6

To dlatego, że właściwość items jest w rzeczywistości niezmienna.

As you know, ze względu na naturę struct w oparciu o implementację Array w Swift, poniższy kod nie wpływa na cat.items.

let cat = Categoryy() 

var _items = cat.items 
_items.append(item) 

Zamiast tego, trzeba zadzwonić jak ten

cat.items.append(item) 

Z drugiej strony, w Objective-C, [cat.items addObject:item] jest dokładnie taki sam, jak następuje:

id _items = [cat items]; 
[_items addObject:item]; 

która jest bardzo podobna do niepracującego kodu Swift.

Niestety, Objective-C nie ma równoważnej semantyki nazywającej właściwość/metodę jako cat.items.append(item) w Swift.

Jest to podobne do:

// 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 

-

Może Apple może wdrożyć że NSMutableArray (lub prywatnym podklasy), oczywiście można żądać. Wątpię, że Apple to zrobi, ponieważ to łamie bezpieczeństwo typu kompilacji według Generics.

Zresztą, myślę, że należy wdrożyć Categoryy takiego:

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 .. 
} 
1

Jeśli chcesz NSMutableArray, najprostszym sposobem jest po prostu użyć NSMutableArray w Swift. Array<T> nie (i nie może) zachowywać się jednocześnie (niezmiennie) NSArray i NSMutableArray w tym samym czasie - teraz zachowuje się tak, jak jest niezmiennym NSArray. Swift może jednak używać wbudowanego typu klasy, który odpowiada NSMutableArray, ale odpowiada .

Inną alternatywą jest użycie klasy Swift do zawijania NSMutableArray z @objc odkrytymi metodami dostępu do NSMutableArray. Pozwala to również używać generycznych do ograniczania elementów do T.

0

Jako obejście problemu można wywołać append w pliku Swift przy użyciu metody, zamiast uzyskać dostęp do tablicy Swift bezpośrednio w Objective-C.

Swift:

func addItem(item:Item) 
{ 
    items.append(item) 
} 

Objective-C:

[yourSwiftObject addItem:item]; 
Powiązane problemy