I want to allow for communication between different views.
I have two smaller views that sit on top of a bigger view, similar to iOS' video player, with some differences. When I tap the bigger view I want to toggle the views appearance, hide or unhide. I've got a protocol that all the views conform to. I want to add the views to another class I'll call HideViewsService
, which has an NSArray
property. Can I force the class that uses this HideViewsService
class, and adds the views, to add only views that conform to this protocol? Or even just UIViews
?
Also, I'd like to call a method on the views that I know all have it, but I don't know how to get by the compiler. Here is my -hideAllViews
method:
-(void)hideAllViews
{
for(int i=0; i<self.viewArray.count; i++)
{
id obj = [self.viewArray objectAtIndex:i];
if([obj isKindOfClass:[UIView class]] == false)
{
return;
}
UIView *view = (UIView *)obj;
if([view respondsToSelector:@selector(hide)])
{
[view hide]; // the compiler obviously doesn't like this
}
}
}
Thanks!! I'm still learning, so please tell me if there is a better way (not just easier, but better).
ObjC does not have generics. Sometimes it would be nice if it did, but it doesn't. But the above design has several problems.
First, if viewArray
is supposed to contain only UIView
objects, then it is a programming error for it to contain anything else. It is not ok to just return
if you find that it doesn't. If you're going to check this here, it should be NSAssert()
. Similarly, if everything in viewArray
should be respond to hide
, you shouldn't just skip it if it doesn't. That's the source of many subtle bugs.
The better solution is to control addition of objects at the point of adding them to HideViewsService
(though there are really better ways to do it anyway; we'll get to that).
@protocol XYZHideableView <NSObject>
- (void)hide;
@end
@interface XYZHideViewsService
- (void)addHideableView:(id<XYZHideableView>)view;
- (void)removeHideableView:(id<XYZHideableView>)view;
@end
Now, you don't need to worry about whether viewArray
contains things that respond to hide
.
That said, I'd generally do this with NSNotificationCenter
. Hideable views should observe a notification like XYZHideAllHideableViews
. When they set it, they should hide themselves. Then you don't need a HideViewsService
. You just just need a +[HideableView hideAllHideableViews]
class method.
If you want to compile without warnings you can just check if the object conforms to the protocol and then cast it to id<Protocol>
:
if ([view conformsToProtocol:@protocol(Protocol)]) {
id<Protocol> conformingView = (id<Protocol>)view;
// or
UIView<Protocol> *conformingView = (UIView<Protocol>*)view;
}
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