0

I have a table view with a search, and search scope buttons with two possible scopes. The table is empty until a search is executed. Each scope has it's own mutable array for the table's data source, we'll say scopeA_array and scopeB_array. To simplify some methods, I'm trying to create a generic pointer reference to whichever array is the currently active scope. So I tried this:

@property (nonatomic, assign) NSMutableArray *tableDataArray;

In viewDidLoad, I assign it to the default selected scope.

_tableDataArray = _scopeA_array;

I can log the memory address of each array, they're both the same.

However, if I execute a search, _scopeA_array gets populated. Then in my numberOfRowsInSection method, I take the count of _tableDataArray but it's empty. I log the addresses again, both are different.

How do I create an array property that just references an array, and always points to the same object in memory even if it changes?

EDIT: A simplified way to test this, with the following lines of code, would like a way for tableDataArray to have the contents of testArray, even though the contents of testArray are assigned after:

NSArray *testArray = [NSArray new];
NSArray *tableDataArray = [testArray copy];
testArray = [NSArray arrayWithObjects:@"my", @"test", @"array", nil];
NSLog(@"table data array: %@", tableDataArray);
// logs empty array
9
  • You're not incrementing the retain count of _scopeA_array ... does it get deallocated before your numberOfRowsInSection call? Commented Jan 29, 2015 at 5:53
  • I don't know, how would I do that? Commented Jan 29, 2015 at 5:58
  • How do you populate _scopeA_array ? Commented Jan 29, 2015 at 5:59
  • 2
    Well, I think that's your problem. To keep the same reference for _scopeA_array you should instead use [_scopeA_array addObjectsFromArray:request_result], asuming request_result is an array Commented Jan 29, 2015 at 6:04
  • 1
    Try changing the property to (nonatomic, strong). Commented Jan 29, 2015 at 6:16

2 Answers 2

3

I think the best approach is use a method to return conditionally the array for the current scope. So you just always use this method to populate your UITableView

- (NSMutableArray*) tableArray
{
    return [self isScopeA] ? _scopeA_array : _scopeB_array;
}
Sign up to request clarification or add additional context in comments.

5 Comments

This is what I'm doing now, but the point (and the question) was to use a pointer reference, if that's even possible.
I can't see why would you like to do that rather this. But anyway you should could assign like this self.tableDataArray = _scopeA_array; when you change your scope
That wouldn't work, because the array gets populated after a search is made, after the scope is changed.
I think that will work because once you assing to self.tableDataArray, this array is pointing to _scopeA_array and therefore the changes made on _scopeA_array are available through self.tableDataArray
I misunderstood the answer before, you are right. This is the best way to do it.
1

How do I create an array property that just references an array, and always points to the same object in memory even if it changes?

If you want to track changes to a variable then you use a pointer to the variable rather than a pointer to a single array instance. E.g.:

@implementation MyController
{
    __strong NSArray* *_currentDataPtr;
    NSArray* _dataA;
    NSArray* _dataB;
}

- (id)init
{
    if (self = [super init])
    {
        _currentDataPtr = &_dataA; // Ensure _currentDataPtr is never NULL
    }
    return self;
}

- (void)setSearchScope:(NSInteger)searchScope
{
    switch (searchScope)
    {
        default :
            NSAssert(NO, @"");
        case 0 :
            _currentDataPtr = &_dataA;
            break;
        case 1 :
            _currentDataPtr = &_dataB;
            break;
    }
}

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    return [*_currentDataPtr count];
}

If you want it to be a property then implement a property getter that dereferences the pointer:

@property (nonatomic, readonly) NSArray* currentData;

- (NSArray*)currentData { return *_currentDataPtr; }

2 Comments

Tried to implement this but xcode doesn't like the double asterisk in NSArray* *_currentDataPtr;, and complains "Pointer to non-const type 'NSArray *' with no explicit ownership." Is that a typo?
@inorganik It looks like you have to explicitly declare the ownership in that case. Local variables and instance variables are __strong by default. I've edited my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.