2014-01-28 52 views
0

非常奇怪的行爲......我在NSNumber類別之前使用了一個名爲NSNumber + Currencies的類。昨天我已經改變了包括核心數據在內的所有內容到NSDecimalNumber,所以我現在有了一個NSDecimalNumber類的貨幣。根本沒有鏈接!到NSNumber +貨幣了。但是,如果我刪除它並嘗試在模擬器中運行我的應用程序,我的應用程序崩潰,並顯示消息「無法識別的選擇器發送到實例...」此實例是一個NSDecimalNumber,我在此類中使用的方法基本上與以前相同。我真的只導入NSDecimalNumber +貨幣。但它沒有任何意義......我已經從模擬器中刪除了應用程序,清理了我的項目,關閉了Xcode,甚至從構建階段手動刪除了舊的類別,但沒有任何幫助..還有另一個竅門嗎?如果我離開這個老類別它運行平穩...Xcode:應用程序崩潰,因爲我刪除了一個類沒有其他類使用了?

我的錯誤日誌。然而,第二次運行後,我的應用程序不會在所有的啓動和錯誤消息是不同的一個:

2014-01-28 11:51:29.458 NetIncome[2341:70b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array' 
*** First throw call stack: 
(
    0 CoreFoundation      0x01ecf5e4 __exceptionPreprocess + 180 
    1 libobjc.A.dylib      0x01abe8b6 objc_exception_throw + 44 
    2 CoreFoundation      0x01e839c2 -[__NSArrayI objectAtIndex:] + 210 
    3 CoreData       0x01899c1f -[NSFetchedResultsController objectAtIndexPath:] + 255 
    4 NetIncome       0x00003dee -[MainCategoriesViewController tableView:cellForRowAtIndexPath:] + 206 
    5 UIKit        0x003ac61f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412 
    6 UIKit        0x003ac6f3 -[UITableView _createPreparedCellForGlobalRow:] + 69 
    7 UIKit        0x00390774 -[UITableView _updateVisibleCellsNow:] + 2378 
    8 UIKit        0x0038eb81 -[UITableView _updateVisibleCellsImmediatelyIfNecessary] + 66 
    9 UIKit        0x0039cb5f -[UITableView _visibleCells] + 35 
    10 UIKit        0x0039cbb4 -[UITableView visibleCells] + 33 
    11 UIKit        0x0039fcc0 -[UITableView setSeparatorStyle:] + 115 
    12 NetIncome       0x000037d4 -[MainCategoriesViewController styleTableView] + 100 
    13 NetIncome       0x0000300a -[MainCategoriesViewController viewDidLoad] + 1194 
    14 UIKit        0x003d1318 -[UIViewController loadViewIfRequired] + 696 
    15 UIKit        0x003f6b15 -[UINavigationController _layoutViewController:] + 39 
    16 UIKit        0x003f702b -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 235 
    17 UIKit        0x003f7123 -[UINavigationController _startTransition:fromViewController:toViewController:] + 78 
    18 UIKit        0x003f809c -[UINavigationController _startDeferredTransitionIfNeeded:] + 645 
    19 UIKit        0x003f8cb9 -[UINavigationController __viewWillLayoutSubviews] + 57 
    20 UIKit        0x00532181 -[UILayoutContainerView layoutSubviews] + 213 
    21 UIKit        0x00328267 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355 
    22 libobjc.A.dylib      0x01ad081f -[NSObject performSelector:withObject:] + 70 
    23 QuartzCore       0x001972ea -[CALayer layoutSublayers] + 148 
    24 QuartzCore       0x0018b0d4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380 
    25 QuartzCore       0x00197235 -[CALayer layoutIfNeeded] + 160 
    26 UIKit        0x003e3613 -[UIViewController window:setupWithInterfaceOrientation:] + 304 
    27 UIKit        0x00302177 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 5212 
    28 UIKit        0x00300d16 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82 
    29 UIKit        0x00300be8 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 117 
    30 UIKit        0x00300c70 -[UIWindow _setRotatableViewOrientation:duration:force:] + 67 
    31 UIKit        0x002ffd0a __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 120 
    32 UIKit        0x002ffc6c -[UIWindow _updateToInterfaceOrientation:duration:force:] + 400 
    33 UIKit        0x003009c3 -[UIWindow setAutorotates:forceUpdateInterfaceOrientation:] + 870 
    34 UIKit        0x00303fb6 -[UIWindow setDelegate:] + 449 
    35 UIKit        0x003d5737 -[UIViewController _tryBecomeRootViewControllerInWindow:] + 180 
    36 UIKit        0x002f9c1c -[UIWindow addRootViewControllerViewIfPossible] + 609 
    37 UIKit        0x002f9d97 -[UIWindow _setHidden:forced:] + 312 
    38 UIKit        0x002fa02d -[UIWindow _orderFrontWithoutMakingKey] + 49 
    39 UIKit        0x0030489a -[UIWindow makeKeyAndVisible] + 65 
    40 UIKit        0x002b7cd0 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1851 
    41 UIKit        0x002bc3a8 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824 
    42 UIKit        0x002d087c -[UIApplication handleEvent:withNewEvent:] + 3447 
    43 UIKit        0x002d0de9 -[UIApplication sendEvent:] + 85 
    44 UIKit        0x002be025 _UIApplicationHandleEvent + 736 
    45 GraphicsServices     0x035202f6 _PurpleEventCallback + 776 
    46 GraphicsServices     0x0351fe01 PurpleEventCallback + 46 
    47 CoreFoundation      0x01e4ad65 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53 
    48 CoreFoundation      0x01e4aa9b __CFRunLoopDoSource1 + 523 
    49 CoreFoundation      0x01e7577c __CFRunLoopRun + 2156 
    50 CoreFoundation      0x01e74ac3 CFRunLoopRunSpecific + 467 
    51 CoreFoundation      0x01e748db CFRunLoopRunInMode + 123 
    52 UIKit        0x002bbadd -[UIApplication _run] + 840 
    53 UIKit        0x002bdd3b UIApplicationMain + 1225 
    54 NetIncome       0x000027ad main + 141 
    55 libdyld.dylib      0x031c070d start + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

EDIT2:這是原來的錯誤消息,僅刪除相關文件後,顯示一次,並立即:

2014-01-28 12:00:15.598 NetIncome[2872:70b] -[__NSCFNumber getLocalizedCurrencyString]: unrecognized selector sent to instance 0x8c59720 
2014-01-28 12:00:15.602 NetIncome[2872:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber getLocalizedCurrencyString]: unrecognized selector sent to instance 0x8c59720' 
*** First throw call stack: 
(
    0 CoreFoundation      0x01ecf5e4 __exceptionPreprocess + 180 
    1 libobjc.A.dylib      0x01abe8b6 objc_exception_throw + 44 
    2 CoreFoundation      0x01f6c903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275 
    3 CoreFoundation      0x01ebf90b ___forwarding___ + 1019 
    4 CoreFoundation      0x01ebf4ee _CF_forwarding_prep_0 + 14 
    5 NetIncome       0x000358da -[NetIncomeViewController viewDidLoad] + 954 
    6 UIKit        0x003d1318 -[UIViewController loadViewIfRequired] + 696 
    7 UIKit        0x003f6b15 -[UINavigationController _layoutViewController:] + 39 
    8 UIKit        0x003f702b -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 235 
    9 UIKit        0x003f7123 -[UINavigationController _startTransition:fromViewController:toViewController:] + 78 
    10 UIKit        0x003f809c -[UINavigationController _startDeferredTransitionIfNeeded:] + 645 
    11 UIKit        0x003f8cb9 -[UINavigationController __viewWillLayoutSubviews] + 57 
    12 UIKit        0x00532181 -[UILayoutContainerView layoutSubviews] + 213 
    13 UIKit        0x00328267 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355 
    14 libobjc.A.dylib      0x01ad081f -[NSObject performSelector:withObject:] + 70 
    15 QuartzCore       0x001972ea -[CALayer layoutSublayers] + 148 
    16 QuartzCore       0x0018b0d4 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380 
    17 QuartzCore       0x0018af40 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26 
    18 QuartzCore       0x000f2ae6 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294 
    19 QuartzCore       0x000f3e71 _ZN2CA11Transaction6commitEv + 393 
    20 QuartzCore       0x001b0430 +[CATransaction flush] + 52 
    21 UIKit        0x002d9dc9 _afterCACommitHandler + 131 
    22 CoreFoundation      0x01e974ce __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30 
    23 CoreFoundation      0x01e9741f __CFRunLoopDoObservers + 399 
    24 CoreFoundation      0x01e75344 __CFRunLoopRun + 1076 
    25 CoreFoundation      0x01e74ac3 CFRunLoopRunSpecific + 467 
    26 CoreFoundation      0x01e748db CFRunLoopRunInMode + 123 
    27 GraphicsServices     0x0351e9e2 GSEventRunModal + 192 
    28 GraphicsServices     0x0351e809 GSEventRun + 104 
    29 UIKit        0x002bdd3b UIApplicationMain + 1225 
    30 NetIncome       0x00002b3d main + 141 
    31 libdyld.dylib      0x031c070d start + 1 
    32 ???         0x00000001 0x0 + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

的代碼我的應用程序崩潰,在第一次行(最後一行是一個):

//Get or set and get the gross income 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSDecimalNumber *grossIncome = [defaults objectForKey:@"grossincome"]; 
    if (!grossIncome) { 
     [defaults setObject:[NSDecimalNumber zero] forKey:@"grossincome"]; 
     [defaults synchronize]; 
     grossIncome = (NSDecimalNumber *)[defaults objectForKey:@"grossincome"]; 
    } 
    self.incomeValueTextField.enabled = NO; 
    self.incomeValueTextField.delegate = self; 
    self.incomeValueTextField.keyboardType = UIKeyboardTypeDecimalPad; 
    self.incomeValueTextField.text = [grossIncome getLocalizedCurrencyString]; 

而且我品類齊全:

#import "NSDecimalNumber+Currency.h" 
#import "Singletons.h" 

@implementation NSDecimalNumber (Currency) 

- (NSString *) getLocalizedCurrencyString 
{ 
    NSNumberFormatter *numberFormatter = [[Singletons sharedManager] numberFormatter]; 

    NSString *numberString = [numberFormatter stringFromNumber:self]; 

    return numberString; 
} 

- (NSString *) getLocalizedCurrencyStringWithDigits:(int)digits 
{ 
    if(digits == 2){ 
     return [self getLocalizedCurrencyString]; 
    } 

    NSNumberFormatter *numberFormatter; 

    if (digits == 0){ 
     numberFormatter =[[Singletons sharedManager] numberFormatterNoDigits]; 
    } else { 
     numberFormatter =[[NSNumberFormatter alloc] init]; 
     [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; 
     [numberFormatter setLocale:[NSLocale currentLocale]]; 
     [numberFormatter setMinimumFractionDigits:digits]; 
     [numberFormatter setMaximumFractionDigits:digits]; 
    } 

    NSString *numberString = [numberFormatter stringFromNumber:self]; 

    return numberString; 
} 

+ (NSDecimalNumber *) getUnLocalizedDecimalNumberWithString:(NSString *)currencyString 
{ 
    NSNumberFormatter *numberFormatter = [[Singletons sharedManager] numberFormatter]; 

    NSNumber *formatedCurrency = [numberFormatter numberFromString:currencyString]; 

    BOOL isDecimal = formatedCurrency != nil; 
    if(isDecimal){ 
     return [NSDecimalNumber decimalNumberWithDecimal:[formatedCurrency decimalValue]]; 
    } else { 
     return [NSDecimalNumber zero]; 
    } 
} 

- (NSDecimalNumber *)abs { 
    if ([self compare:[NSDecimalNumber zero]] == NSOrderedAscending) { 
     // Number is negative. Multiply by -1 
     NSDecimalNumber * negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1 
                      exponent:0 
                     isNegative:YES]; 
     return [self decimalNumberByMultiplyingBy:negativeOne]; 
    } else { 
     return self; 
    } 
} 
+1

充分展現你的錯誤日誌......這是遠遠不夠的'無法識別的選擇發送到instance'? – Mani

+1

這不是一個無法識別的選擇器崩潰。這是一個數組越界的崩潰。 – jrturton

+1

你的陣列是零 – codercat

回答

1

昨天你一直在warned about subclassing/categories on class clusters,現在你明白了爲什麼。 (好吧,實際上它是更多或NSUserDefaults的意外行爲的問題,但它是相關的^^)

您的問題是,你從NSUserDefaults得到的對象不是一個NSDecimalNumber,因爲NSDecimalNumbers不是plist值可以保存在NSUserDefaults中。但NSDecimalNumber是NSNumber的一個子類,它可以保存在NSUserDefaults中,所以NSUserDefaults只會保存NSDecimalNumber的「NSNumber part」,基本上它會將其轉換爲NSNumber。通過這個過程,它失去了它的精確度,並且是上課。

當你從NSUserDefaults中得到對象時,你實際上會得到一個NSNumber的實例。而你的類別在NSNumber上不存在。


我加了一些調試日誌到您的代碼並運行它給你:

// Wrong! 
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:@"1.23456789123456789"]; 
NSLog(@"%@ - %@", decimalNumber, NSStringFromClass([decimalNumber class])); 
[[NSUserDefaults standardUserDefaults] setObject:decimalNumber forKey:@"___number"]; 
NSDecimalNumber *objectFromUserDefaults = [[NSUserDefaults standardUserDefaults] objectForKey:@"___number"]; 
NSLog(@"%@ - %@", objectFromUserDefaults, NSStringFromClass([objectFromUserDefaults class])); 

其中產量這樣的結果:

xxx[98912:70b] 1.23456789123456789 - NSDecimalNumber 
xxx[98912:70b] 1.234567891234568 - __NSCFNumber 

正如你可以看到返回的對象是一個實例__NSCFNumber

這裏是正確的方法:

// Correct 
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:@"1.23456789123456789"]; 
NSLog(@"%@ - %@", decimalNumber, NSStringFromClass([decimalNumber class])); 
NSData *archivedDecimalNumber = [NSKeyedArchiver archivedDataWithRootObject:decimalNumber]; 
[[NSUserDefaults standardUserDefaults] setObject:archivedDecimalNumber forKey:@"___archivedNumber"]; 
NSData *dataFromUserDefaults = [[NSUserDefaults standardUserDefaults] objectForKey:@"___archivedNumber"]; 
NSDecimalNumber *decimalNumberFromUserDefaults = [NSKeyedUnarchiver unarchiveObjectWithData:dataFromUserDefaults]; 
NSLog(@"%@ - %@", decimalNumberFromUserDefaults, NSStringFromClass([decimalNumberFromUserDefaults class])); 

其產生:

xxx[98912:70b] 1.23456789123456789 - NSDecimalNumber 
xxx[98912:70b] 1.23456789123456789 - NSDecimalNumber 

如預期。

但是你應該仍然擺脫NSDecimalNumber類別。只需將該代碼放入它自己的類中即可。將其稱爲ZHNumberFormatter並在其中進行格式化。

NSNumberFormatters創建過程中採取自己的時間,你不希望創建他們爲每一個轉換。

+0

中的其他項目現在我學到了很多東西:-)我仍然有類別,但現在只需爲用戶默認值中的這個特定值保存一個雙精度值。現在它可以工作。我爲我的NumberFormatter創建了一個Singleton,所以我只在整個應用程序中使用了一個Singleton。 Thx很適合你對我的代碼的深入分析! – MichiZH

