確實有辦法做到這一點。您可以聲明相關屬性@dynamic
,然後使用+resolveInstanceMethod:
實際按需創建setter。你可以在sample code for iOS:PTL中找到這樣的例子。此示例演示如何自動使您的訪問器讀取和寫入字典(properties
)而不是從ivars讀取和寫入。爲了使這項工作適合您,您可能需要始終在字典中存儲NSNull
並覆蓋獲取方(propertyIMP()
)以將其轉換爲nil
。所以,你會改變這一點:
[[self properties] setValue:value forKey:key];
到:
[[self properties] setValue:(value ?: [NSNull null]) forKey:key];
而變化:
return [[self properties] valueForKey:NSStringFromSelector(_cmd)];
到:
id value = [[self properties] valueForKey:NSStringFromSelector(_cmd)];
return (value == [NSNull null] ? nil : value);
或類似的東西。
但是......除非這是一個主要的勝利,否則我會避免這種魔法。我對此的典型解決方案是以其他方式進行,並將其放在呼叫者不應通過[NSNull null]
的時候。我用像RNNonNull()
功能:
id RNNonNull(id x) { return (x == [NSNull null]) ? nil : x; }
然後調用方負責將包裝:
obj.foo = RNNonNull(mystuff);
如果這是不可能的,我可能會用手工重寫getter就NSNull
轉換爲nil
而不是使用運行時來做(它會是一個單行的方法)。我使用運行時的唯一原因是如果有一堆屬性,並且對象非常簡單(純粹是一個數據對象)。
雖然有用,但我不認爲這實際上回答了關於-setValue:forKey:可重寫性的問題。 –