属性和 ivars 的问题

Posted

技术标签:

【中文标题】属性和 ivars 的问题【英文标题】:Problems with properties and ivars 【发布时间】:2017-04-04 19:26:46 【问题描述】:

我正在尝试从网页加载一些 JSON,它可以工作,但是我在自动合成的属性和内容方面遇到了一些问题。

这是我的 .h 代码:

@interface MasterViewController : UITableViewController

@property (nonatomic, strong) NSArray *jsonList;
@property (nonatomic, strong) NSDictionary *jsonResults;

这是我的 .m 代码:​​

NSData *jsonText = [[NSData alloc] initWithBase64EncodedString: [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil] options:0];

self.jsonResults = [NSJSONSerialization JSONObjectWithData:jsonText options:NSJSONReadingMutableContainers error:&error];  
//jsonResults contains 71 records.
self.jsonList = self.jsonResults.allKeys; //errors out here. [__NSArrayM allKeys]: unrecognized selector sent

JSON 示例:

["CustomerID":419,"CustomerName":"Alford","Locked":0,"ExpenseReport":1,"CustomerID":600,"CustomerName":"Allan","Locked" :0,"ExpenseReport":0,"CustomerID":18424,"CustomerName":"Park","Locked":0,"ExpenseReport":0]

这是堆栈跟踪:

2017-04-04 11:08:04.798180 GWM[30923:6253087] [] nw_host_stats_add_src recv too small, received 24, expected 28
2017-04-04 11:08:04.888706 GWM[30923:6253087] [] ____nwlog_simulate_crash_inner_block_invoke dlopen CrashReporterSupport failed
2017-04-04 11:08:04.889985 GWM[30923:6253087] [] __nwlog_err_simulate_crash simulate crash failed "nw_socket_set_common_sockopts setsockopt SO_NOAPNFALLBK failed: [42] Protocol not available"
2017-04-04 11:08:04.901282 GWM[30923:6253087] [] nw_socket_set_common_sockopts setsockopt SO_NOAPNFALLBK failed: [42] Protocol not available, dumping backtrace:
        [x86_64] libnetcore-856.30.16
    0   libsystem_network.dylib             0x000000010f2a4666 __nw_create_backtrace_string + 123
    1   libnetwork.dylib                    0x0000000110414006 nw_socket_add_input_handler + 3164
    2   libnetwork.dylib                    0x00000001103f1555 nw_endpoint_flow_attach_protocols + 3768
    3   libnetwork.dylib                    0x00000001103f0572 nw_endpoint_flow_setup_socket + 563
    4   libnetwork.dylib                    0x00000001103ef298 -[NWConcrete_nw_endpoint_flow startWithHandler:] + 2612
    5   libnetwork.dylib                    0x000000011040aae1 nw_endpoint_handler_path_change + 1261
    6   libnetwork.dylib                    0x000000011040a510 nw_endpoint_handler_start + 570
    7   libnetwork.dylib                    0x00000001104221f9 nw_endpoint_resolver_start_next_child + 2240
    8   libdispatch.dylib                   0x000000010f021978 _dispatch_call_block_and_release + 12
    9   libdispatch.dylib                   0x000000010f04b0cd _dispatch_client_callout + 8
    10  libdispatch.dylib                   0x000000010f028e17 _dispatch_queue_serial_drain + 236
    11  libdispatch.dylib                   0x000000010f029b4b _dispatch_queue_invoke + 1073
    12  libdispatch.dylib                   0x000000010f02c385 _dispatch_root_queue_drain + 720
    13  libdispatch.dylib                   0x000000010f02c059 _dispatch_worker_thread3 + 123
    14  libsystem_pthread.dylib             0x000000010f4d74de _pthread_wqthread + 1129
    15  libsystem_pthread.dylib             0x000000010f4d5341 start_wqthread + 13