-1

您可能仍然在某處引用該類別。 您應該創建一個異常斷點。 (在幫助菜單中查找「創建異常斷點」) 這會阻止你犯下有罪的代碼行!

+0

Thx請參閱我的編輯,我有代碼行導致此。儘管它沒有任何意義,因爲我的老班不在這裏使用.. – MichiZH

+1

這是更好的評論,而不是一個答案。 – Abizern

+0

日誌建議您在NSNumber上調用getLocalizedCurrencyString。 讀你的代碼,我必須承擔有已經存儲在您的喜好(可能是從一箇舊的運行你的NSNumber到NSDecimalNumber變更前)的一個NSNumber的 嘗試從您的測試設備/模擬器等刪除您的應用程序再次 –

0

重置您的模擬器並嘗試運行該應用程序。

iOS模擬器 - >重置內容和設置。

+0

我... ...它總是首先我的應用程序運行良好的相同,直到我訪問選項卡這行代碼在我的編輯上面,然後將其與第二錯誤消息崩潰當我試圖重新打開我的應用我甚至不看第一屏和出現的第一個錯誤消息。我不知道該怎麼辦:-( – MichiZH

+0

分配對象,然後保存到NSUserDefalut。嘗試下面的代碼,它的工作。 NSDecimalNumber * decNum = [[NSDecimalNumber頁頭] initWithDouble:0.0F]; [decNum getLocalizedCurrencyString] – Preet

0

用戶NSKeyedArchiver和NSKeyedUnarchiver將對象存儲在用戶默認值中。 嘗試使用下面的代碼其工作正常。

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
NSDecimalNumber *grossIncome = [defaults objectForKey:@"grossincome"]; 
if (!grossIncome) { 
    NSDecimalNumber *decNum = [[NSDecimalNumber alloc] initWithDouble:0.0f]; 
    NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:decNum]; 
    [defaults setObject:myEncodedObject forKey:@"grossincome"]; 
    [defaults synchronize]; 

    NSData *myDecodedObject = [defaults objectForKey:@"grossincome"]; 
    grossIncome = (NSDecimalNumber*)[NSKeyedUnarchiver unarchiveObjectWithData:myDecodedObject]; 

} 
[grossIncome getLocalizedCurrencyString]; 
+0

你能解釋一下爲什麼我要做到這一點,這並不影響存儲在任何NSUserDefaults的項目,如果我訪問他們「是否正常? 「?我能夠縮小它的範圍,當我刪除這個文件時,這肯定是這些代碼行的問題,並且在崩潰之後,我的應用程序不再啓動了,因爲我的NSFetchedResultsCo ntroller緩存不斷崩潰應用程序。還沒有找到爲什麼,但當我刪除緩存它再次工作。 – MichiZH

+0

它不會影響存儲在 – Preet

相關問題