NSMutableArray中的__NSCFString在分配它的函数之外变为nil

时间:2014-08-30 02:12:55

标签: ios objective-c arrays json nsstring

我的应用中有一个代表用户OtherUser的课程。该类包含多个NSString *属性。当我使用静态@"string"字符串分配这些属性时,属性将保存为__NSCFConstantString *值。当我使用从JSON转换的字符串为它们分配时,它们将保存为__NSCFString *值。我正在保存OtherUser个对象的可变数组的可变数组。当我在分配值的函数之外访问数组时,只有__NSCFConstantString *值仍然存在,而__NSCFString *值都变为零。有没有办法将我的NSCFString对象转换为NSCFConstantString对象,或者某种方法来解决这个限制?

This是数组在我的ConnectionDidFinishLoading方法中分配了所有值后的样子。 User Test Testman是使用下载的JSON数据创建的,而用户Rose Lalonde是在本地创建的,具有@"string"值。

This是我在CellForRowAtIndexPath方法中再次提取数组时的数组。除了他的身份证外,Test Testman丢失了他的所有数据,而Rose Lalonde保留了她的所有数据。 (我为链接图像而不是嵌入而道歉 - 我的代表还不够高,无法嵌入图片。)

这是我的connectionDidFinishLoading方法,首先调用它并创建数组:

//Called when the connection finishes loading all data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSLog(@"Connection finished!");

    //Converts downloaded JSON data to an array
    NSError *error = [[NSError alloc] init];
    NSArray *arr = [NSJSONSerialization JSONObjectWithData:_responseData
                                                   options:kNilOptions
                                                     error:&error];

    //Checks if the array was properly instantiated
    if (!arr) {
        NSLog(@"Error parsing JSON: %@", error);
    } else {
        //Initializes the arrays if they are not already initialized
        if (!_bestFriends) _bestFriends = [[NSMutableArray alloc] init];
        if (!_onlineFriends) _onlineFriends = [[NSMutableArray alloc] init];
        if (!_offlineFriends) _offlineFriends = [[NSMutableArray alloc] init];

        //Loops through each result dictionary and creates a friend object with its contents
        for(NSDictionary *item in arr) {
            OtherUser *friend = [[OtherUser alloc] init];
            friend.firstname = [NSString stringWithString:(NSString *)[item objectForKey:@"firstname"]];
            friend.lastname = (NSString *)[item objectForKey:@"lastname"];
            friend.username = (NSString *)[item objectForKey:@"username"];
            friend.userID = [NSNumber numberWithInt:[(NSString *)[item objectForKey:@"userID"] intValue]];
            friend.isOnline = [(NSString *)[item objectForKey:@"isOnline"] boolValue];
            friend.isInSession = [(NSString *)[item objectForKey:@"isInSession"] boolValue];

            //Sorts the friend into online or offline
            if (friend.isOnline) {
                [_onlineFriends addObject:friend];
            } else {
                [_offlineFriends addObject:friend];
            }
        }

        //user object created with local data to test best friends array
        OtherUser *tempUser = [[OtherUser alloc] initWithFirstname:@"John"
                                                          Lastname:@"Egbert"
                                                          Username:@"ectobiologist"
                                                            UserID:[NSNumber numberWithInt:10]
                                                       OnlineState:YES
                                                      SessionState:NO];
        [_bestFriends addObject:tempUser];

        //User created with local data to compare to downloaded JSON users
        OtherUser *tempUser2 = [[OtherUser alloc] initWithFirstname:@"Rose"
                                                           Lastname:@"Lalonde"
                                                           Username:@"tentacletherapist"
                                                             UserID:[NSNumber numberWithInt:15]
                                                        OnlineState:YES
                                                       SessionState:NO];
        [_onlineFriends addObject:tempUser2];
    }

    //Adds the arrays to the array array
    self.arrays = [NSMutableArray arrayWithObjects:_bestFriends, _onlineFriends, _offlineFriends, nil];

    //Resets the table data
    [self.tableView reloadData];
    NSLog(@"reloading data...");
}

