2014-09-19 15 views
11

Một lớp Swift đơn giản có một trường kiểu var Array. Khi lớp được thích nghi với Objective-C kiểu trường được tiếp xúc như NSArray (bất biến) trong khi nó phải được NSMutableArray (có thể thay đổi)Trường lớp Swift loại var Array được chuyển thành NSArray bất biến thay vì NSMutableArray

class Categoryy: NSObject { 

    var items = Array<Item>() 

}

Các Categoryy lớp nhanh chóng được điều chỉnh để Objective-C trong tiêu đề Xcode tạo tập tin MODULE_NAME-swift.h như sau:

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

là có một cách cho các mục var: trường mảng được chuyển đổi sang một NSMutableArray có thể thay đổi trong Objective-c?

+0

Bạn không thể thay đổi tiêu đề để NSMutableArray? – erdekhayser

+0

nó không phải là một giải pháp khả thi: (Tiêu đề Xcode tạo cho Swift có tên MODULE-swift.h bị xóa và tái tạo bởi Xcode mỗi lần một trong những tệp nhanh chóng thay đổi một trường hoặc chữ ký phương thức. các trường từ NSArray tới NSMutableArray nhưng ngay khi bạn thay đổi các trường hoặc các phương thức của một tập tin nhanh chóng, tất cả các thay đổi của bạn đều bị mất – Giorgio

+0

Bạn đã tạo ra một radar về điều này chưa? –

Trả lời

6

Đó là vì items thuộc tính thực sự là không thay đổi.

As you know, vì bản chất của struct dựa trên việc triển khai Array trong Swift, mã sau không ảnh hưởng đến cat.items.

let cat = Categoryy() 

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

Thay vào đó, bạn phải gọi như thế này

cat.items.append(item) 

Mặt khác, trong Objective-C, [cat.items addObject:item] là chính xác giống như sau:

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

Đó là rất giống nhau sang mã Swift không hoạt động.

Rất tiếc phải nói, Mục tiêu-C không có thuộc tính/phương thức tương đương gọi ngữ nghĩa là cat.items.append(item) trong Swift.

này tương tự như:

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

-

Có lẽ Apple có thể thực hiện điều đó như NSMutableArray (hoặc lớp con tin), tất nhiên bạn có thể yêu cầu. Tôi nghi ngờ Apple sẽ làm điều đó, bởi vì điều đó phá vỡ thời gian biên dịch an toàn loại bằng Generics.

Dù sao, tôi nghĩ, bạn nên thực hiện Categoryy như thế này:

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

Nếu bạn muốn một NSMutableArray, cách dễ nhất là chỉ cần sử dụng một NSMutableArray trong Swift. Array<T> không (và không thể) cả hai hoạt động như (một bất biến) NSArrayNSMutableArray cùng một lúc - ngay bây giờ, những gì nó hoạt động như là một bất biến NSArray. Swift có thể sử dụng loại lớp được tích hợp tương ứng với NSMutableArray cách Array<T> tương ứng với NSArray.

Một giải pháp thay thế khác là sử dụng lớp Swift bao gồm NSMutableArray với @objc các phương pháp tiếp xúc để truy cập vào NSMutableArray. Điều đó cũng cho phép bạn sử dụng Generics để hạn chế các mục thành T.

0

Để giải quyết sự cố này, bạn có thể gọi append trong tệp Swift bằng phương thức, thay vì truy cập mảng Swift trực tiếp trong Mục tiêu-C.

Swift:

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

Objective-C:

[yourSwiftObject addItem:item]; 
Các vấn đề liên quan