使用NSKeyedUnarchiver解压数据如何防止crash

本文介绍如何使用try-catch-finally语句块来处理使用NSKeyedArchiver和NSKeyedUnarchiver过程中可能出现的异常,以避免程序崩溃,并提供了一个具体的案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用NSKeyedArchiver压缩对象成二进制数据,再使用NSKeyedUnarchiver解压二进制数据,如果解压时数据为nil,或者数据中有异常的数据,那么解压将会出错,甚至会导致程序crash掉,例如报错如下:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(
	0   CoreFoundation                      0x026ca5e4 __exceptionPreprocess + 180
	1   libobjc.A.dylib                     0x023988b6 objc_exception_throw + 44
	2   CoreFoundation                      0x0266b556 -[__NSArrayM objectAtIndex:] + 246
	3   论文批阅系统                  0x0002b2f0 -[Stroke initWithCoder:] + 320
	4   Foundation                          0x01fabd6a _decodeObjectBinary + 3498
	5   Foundation                          0x01fad226 -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] + 2204
	6   Foundation                          0x01fad495 -[NSArray(NSArray) initWithCoder:] + 255
	7   Foundation                          0x01fabd6a _decodeObjectBinary + 3498
	8   Foundation                          0x01faae55 _decodeObject + 340
	9   Foundation                          0x01faacf9 -[NSKeyedUnarchiver decodeObjectForKey:] + 181
	10  Foundation                          0x0201c8cd +[NSKeyedUnarchiver unarchiveObjectWithData:] + 106
	11  论文批阅系统                  0x0001b057 -[MyPDFPage initWithDocument:PageIndex:] + 3223
	12  论文批阅系统                  0x0002c1b8 -[PDFScrollView initWithFrame:Document:PageIndex:] + 856
	13  论文批阅系统                  0x00022ae9 -[MainPDFViewController viewDidLoad] + 5193
	14  UIKit                               0x0121e9a8 -[UIViewController loadViewIfRequired] + 696
	15  UIKit                               0x0121ec44 -[UIViewController view] + 35
	16  UIKit                               0x01238a72 -[UINavigationController _startCustomTransition:] + 778
	17  UIKit                               0x01245757 -[UINavigationController _startDeferredTransitionIfNeeded:] + 688
	18  UIKit                               0x01246349 -[UINavigationController __viewWillLayoutSubviews] + 57
	19  UIKit                               0x0137f39d -[UILayoutContainerView layoutSubviews] + 213
	20  UIKit                               0x01175dd7 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
	21  libobjc.A.dylib                     0x023aa81f -[NSObject performSelector:withObject:] + 70
	22  QuartzCore                          0x00dd872a -[CALayer layoutSublayers] + 148
	23  QuartzCore                          0x00dcc514 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
	24  QuartzCore                          0x00dcc380 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
	25  QuartzCore                          0x00d34156 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
	26  QuartzCore                          0x00d354e1 _ZN2CA11Transaction6commitEv + 393
	27  QuartzCore                          0x00d35bb4 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
	28  CoreFoundation                      0x0269253e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
	29  CoreFoundation                      0x0269248f __CFRunLoopDoObservers + 399
	30  CoreFoundation                      0x026703b4 __CFRunLoopRun + 1076
	31  CoreFoundation                      0x0266fb33 CFRunLoopRunSpecific + 467
	32  CoreFoundation                      0x0266f94b CFRunLoopRunInMode + 123
	33  GraphicsServices                    0x0343d9d7 GSEventRunModal + 192
	34  GraphicsServices                    0x0343d7fe GSEventRun + 104
	35  UIKit                               0x0110b94b UIApplicationMain + 1225
	36  论文批阅系统                  0x0002b17d main + 141
	37  libdyld.dylib                       0x0676b70d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

在苹果官网上找到了一个防止crash的方法(http://lists.apple.com/archives/cocoa-dev/2009/Jul/msg00181.html),就是使用try - catch - finally语句块:

例如,将

        // 解压从文件中加载的二进制数据
        NSMutableData *mdata = [filePersistence loadMutableDataFromFile:drawStrokesFileName inDocumentWithDirectory:drawStrokesFileDirectory];
        if (mdata) {
            self.previousDrawStrokes = [NSKeyedUnarchiver unarchiveObjectWithData:mdata];
        }


更改为:

        NSMutableData *mdata = [filePersistence loadMutableDataFromFile:drawStrokesFileName inDocumentWithDirectory:drawStrokesFileDirectory];
        if (mdata) {
            @try {
                self.previousDrawStrokes = [NSKeyedUnarchiver unarchiveObjectWithData:mdata];
            }
            @catch (NSException *exception) {
                NSLog(@"%@", exception);
            }
            @finally {
                
            }
        }

再运行,尽管程序依然会报错:

2013-11-29 18:40:33.820 论文批阅系统[3073:70b] *** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array

但起码不会crash掉。


但要注意的是,这个方法只是防止程序崩溃(起码程序不会死掉了),并没有从根本上解决错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值