我的CellForRowAtIndexPath方法,接下来被调用并且是数组数据被擦除的地方,如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"Creating Cell...");
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    //Creates a user object from the proper index of the proper array (e.g. _onlineFriends[1])
    OtherUser *friend = [[_arrays objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];

    // Configure Cell
    UILabel *label = (UILabel *)[cell.contentView viewWithTag:10];
    [label setText:[friend fullname]];

    NSLog(@"Cell created!");
    return cell;
}

以及我的FriendsTableViewController.h文件,以防万一:

@interface FriendsTableViewController : UITableViewController <NSURLConnectionDelegate> {
    NSMutableData *_responseData;
    NSMutableArray *_onlineFriends;
    NSMutableArray *_bestFriends;
    NSMutableArray *_offlineFriends;
}

@property NSMutableArray *arrays;

编辑:其他用户文件:

//OtherUser.h
#import <Foundation/Foundation.h>

@interface OtherUser : NSObject

@property (weak, nonatomic) NSNumber *userID;
@property (weak, nonatomic) NSString *firstname;
@property (weak, nonatomic) NSString *lastname;
@property (weak, nonatomic) NSString *username;
@property (nonatomic, assign) BOOL isOnline;
@property (nonatomic, assign) BOOL isInSession;
@property (weak, nonatomic) NSNumber *sessionID;

- (id)initWithFirstname:(NSString *)firstName Lastname:(NSString *)lastName
               Username:(NSString *)userName UserID:(NSNumber *)uID
            OnlineState:(BOOL)online SessionState:(BOOL)inSession;
- (id) init;

- (NSString *) fullname;

//OtherUser.m

//Initializes an empty User object
- (id)init {
    self = [super init];
    if (self) {
        self.userID = 0;
        self.username = @"";
        self.firstname = @"";
        self.lastname = @"";
        self.isOnline = NO;
        self.isInSession = NO;

        return self;
    }
    return nil;
}

- (id)initWithFirstname:(NSString *)firstName Lastname:(NSString *)lastName
               Username:(NSString *)userName UserID:(NSNumber *)uID
            OnlineState:(BOOL)online SessionState:(BOOL)inSession {
    self = [super init];

    if (self) {
        self.userID = uID;
        self.username = userName;
        self.firstname = firstName;
        self.lastname = lastName;
        self.isOnline = online;
        self.isInSession = inSession;

        NSLog(@"Friend %@ %@ created.", self.firstname, self.lastname);

        return self;
    }
    return nil;
}

- (NSString *)fullname {
    return [NSString stringWithFormat:@"%@ %@", self.firstname, self.lastname];
}

1 个答案:

答案 0 :(得分:3)

您已将“firstname”,“lastname”和其他属性声明为 weak

@property (weak, nonatomic) NSString *firstname;

表示它们不保留引用的对象,并将设置为nil 如果引用的对象被释放。当JSON数组arr出现时会发生这种情况 超出范围。 NSString文字是静态分配的,永远不会被释放, 这就是为什么Rose Lalonde不会失去这里的财产。

您应该将Objective-C属性声明为 strong ,或者 - 在字符串的情况下 - 声明为 copy

@property (copy, nonatomic) NSString *firstname;
// ...
@property (strong, nonatomic) NSNumber *sessionID;

顺便说一句,所有类型广播和<{p>}中的stringWithString电话

friend.firstname = [NSString stringWithString:(NSString *)[item objectForKey:@"firstname"]];
friend.lastname = (NSString *)[item objectForKey:@"lastname"];
// ...

没有必要,您可以简单地将其写为

friend.firstname = [item objectForKey:@"firstname"];
friend.lastname = [item objectForKey:@"lastname"];

或使用(较新的)下标符号:

friend.firstname = item[@"firstname"];
friend.lastname = item[@"lastname"];