I need some help in understanding how to use NSArrays / NSMutableArrays as properties.
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;
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 UITableView
s data sources). Do you always reload the data source with completely new data? I'd just use NSArray
in that case.
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).
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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With