Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize NSArrays / NSMutableArrays when declared as properties

I need some help in understanding how to use NSArrays / NSMutableArrays as properties.

  1. What property attributes should the arrays be : strong or copy ? In which case should I use which attribute?
  2. How do I initialize the arrays in code.
  3. Should my property array be NSArray or NSMutableArray

Currently the way I am doing it 2 different ways as below. But it is all patchy and done with no clear understanding of the mechanics of it. Which one of it is correct or incorrect.

Approach 1


 .m file
    interface() 
           @property (nonatomic, strong) NSMutableArray *arrayOfData;
    implementation
         <....other code>

          self.arrayOfData = [NSMutableArray arrayWithCapacity:count];
         [self.arrayOfData addObject:<my object>]

Approach 2


 .h file
         @property (nonatomic, strong) NSArray *arrayOfData;
 .m file
     //Property setter
        - (void)setListOfData:(NSMutableArray *)newList {
              if (_arrayOfData != newList) {
                    _arrayOfData = [newList copy];
              }
          }     

     //Function which initializes the arrayOfData

       NSMutableArray *newData = [[NSMutableArray alloc] init];

       .....<code which adds data>
       self.arrayOfData = newData;
like image 488
Vidya Bansal Avatar asked Sep 13 '13 20:09

Vidya Bansal


1 Answers

NSArray or NSMutableArray

Well, whether to use NSArray or NSMutableArray depends heavily on your use case. Are you changing the contents of the array during runtime but only few items here or there? Use NSMutableArray (perfect for editable UITableViews data sources). Do you always reload the data source with completely new data? I'd just use NSArray in that case.

strong or copy

That again depends on what you want to do. If, when someone calls the property you want them to get their own copy of the data source, use copy. But I have actually never used it this way and I think for 90 % of the use cases you will be better off using strong. That means that the caller of .arrayOfData gets a pointer to the NSArray in your class (and can thus detect changes to it).

how to use

As I mentioned, I usually use NSMutableArray for like a UITableView data source. In the header file I have

@property (nonatomic, strong) NSMutableArray *arrayOfData;

same as you. What I do differently is that in the .m file, I override the getter to lazily create me a NSMutableArray. I would thus leave the setter alone and put the following getter implementation.

- (NSMutableArray *) arrayOfData
{
    if (!_arrayOfData) {
        _arrayOfData = [NSMutableArray new];
    }
    return _arrayOfData;
}

This way, the first time you use self.arrayOfData in your class, it gets allocated and inited and saved into the instance variable. Then from the second time on it will just keep returning the instance variable. Hope this cleared it up a bit.

edit

Sample usecase: You have a Twitter client with TwTableViewController showing the list of tweets. Let's say you will have a private method called -(NSArray*)_getNewTweets that will fetch the tweets from the server and return you an NSArray with them. To do this thing you create a fetchNewData method also. See the flow below.

TwTableViewController.h:

@interface TwTableViewController : UITableViewController
@property (nonatomic, strong) * downloadedTweets;
- (void) fetchNewData;
@end

TwTableViewController.m:

@implementation TwTableViewController

- (NSMutableArray *) downloadedTweets
{
    if (!_downloadedTweets) {
        _downloadedTweets = [NSMutableArray new];
    }
    return _downloadedTweets;
}

- (NSArray *)_getNewTweets
{
    NSArray * newTweets = ... //whatever magic to download new tweets
    return newTweets;
}

- (void) fetchNewData
{
    [self.downloadedTweets addObjectsFromArray:[self _getNewTweets]];
    [self.tableView reloadData]; //animated would be prettier, but out of this scope
}

- (void) viewDidLoad
{
    [super viewDidLoad];
    [self fetchNewData];
}

//tableview stuff

@end

The first time you call self.downloadedTweets, the array will get created empty and you can just keep adding/moving/removing items. No need to overwrite this array for another one, one is enough. I used -addObjectsFromArray: but of course you can use -addObject: also. Is it clearer now?

like image 179
czechboy Avatar answered Nov 15 '22 08:11

czechboy