我正在分配一個 NSMutableAttributedString,然后將它分配給 SKLabelNode 的 attributesString 屬性。該屬性是一個 (NSAttributedString *),但我認為我可以將它轉換為 (NSMutableAttributedString *),因為它是這樣分配的。然后訪問它的 mutableString 屬性,更新它,每次我想更改字串時都不必再分配一次。
但是在轉換之后,該物件是不可變的,并且當我嘗試對其進行變異時會引發例外。
我不能僅僅因為它被參考為不可變而改變被分配為可變的 NSObject 是真的嗎?
uj5u.com熱心網友回復:
我不能僅僅因為它被參考為不可變而改變被分配為可變的 NSObject 是真的嗎?
不,您在這里的一般直覺是正確的。一般暫時忽略“可變”和“不可變”的概念,而是關注和之間的子類化關系:通常,具有可變/不可變對應項的 Apple 框架物件將可變變體作為不可變變體的子型別。將可變變數分配給不可變變數不會改變存盤變數的任何內容,如下所示:NS<SomeType>NSMutable<SomeType>
@interface Foo: NSObject @end
@implementation Foo @end
@interface Bar: Foo @end
@implementation Bar @end
Foo *f = [[Bar alloc] init];
NSLog(@"%@", f); // => <Bar: 0x6000014b0040>
你可以看到類似的東西NSMutableAttributedString(雖然它有點復雜,因為NSAttributedString和 子型別形成了一個類集群:
NSAttributedString *s = [[NSMutableAttributedString alloc] initWithString:@"Hello"];
NSLog(@"%@", [s class]); // => NSConcreteMutableAttributedString
但是:分配給像 with和上面這樣的區域變數與分配給 an的屬性之間的主要區別在于屬性的定義:fsSKLabelNodeattributedText
@property(nonatomic, copy, nullable) NSAttributedString *attributedText;
具體而言,SKLabelNode執行一個拷貝上分配給它的attributedText屬性,以及一個上執行復制NSMutableAttributedString產生一個不可變的變體:
NSAttributedString *s = [[[NSMutableAttributedString alloc] initWithString:@"Hello"] copy];
NSLog(@"%@", [s class]); // => NSConcreteAttributedString
所以,當你以SKLabelNode這種方式分配給你的時候,它不會存盤你的原始實體,而是它自己的一個副本——而且這個副本恰好是不可變的。
請注意,這是行為是兩件事的匯合:
SKLabelNode選到-copy所分配的變數; 如果它-retain改為編輯它(例如@property(nonatomic, strong, nullable)),這將按您的預期作業NSMutableAttributedStringNSAttributedString從它的-copy方法回傳一個,但它不是必須的。事實上,大多數型別instancetype從回傳-copy,但NSMutableAttributedString選擇NSAttributedString從其-copy方法回傳 an 。(嗯,這就是類簇的重點:-copy→ 不可變的,-mutableCopy→ 可變的)
所以一般來說,情況不一定是這樣,但是您會看到使用這些規則實作的可變/不可變類集群的這種行為。
為了比較,與Foo上面的例子:
@interface Foo: NSObject @end
@implementation Foo
- (instancetype)copyWithZone:(NSZone *)zone {
// Expects to return a new Foo:
return [[[self class] alloc] init];
// OR:
// Not all types allow copying:
return self;
}
@end
@interface Bar: Foo @end
@implementation Bar @end
Foo *f = [[[Bar alloc] init] copy];
NSLog(@"%@", f); // => <Bar: 0x600001e7c1a0>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/403869.html
標籤:
