Reputation: 26385
I'd like to create a property made by an array of CGRect pointers, the number is not defined at the beginning, so I'd like to create a pointer of to a zone o memory that contains the beginning of this array of pointer. It seems quite difficult, I've seen different answer and basing my solution on that.
So far I've writtent that:
@interface ViewController ()
@property (assign) CGRect * rectArray;
@property (strong, nonatomic) NSArray * hotspots;
@end
@implementation ViewController
- (CGRect *) createRectArray {
int count = _hotspots.count;
_rectArray = malloc(sizeof(CGRect*)*count);
for (int i = 0; i<count; i++) {
CGRect currentFrame = ((UIView*)_hotspots[i]).frame;
_rectArray[i] = ¤tFrame;
}
return _rectArray;
}
@end
but the compiler complains telling me that the assignment is not correct.
I'm guessing that probably the correct variable is not a CGRect * rectArray, but a double indirection CGRect ** rectArray.
Is that correct?
[UPDATE]
Actually it doesn't make sense what I want to do... because the property -frame return a copy of CGRect and not a pointer to it, so my idea to have direct and fast access to that is gone.
Upvotes: 1
Views: 175
Reputation: 130102
The following code accesses the rectArray
correctly.
@interface ViewController ()
//array of pointers
@property (assign) CGRect **rectArray;
@property (strong, nonatomic) NSArray * hotspots;
@end
@implementation ViewController
- (CGRect **) createRectArray {
int count = _hotspots.count;
_rectArray = malloc(sizeof(CGRect*)*count);
for (int i = 0; i<count; i++) {
//this will never work, the frame returned from UIView is a temporary which will get released!
CGRect currentFrame = ((UIView*)_hotspots[i]).frame;
_rectArray[i] = ¤tFrame;
}
return _rectArray;
}
- (void)dealloc {
free(_rectArray);
}
@end
However, as I am writing in the comments, this won't work. [UIView frame]
returns a C-struct. This behaves the same as primitive variables (NSInteger
, long
etc.). It gets copied. ¤tFrame
is a reference to your local stack variable, which will get freed when the code goes outside scope (for
iteration ends, method ends). It won't do what you are expecting. Accessing the stored pointers will make your application crash.
Your expected functionality can be accomplished easily by the following two methods
- (void)setFrame:(CGRect)frame forHotspotAtIndex:(NSUinteger)index {
UIView* hotspot = [self.hotspots objectAtIndex:index];
hotspot.frame = frame;
}
- (CGRect)frameForHotspotAtIndex:(NSUinteger)index {
UIView* hotspot = [self.hotspots objectAtIndex:index];
return hotspot.frame;
}
Upvotes: 1
Reputation: 3090
If you are allocating an array of CGRects, malloc(sizeof(CGRect*)*count)
is wrong as you are trying to allocate an array of pointers to CGRect.
Also when we assign CGRect to the array, we don't need to get its pointer, _rectArray[i] = currentFrame
should work just fine.
The following code should work for you:
@interface ViewController ()
@property (assign) CGRect * rectArray;
@property (strong, nonatomic) NSArray * hotspots;
@end
@implementation ViewController
- (CGRect *) createRectArray {
int count = _hotspots.count;
_rectArray = malloc(sizeof(CGRect)*count);
for (int i = 0; i<count; i++) {
CGRect currentFrame = ((UIView*)[_hotspots objectAtIndex:i]).frame;
_rectArray[i] = currentFrame;
}
return _rectArray;
}
@end
Upvotes: 1