1

I have an array of views, and I need to hide them all, so I use:

BOOL shouldHideViews = YES;
[allViews makeObjectPerformSelector:@selector(setHidden:) withObject:(void *)shouldHideViews]

When I convert the code to ARC, it tells me I need some bridged cast, then I changed:

(void *)shouldHideViews

to

(__bridge BOOL)shouldHideViews

it says incompatible types casting 'int' to 'BOOL' with a __bridge cast

So how do I do it? I know I can just iterate all the views in the array, but this is not the point, I want to know in general what I should do to make this ARC compatible.

Thanks!

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
hzxu
  • 5,753
  • 11
  • 60
  • 95
  • Done use arc for automatic-reference-counting questions. Explanation here: http://meta.stackexchange.com/questions/137914/disambiguate-the-arc-tag/137934#comment387066_137914 – Richard J. Ross III Jun 28 '12 at 04:01
  • Was this a working piece of code before ARC? – Sergey Kalinichenko Jun 28 '12 at 04:12
  • @dasblinkenlight, yeah, it magically works. I just ran into another guy doing this last week. It gets turned into a pointer to 0x1 I believe, and it kind of just works it way through the system as a "true enough." – Rob Napier Jun 28 '12 at 04:16

4 Answers4

1

you can't pass primitive types as a void pointer. You should keep the boolean variable as an instance variable and reference it in the setHidden. That way you can just do this:

shouldHideViews = YES; //declare BOOL shouldHideViews; in your .h file
[allViews makeObjectPerformSelector:@selector(setHidden) withObject:nil];
Kpmurphy91
  • 554
  • 5
  • 15
  • I know what you are saying, but setHidden: is a method in UIView, and I have an array of views, so it is not something I can control unless I subclass the view. – hzxu Jun 28 '12 at 04:19
  • Subclass NSArray! You can create a method in your subclassed NSArray that sends setHidden: to all of the UIViews in your array. Make sure that when you loop through all of the objects in the array, you're checking that it's a UIView before sending it setHidden:, or else your app will crash. – Kpmurphy91 Jun 28 '12 at 05:40
1

These will be rather helpful to you

How to use performSelector:withObject:afterDelay: with primitive types in Cocoa?.

Using performSelector:withObject:afterDelay: with non-object parameters

SEL performSelector and arguments

Either you should make a wrapper using NSNumber or use NSInvocation.

Community
  • 1
  • 1
Michael Boselowitz
  • 3,012
  • 1
  • 19
  • 22
1

The object argument to makeObjectsPerformSelector:withObject: is of type id. That means it needs to point to an Objective-C object. Casting a non-object to an id is a bad idea, because the system (particularly under ARC) is allowed to do things like send the retain and release messages to an id, and that will crash if you cast YES to id.

I suggest just using fast enumeration:

for (UIView *view in allViews) {
    view.hidden = shouldHideViews;
}
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
1

The other answers indicating that you can't pass YES this way are correct. There are easier solutions however:

[allViews setValue:[NSNumber numberWithBool: shouldHideViews] forKey:@"hidden"];

This works because NSArray overrides its setValue:forKey: for exactly this use.

You can also now use blocks:

[allViews enumerateObjectsUsingBlock:
  ^(id obj, NSUInteger idx, BOOL *stop){ [obj setHidden:shouldHideViews];}];

Or the tried and true for() loop (see @rob mayoff's answer.)

Of them, I generally just use a for loop.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610