2011-02-19 21 views
2

我有一個不錯的對象,描述了一個比較大的數據集。我決定在對象中實現一些輔助功能。顯然,我不知道如何寫一個setter

基本上,而是採用了標準制定者的NSString的,我定義自己的二傳手,並在同一時間設置的另一個對象。

例如:

-(void) setNumber:(NSString *)number_in 
{ 
    number = [number_in copy]; 
    title = @"Invoice "; 
    title = [title stringByAppendingString:number]; 
} 

我知道我會需要「稱號」作爲特定格式的屬性。標題是基於數字,所以我創建了一個setter來在一個打卡中設置數字和標題。 (標題有默認的合成二傳手......我不別處定義它)

出於某種原因,我越來越發送到釋放實例錯誤的消息。如果我刪除這個setter,代碼工作正常。

我的屬性定義是在這裏:

@property (nonatomic, copy) NSString *number; 
@property (nonatomic, copy) NSString *title; 

我試圖保持,無濟於事。我設置的malloc堆日誌和記錄此:

Alloc: Block address: 0x06054520 length: 32 
Stack - pthread: 0xa003f540 number of frames: 30 
    0: 0x903ba1dc in malloc_zone_malloc 
    1: 0x102b80d in _CFRuntimeCreateInstance 
    2: 0x102d745 in __CFStringCreateImmutableFunnel3 
    3: 0x10824dd in _CFStringCreateWithBytesNoCopy 
    4: 0xae222e in -[NSPlaceholderString initWithCStringNoCopy:length:freeWhenDone:] 
    5: 0xaf9e8e in _NSNewStringByAppendingStrings 
    6: 0xaf9a76 in -[NSString stringByAppendingString:] 
    7: 0x112ba in -[Invoice setNumber:] at Invoice.m:25 
    8: 0x11901 in -[Invoice copyWithZone:] at Invoice.m:47 
    9: 0x107c7ca in -[NSObject(NSObject) copy] 
    10: 0x1117632 in -[NSArray initWithArray:range:copyItems:] 
    11: 0x107f833 in -[NSArray initWithArray:copyItems:] 
    12: 0x5595 in -[InvoicesTableViewController wrapper:didRetrieveData:] at InvoicesTableViewController.m:96 
    13: 0x4037 in -[Wrapper connectionDidFinishLoading:] at Wrapper.m:288 
    14: 0xb17172 in -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] 
    15: 0xb170cb in _NSURLConnectionDidFinishLoading 
    16: 0x18ca606 in _ZN19URLConnectionClient23_clientDidFinishLoadingEPNS_26ClientConnectionEventQueueE 
    17: 0x1995821 in _ZN19URLConnectionClient26ClientConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XClientEvent18XClientEventParamsEl 
    18: 0x18c0e3c in _ZN19URLConnectionClient13processEventsEv 
    19: 0x18c0cb7 in _ZN17MultiplexerSource7performEv 
    20: 0x10fd01f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ 
    21: 0x105b28b in __CFRunLoopDoSources0 
    22: 0x105a786 in __CFRunLoopRun 
    23: 0x105a240 in CFRunLoopRunSpecific 
    24: 0x105a161 in CFRunLoopRunInMode 
    25: 0x1c29268 in GSEventRunModal 
    26: 0x1c2932d in GSEventRun 
    27: 0x39542e in UIApplicationMain 
    28: 0x2199 in main at main.m:14 
    29: 0x2115 in start 

最後,我不斷收到此錯誤:

-[CFString release]: message sent to deallocated instance 0x4b5aee0 

感謝提前:)

回答

7

使用self.title調用你合成一百萬設定裝置以及釋放舊的價值number

- (void)setNumber:(NSString *)number_in 
{ 
    [number release]; 
    number = [number_in copy]; 
    self.title = [NSString stringWithFormat:@"Invoice %@", number]; 
} 
+0

我想我愛你。 (將在6分鐘內接受) – clifgriffin

+0

這是更好的:) – fabian789

+0

或者你可以寫[title title release]和'title = [[NSString stringWithFormat:@「Invoice%@」,number] retain]'以防你想要title屬性是隻讀的,因爲我認爲它應該是。 – tia

5

title是越來越自動釋放並number在程序中泄漏。要編寫一個完整的setter,你應該首先複製傳入的對象,然後做一個發佈。

-(void) setNumber:(NSString *)number_in { 
    if (number == number_in) { 
     return; 
    } 

    NSString *oldValue = number; 
    number = [number_in copy]; 
    [oldValue release]; 

    self.title = [title stringByAppendingString:number]; 
} 

原因首先複製,然後釋放是因爲不可變對象上調用copy可以返回相同的對象回來,而不是創建一個新的副本。因此,如果setNumber被同一個對象調用了兩次,並且首先發布了number,則它變爲無效,然後在該無效對象上調用copy可能會導致問題。

if檢查是優化步驟,而如果你想你可以刪除。

此外,您可能希望在編寫自定義制定者結帳這個article

由於@tia和@Mark已發佈,如果標題始終依賴於號碼的值,則標題應爲readonly屬性。然後將改性setNumber可能看起來像,可能需要當nil number_in被傳遞爲

- (void) setNumber:(NSString *)number_in { 
    if (number == number_in) { 
     return; 
    } 

    NSString *oldNumber = number; 
    number = [number_in copy]; 
    [oldNumber release]; 

    NSString *oldTitle = title; 
    title = [title stringByAppendingString:number]; 
    [oldTitle release]; 
} 

附加的檢查,當nil傳遞給stringByAppendingString,一個NSInvalidArgumentException升高爲。所以這裏有這個檢查器的最終版本,

- (void) setNumber:(NSString *)number_in { 
    if (number == number_in) { 
     return; 
    } 

    NSString *oldNumber = number; 
    number = [number_in copy]; 
    [oldNumber release]; 

    if (number) { 
     NSString *oldTitle = title; 
     title = [title stringByAppendingString:number]; 
     [oldTitle release]; 
    } 
} 
+0

+1我從來沒有理解在複製操作期間保持原有值的原因直到現在。謝謝! –

+0

哇。謝謝。非常非常有幫助。 – clifgriffin

相關問題