0

Is there a way to catch an event or notification if a view was added as subview to an existing view of a controller? I have a library here and I cannot subclass but need to know if a specific subview was added to trigger a custom action. Is there a chance?

Krumelur
  • 32,180
  • 27
  • 124
  • 263

2 Answers2

2

I will try adding a category for the didAddSubview method.

EDIT

Category is an alternative to subclassing so you could use something along those lines:

.h:

  #import <UIkit/UIKit.h>

  @interface UIView (AddSubView)

  - (void)didAddSubview:(UIView *)view

  @end

.m:

@implementation UIView (AddSubView)
- (void)didAddSubview:(UIView *)view
{
     [self addSubview: view];

     // invoke the method you want to notify the addition of the subview

}
@end
tiguero
  • 11,477
  • 5
  • 43
  • 61
  • I don't know. What about it? :-) I mean: can you provide some example code? – Krumelur Jan 02 '13 at 16:09
  • Not quite recommended. Here is why: http://stackoverflow.com/questions/5272451/overriding-methods-using-categories-in-objective-c – Rad'Val Jan 02 '13 at 16:36
  • @ValentinRadu Thanks for pointing this out: there are definitely some drawbacks you need to consider when using category for the purpose i mentioned but what about in this scenario? Would you have better alternative? – tiguero Jan 02 '13 at 16:44
  • Yes, in a way, but involves some runtime gymnastics, check out my answer. – Rad'Val Jan 02 '13 at 17:05
  • Isn't there an NSNotification or something KVO'able to use instead of making handstands? – Krumelur Jan 02 '13 at 18:45
  • 1
    As far as I know, nothing reliable. KVO is certainly not reliable since as long as a property is not documented to be KVO, even if it works now, it may break in the future updates. – Rad'Val Jan 02 '13 at 19:22
1

Not that I think this method is cleaner than the one @tiguero suggested, but I think it's slightly safer (see why using categories could be dangerous in my comments to his answer) and offers you more flexibilty.

This is somehow, although not exactly, but more at the conceptual level, the same way KVO works. You basically, dynamically alter the implementation of willMoveToSuperview and add your notification code to it.

//Makes views announce their change of superviews
Method method = class_getInstanceMethod([UIView class], @selector(willMoveToSuperview:));
IMP originalImp = method_getImplementation(method);

void (^block)(id, UIView*) = ^(id _self, UIView* superview) {
    [_self willChangeValueForKey:@"superview"];
    originalImp(_self, @selector(willMoveToSuperview:), superview);
    [_self didChangeValueForKey:@"superview"];
};

IMP newImp = imp_implementationWithBlock((__bridge void*)block);
method_setImplementation(method, newImp);
Rad'Val
  • 8,895
  • 9
  • 62
  • 92
  • Wow. That looks hacky. Will this be accepted for the App Store? – Krumelur Jan 02 '13 at 18:50
  • Accepted as it seems to be the cleaner of the dirty approaches and has been used before, as here: http://stackoverflow.com/questions/5612863/observing-changes-to-a-uiviews-window-and-superview-properties – Krumelur Jan 02 '13 at 19:09
  • Yes, I used it in the past and my app passed validation. On top of that, I see no reason for which they would try to stop you, it's not private API, just, a little bit awkward, but also powerful if you think about it. – Rad'Val Jan 02 '13 at 19:21