1

I have a NSMutableArray in which I would like to store some CGRects:

So, I tried using the following (for example):

UIView *view = [[UIView alloc] initWithFrame:(CGRect){{0, 0}, 50, 50}];

[array1 addObject:[NSValue value:&view->frame withObjCType:@encode(CGRect)]];

But this is causing warning: &view->frame

It is a property, but I would like to access it directly so that I can use the above syntax and use it for the value: parameter like the above.

I know I could access &self->_view (if I wanted to add the view to the array, which is not the case here), so I tried &view->frame (and even &view->_frame), but it is causing warning and doesn't work.

It would, unless I so the following first:

CGRect tempRect = view.frame; 
[array1 addObject:[NSValue value:&tempRect withObjCType:@encode(CGRect)]];

So my question is, what have I done wrong here with &view->frame (or even: &view->_frame)?

And is there a way to do that without first having to do this:

CGRect tempRect = view.frame;
[array1 addObject:[NSValue value:&view->frame withObjCType:@encode(CGRect)]];

Other words, can I simply use a cast here without having to create first a CGRect (tempRect)?

Addendum:

If my memory serves, I think casting on & in C is invalid. Am not sure, please let me know if my memory is correct.

Unheilig
  • 16,196
  • 193
  • 68
  • 98
  • 1
    This looks really evil. Why not use the CGRect categories for NSValue? https://developer.apple.com/library/ios/documentation/uikit/reference/NSValue_UIKit_Additions/Reference/Reference.html – Stefan Fisk Jan 28 '14 at 19:33
  • You cannot use `view->frame` or `view->_frame` because `UIView` has no instance variable frame or _frame in its public interface! - Using `valueWithCGRect:`, as Stefan suggested, is the best solution. – Martin R Jan 28 '14 at 19:35
  • @StefanFisk Can you explain the evilness of it? – Unheilig Jan 28 '14 at 19:37
  • @MartinR Right, but I thought `CGRect` is just a struct, and since we could do the same with `struct`, I thought I would try doing this. I heard about the use of `[NSValue valueWithCGRect:view.frame]` but I would like to know if my approach is still feasible and hopefully learn something (good or bad) from it. – Unheilig Jan 28 '14 at 19:39
  • @Unheilig: `value:withObjCType:` requires the *address* of a variable, but UIView does not expose an instance variable for its frame property. And `view.frame` is a method call, and you cannot take the address of a method's/function's return value (we had that discussion, didn't we?). - `[NSValue valueWithCGRect:view.frame]` is effectively the same as your second method using `tempRect`. – Martin R Jan 28 '14 at 20:02
  • @MartinR Sure, I definitely remember, that's why I tried to do `view->frame`; I didn't know `UIView` doesn't expose the `frame` property. My confusion was based on: if there is a property on a class and if I wanted to bypass property usage, I could do `_variable` to access it. Now I know it is not exposed, hence not possible. But going back to the approach: since `CGRect` is a struct, though evil (btw, why is it evil?), it would be possible to send this down to value parameter: `...value:&aSturct....encode(CGRect)..`, correct? – Unheilig Jan 28 '14 at 20:12
  • 1
    @Unheilig: I *assume* that Stefan referred to your accessing the instance variables directly, when speaking of "evil". - `[NSValue value:&tempRect withObjCType:@encode(CGRect)]` looks OK, only that `value:objCType:` is deprecated and you should use `valueWithBytes:objCType:`. But if there is a dedicated method `valueWithCGRect:` then one should use it. – Martin R Jan 28 '14 at 20:16

1 Answers1

2
[array1 addObject:[NSValue valueWithCGRect:view.frame]];

CGRect rect = [[array1 lastObject] CGRectValue];

Documentation: NSValue UIKit Additions Reference

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • But would my approach (though evil as other has claimed, which somehow ignites further my curiosity) still be possible? Could you please elaborate a bit more on the good (if any) and bad of my approach and what's wrong with it? Thanks in advance. – Unheilig Jan 28 '14 at 19:42
  • Your approach is not possible because `UIView` has no instance variable that stores its frame. See [this answer](http://stackoverflow.com/a/13980286/77567) for details. – rob mayoff Jan 28 '14 at 19:59
  • 1
    The closest you can come is `[NSValue valueWithBytes:&(CGRect){view.frame.origin, view.frame.size} objCType:@encode(CGRect)]`, which is confusing and calls `view.frame` twice. – rob mayoff Jan 28 '14 at 20:05
  • But isn't it true that in `C` it is invalid to take the address of a Rvalue (i.e., `&(CGRect)`)? – Unheilig Jan 28 '14 at 20:17
  • 1
    @Unheilig: `(CGRect){view.frame.origin, view.frame.size}` is a "Compound Literal" and that is an lvalue, compare http://gcc.gnu.org/onlinedocs/gcc-3.2.2/gcc/Compound-Literals.html. (I hope that I got the terminology right.) – Martin R Jan 28 '14 at 20:25