清除NSMutableArray来存储一个新的json吧

时间:2014-04-23 20:59:04

标签: ios objective-c arrays json nsmutablearray

我在网络请求中提供了一个json数组,并将其存储在NSMutableArray中。第一次运行正常。但是,当我刷新我的屏幕,并且执行一个新的web请求,将json存储在同一个数组中时,问题就开始了

如何清除我的数组以存储来自网络请求的新json?

在我存储json的数组下面:

SingletonClass.h

#import <Foundation/Foundation.h>
@class Singleton;
@protocol SingletonDelegate <NSObject>
@end

@interface SingletonClass : NSObject

// ...
@property (nonatomic, strong) NSMutableArray *uData;

@end

SingletonClass.m

#import "SingletonClass.h"

@implementation SingletonClass

static SingletonClass *sharedInstance = nil;

// Get the shared instance and create it if necessary.
+ (SingletonClass *)sharedInstance {
    if (sharedInstance == nil) {
        sharedInstance = [[super allocWithZone:NULL] init];
    }

    return sharedInstance;
}

- (id)init
{
    self = [super init];
    if (self) {
        // ...
        self.uData = [[NSMutableArray alloc] init]; // store json array from web-request
    }
    return self;
}
@end

这里有3个变种,我尝试在数组中重新存储json。第一个Web请求按预期工作,但如果我执行另一个Web请求,我会收到错误...

WebApi.h

#import "AFHTTPRequestOperationManager.h"
#import "SingletonClass.h"


@interface WebApi : AFHTTPRequestOperationManager <SingletonDelegate>

@property (nonatomic, strong) SingletonClass *sshare;
-(void)getUserStream;

@end

WebApi.m - 包括3个变种

#import "WebApi.h"

#define kApiHost @"http://foo.net"
#define kApiPath @"bar"

@implementation WebApi

-(id)init {
    self = [super init];
    if (self != nil) {
        self.sshare = [SingletonClass sharedInstance];
    }
    return  self;
}

-(void)getUserStream {

    NSString *URLString = [NSString stringWithFormat:@"%@/%@/pics/user", kApiHost, kApiPath];

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    [self setAuthHeader:manager];

    // clear uData
    [self.sshare.uData removeAllObjects];  // Breakpoint set

    [manager GET:URLString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

        // Variant 1
        self.sshare.uData = responseObject;

        // Variant 2
        NSMutableArray *tmp = [NSMutableArray arrayWithArray:responseObject];
        self.sshare.uData = [tmp copy];

        // Variant 3
        NSMutableArray *tmp = [NSMutableArray arrayWithArray:responseObject];
        self.sshare.uData = [tmp mutableCopy];

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        DLog(@"Error: %@, responseString: %@", error, operation.responseString);
    }];
}

@end

在断点removeAllObjects

之后的变量1上出错
[1417:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
*** First throw call stack:
(0x2f851f03 0x39fe6ce7 0x2f851e45 0x2f7cee7b 0x2f79b769 0x3d377 0x3aeb5 0x320b66c7 0x320b6663 0x320b6633 0x320a1d7b 0x321e1eef 0x3a4cfd53 0x3a4d4817 0x3a4cfd3f 0x3a4d13ef 0x3a4d2673 0x2f81c679 0x2f81af45 0x2f7857a9 0x2f78558b 0x346f26d3 0x320e4891 0x63569 0x3a4e4ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException

变量2上的错误,在removeAllObjects

上的断点之后
[1425:60b] -[__NSArrayI removeAllObjects]: unrecognized selector sent to instance 0x156f5910
[1425:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI removeAllObjects]: unrecognized selector sent to instance 0x156f5910'
*** First throw call stack:
(0x2f851f03 0x39fe6ce7 0x2f855837 0x2f85412f 0x2f7a30d8 0x2c2ff 0x29e3d 0x320b66c7 0x320b6663 0x320b6633 0x320a1d7b 0x321e1eef 0x3a4cfd53 0x3a4d4817 0x3a4cfd3f 0x3a4d13ef 0x3a4d2673 0x2f81c679 0x2f81af45 0x2f7857a9 0x2f78558b 0x346f26d3 0x320e4891 0x52569 0x3a4e4ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException

变量3上的错误,在removeAllObjects

上的断点之后
[1392:60b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 3 beyond bounds for empty array'
*** First throw call stack:
(0x2f851f03 0x39fe6ce7 0x2f7880cd 0xefbef 0x321b4199 0x3215b3fb 0x3215ac51 0x32081305 0x31cfd31b 0x31cf8b3f 0x31cf89d1 0x31cf83e5 0x31cf81f7 0x31d4bd45 0x34b1b75d 0x3053c5c9 0x2f811c4d 0x2f81c83f 0x2f81c7db 0x2f81afa7 0x2f7857a9 0x2f78558b 0x346f26d3 0x320e4891 0x119569 0x3a4e4ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException

2 个答案:

答案 0 :(得分:1)

responseObjectNSArray(在您的情况下,它也可能是 NSDictionary,具体取决于JSON响应。)

self.sshare.uData = responseObject;

将此(不可变的)NSArray分配给self.sshare.uData,并且无关紧要 属性声明为NSMutableArray。因此,稍后调用removeAllObjects 在这个对象崩溃。

也是如此
self.sshare.uData = [tmp copy];

因为copy也会返回NSArray,即使在NSMutableArray上进行了调用。

最后,

self.sshare.uData = [tmp mutableCopy];

实际上在属性中存储了一个可变数组。在这种情况下,因为你崩溃了 不要打电话

[self.tableView reloadData]

通知表格视图数据源已更改。


实际上,在开始获取之前,您不必清空数组。 只需分配新值并在调用完成块时重新加载表视图:

[manager GET:URLString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

    self.sshare.uData = responseObject;
    // or, if you need a mutable array:
    // self.sshare.uData = [responseObject mutableCopy];
    [self.tableView reloadData];

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    DLog(@"Error: %@, responseString: %@", error, operation.responseString);
}];

答案 1 :(得分:1)

你的第一个变体是因为某个地方你得到的是NSArray,而不是NSMutableArray(可能是你第一次得到JSON)。您可能希望使用mutableCopy而不是arrayWithArray。

但这一切都没有实际意义:你不需要大惊小怪。将第一个JSON转换为数组时,将其保留为数组(除非您需要更改其内容)。然后,当你得到第二个json数组时,只需指定数组指针指向它,而不是原始数组。像这样:

@property(nonatomic, strong) NSArray * myCurrentJson;
self.myCurrentJson = [mydownloadedJSonString JSONvalue];

然后在你的代码中稍后获得一个新的JSON数组时,只需设置:

self.myCurrentJson = [myNewDownloadedJsonString JSONvalue];

这样myCurrentJson总是指向一个有效的json块,你不必为mutable大惊小怪,因为那些数组不会改变。当你替换数组时,旧的数组不再有任何引用,因此ARC会将它释放到内存中。如果您需要改变值,只需在原始数组上执行mutableCopy,然后在该数组中进行更改。