2017-04-04 14:25:58.281111 GWM[30923:6338888] [] nw_socket_write_close shutdown(12, SHUT_WR): [57] Socket is not connected
2017-04-04 14:25:58.281978 GWM[30923:6338888] [] nw_endpoint_flow_service_writes [1.1 ready socket-flow (satisfied)] Write request has 0 frame count, 0 byte count
2017-04-04 14:25:58.282905 GWM[30923:6338894] [] __tcp_connection_write_eof_block_invoke Write close callback received error: [89] Operation canceled
2017-04-04 14:25:58.378 GWM[30923:6252853] -[__NSArrayM allKeys]: unrecognized selector sent to instance 0x600000247fe0
2017-04-04 14:25:58.396 GWM[30923:6338892] XPC connection interrupted
2017-04-04 14:25:59.741 GWM[30923:6252853] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM allKeys]: unrecognized selector sent to instance 0x600000247fe0'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010d1bcd4b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010c7fd21e objc_exception_throw + 48
    2   CoreFoundation                      0x000000010d22cf04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
    3   CoreFoundation                      0x000000010d142005 ___forwarding___ + 1013
    4   CoreFoundation                      0x000000010d141b88 _CF_forwarding_prep_0 + 120
    5   GWM                                 0x000000010c11a29e -[MasterViewController viewDidLoad] + 1070
    6   UIKit                               0x000000010d782a3d -[UIViewController loadViewIfRequired] + 1258
    7   UIKit                               0x000000010d782e70 -[UIViewController view] + 27
    8   UIKit                               0x000000010d7d11fa -[UINavigationController preferredContentSize] + 198
    9   UIKit                               0x000000010dea4b3d -[UIViewController(UIPopoverController_Internal) _resolvedPreferredContentSize] + 62
    10  UIKit                               0x000000010deace79 -[UIPopoverController _transitionFromViewController:toViewController:animated:] + 146
    11  UIKit                               0x000000010dea53a8 -[UIPopoverController _initWithContentViewController:popoverControllerStyle:] + 887
    12  UIKit                               0x000000010dc160bc -[UISplitViewControllerClassicImpl _setupHiddenPopoverControllerWithViewController:] + 110
    13  UIKit                               0x000000010dc14b68 -[UISplitViewControllerClassicImpl _addOrRemovePopoverPresentationGestureRecognizer] + 121
    14  UIKit                               0x000000010dc1442e -[UISplitViewControllerClassicImpl loadView] + 349
    15  UIKit                               0x000000010d78261c -[UIViewController loadViewIfRequired] + 201
    16  UIKit                               0x000000010d782e70 -[UIViewController view] + 27
    17  UIKit                               0x000000010d64c4b5 -[UIWindow addRootViewControllerViewIfPossible] + 71
    18  UIKit                               0x000000010d64cc06 -[UIWindow _setHidden:forced:] + 293
    19  UIKit                               0x000000010d660519 -[UIWindow makeKeyAndVisible] + 42
    20  UIKit                               0x000000010d5d8f8d -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4818
    21  UIKit                               0x000000010d5df0ed -[UIApplication _runWithMainScene:transitionContext:completion:] + 1731
    22  UIKit                               0x000000010d5dc26d -[UIApplication workspaceDidEndTransaction:] + 188
    23  FrontBoardServices                  0x00000001106d96cb __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    24  FrontBoardServices                  0x00000001106d9544 -[FBSSerialQueue _performNext] + 189
    25  FrontBoardServices                  0x00000001106d98cd -[FBSSerialQueue _performNextFromRunLoopSource] + 45
    26  CoreFoundation                      0x000000010d161761 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    27  CoreFoundation                      0x000000010d14698c __CFRunLoopDoSources0 + 556
    28  CoreFoundation                      0x000000010d145e76 __CFRunLoopRun + 918
    29  CoreFoundation                      0x000000010d145884 CFRunLoopRunSpecific + 420
    30  UIKit                               0x000000010d5daaea -[UIApplication _run] + 434
    31  UIKit                               0x000000010d5e0c68 UIApplicationMain + 159
    32  GWM                                 0x000000010c123e9f main + 111
    33  libdyld.dylib                       0x000000010f09768d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

最终我想用表格视图显示它,但我还没有找到一种方法将 NSDictionary 与表格绑定,而不先将其放入 NSArray...

【问题讨论】:

显然你的 JSON 有一个数组作为根而不是字典。 __NSArrayM 是可变数组的内部名称。该错误表明您已向其发送了 allKeys 消息 - 合理地 - 它不理解。 @rmaddy 我在我的 json 样本中添加了 就像我说的,它是一个数组,而不是字典。这就是方括号的意思。 @PhillipMills 为什么它是一个可变数组?我将其声明为 NSArray 属性... 【参考方案1】:

您的 JSON 是一个字典数组。但是您的代码假定 JSON 是一个字典。

如果您只需要 jsonList 数组,我会去掉不必要的 jsonResults 属性。

那么你的代码应该是:

NSData *jsonText = [[NSData alloc] initWithBase64EncodedString: [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil] options:0];

self.jsonList = [NSJSONSerialization JSONObjectWithData:jsonText options:0 error:&error];
if (self.jsonList == nil) 
    NSLog(@"Error reading JSON: %@", error);

【讨论】:

以上是关于属性和 ivars 的问题的主要内容,如果未能解决你的问题,请参考以下文章

我可以将标准 ivars 和属性添加到 NSManagedObject 吗?

核心数据的 Objective C 属性与 ivar 问题

Objective C - 使用属性获取访问器与直接使用 iVar

每个 ivar 都必须是一个属性吗?

Xcode 4.5 中@property 和 ivar 的区别

属性(property)与成员变量(ivar)