Frage

I think that I'm missing some fundamental knowledge on Xcode Objective C programming standards. Unfortunately I couldn't find the appropriate solution to my problem.

The problem is that when I try to keep data in an array of objects it becomes impossible to keep them separately. Adding new objects overwrites the previous objects in array. Here is some code about that:

CustomObject.m file:

#import "CustomObject.h"

NSString * title;
NSString * detail;

@implementation CustomObject
- (void) initCustomObjectWithValues : (NSString *) iTitle : (NSString *) iDetail {
    title = [NSString stringWithString:iTitle];
    detail = [NSString stringWithString:iDetail];
}
- (NSString *) getTitle {
    return title;
}
- (NSString *) getDetail {
    return detail;
}

@end

viewDidLoad function in ViewController.m file:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    myMutableArray = [[NSMutableArray alloc] init];

    for (int i=0; i<10; i++) {
        NSString * tempTitle = [@"title " stringByAppendingString:[NSString stringWithFormat:@"%d",i]];
        CustomObject * myCustomObject = [[CustomObject alloc] init];
        [myCustomObject initCustomObjectWithValues :[NSString stringWithFormat:@"%@",tempTitle]
                                                   :[@"detail " stringByAppendingString:[NSString stringWithFormat:@"%d",i]]];
        [myMutableArray addObject:myCustomObject];
    }

    for (int i=0; i<10; i++) {
        NSLog(@"%@",[[myMutableArray objectAtIndex:i] getTitle]);
        NSLog(@"%@",[[myMutableArray objectAtIndex:i] getDetail]);
        NSLog(@"----------------------------");
    }

}

Here, myMutableArray is defined at the top of the ViewController.m file. (To make it global and can be used in other functions in future)

Here what I've got in the logs:

title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------

As far as I understand each new added object overwrites the olds. First I thought that they are referring to same allocated memory but in debug tool myMutableArray seems like this:

Printing description of myMutableArray:
<__NSArrayM 0x8d8cb60>(
<CustomObject: 0x8d8e990>,
<CustomObject: 0x8d8dd40>,
<CustomObject: 0x8d8d2e0>,
<CustomObject: 0x8d8d470>,
<CustomObject: 0x8d8d350>,
<CustomObject: 0x8d8ddf0>,
<CustomObject: 0x8d8df00>,
<CustomObject: 0x8d8df40>,
<CustomObject: 0x8d8dff0>,
<CustomObject: 0x8d8e0c0>
)

Does anyone have an idea about the solution. It should be something very basic but I can't catch the problem.

Thank you all in advance

War es hilfreich?

Lösung

using

NSString * title;
NSString * detail;

outside of the @interface part creates global variables. When you assign a variable to title or detail you don't set an instance variable of your object, you change those global variables. And since they are global, they are the same for all objects that reference them.

Turn those global variables into instance variables, or even better use @property.

Your code is bad objective-c overall.
You should not use get in getters that return variables. You should not have methods that start with init and don't return self. You should only call init in [[Foo alloc] init...] situations. You should avoid unnamed parameters in your methods. And there is no need to create strings from strings from strings.

Here is how I would write it:

// CustomObject.h
@interface CustomObject : NSObject
@property (copy, nonatomic) NSString * title;
@property (copy, nonatomic) NSString * detail;

- (id)initWithTitle:(NSString *)title detail:(NSString *)detail
@end

// CustomObject.m
#import "CustomObject.h"

@implementation CustomObject

- (id)initWithTitle:(NSString *)title detail:(NSString *)detail {
    self = [super init];
    if (self) {
        // use stringWithString: to create @"" strings when title is nil
        // if nil is a valid value for those variables you should use
        // _title = [title copy];
        _title = [NSString stringWithString:title];
        _detail = [NSString stringWithString:detail];
    }
    return self;
}

@end

 

for (int i=0; i<10; i++) {
    NSString *tempTitle = [NSString stringWithFormat:@"title %d",i];
    NSString *tempDetail = [NSString stringWithFormat:@"detail %d",i];
    CustomObject * myCustomObject = [[CustomObject alloc] initWithTitle:tempTitle detail:tempDetail];
    [myMutableArray addObject:myCustomObject];
}

for (int i=0; i<10; i++) {
    CustomObject *object = myMutableArray[i];
    NSLog(@"%@", object.title);
    // or NSLog(@"%@", [object title]); if you don't like dot-notation.
    NSLog(@"%@", object.detail);
    NSLog(@"----------------------------");
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top