viewWillAppear is called on UIViewController when a view is about to be shown on screen. Is it possible to get similar callback on UIView?
3 Answers
How about the following from the UIView reference
willMoveToSuperview:, didMoveToSuperview - Implement these methods as needed to track the movement of the current view in your view hierarchy.
this will at least tell you when it is added to a view hierarchy but there is no guarantee that the view hierarchy is presented/viewable.

- 38,494
- 5
- 70
- 88
-
10I think `willMove(toWindow:)`/`didMoveToWindow()` are slightly closer analogues, because in those you can test if the window is `nil` to see whether the view is part of a hierarchy that is attached to a screen. That's probably what you want if you're setting timers to control animation or something like that. – Jon Colverson Mar 30 '17 at 06:03
-
Jon is right. And this also allows you to check when a view appears between View Controller transitions, even when it isn't moving within the view hierarchy. – Lee Probert Dec 11 '17 at 17:57
No, but you can forward that notification to the desired view from your view controller.

- 2,656
- 1
- 20
- 23
-
8
-
@devios1 Ultimately every view is within a viewController, so unless that view has private access, you can reference that view in the `viewWillAppear` and call `view.MyOnViewWillAppearFunc()`. – mfaani Sep 23 '19 at 16:05
- Note, I was originally going to post this answer here but seeing as this was asked years prior I marked that one as a duplicate and will now answer here instead.
Macro Solution
I've made a macro solution for this that is very elegant and easy to use.
.m
Add the following to your .m
-(void)viewDidLoad {
//normal stuff
}
__METHOD_MACRO_wasRemovedFromSuperview() {
//Code here will run whenever this view is removed from its superview
}
__METHOD_MACRO_wasAddedAsSubview() {
//Code here will run whenever this view is added as the subview of another view
}
Yup! It really is that easy!
(Due to how the ifdef toggling of the macro is set-up below, you can use one or the other or both!)
.h
Add the following to your .h beneath @end
(or, if you want to keep things clean, you can simply add to a file called macros.h and #import it)
Note: If you add this (or import this) to multiple files that also import each other or @class each other you can end up messing up the #ifdef logic and this macro could fail, I suggest importing it from a separate .h file for each class you need it in, this macro was created more as a proof of concept than something to be used in production code
//Logic for __METHOD_MACRO_wasAddedAsSubview() and __METHOD_MACRO_wasRemovedFromSuperview()
#define startSuppressingWarnings() \
_Pragma("clang clang diagnostic push")\
_Pragma("clang diagnostic ignored \"-Weverything\"")
#define stopSuppressingWarnings() \
_Pragma("clang clang diagnostic pop")
#define __INTERNAL_METHOD_MACRO__didChangeSuperviewsSetup() \
-(void)didMoveToWindow {\
[super didMoveToWindow];\
if (self.window && self.superview) {\
startSuppressingWarnings()/*Hide potential undeclared selector warnings*/\
if ([self respondsToSelector:@selector(__wasAddedAsSubview)]) {\
[self performSelector:@selector(__wasAddedAsSubview)];\
}\
stopSuppressingWarnings()\
} else {\
startSuppressingWarnings()/*Hide potential undeclared selector warnings*/\
if ([self respondsToSelector:@selector(__wasRemovedFromSuperview)]) {\
[self performSelector:@selector(__wasRemovedFromSuperview)];\
}\
stopSuppressingWarnings()\
}\
}
#ifdef __INTERNAL_METHOD_MACRO__didChangeSuperviewsSetup_wasSetup
///Called when UIView was added as subview OR moved to another superview OR if another VC was presented
#define __METHOD_MACRO_wasAddedAsSubview() \
-(void)__wasAddedAsSubview/*{ //perform extra processes here }*/
#else
#define __INTERNAL_METHOD_MACRO__didChangeSuperviewsSetup_wasSetup 1
///Called when UIView was added as subview OR moved to another superview
#define __METHOD_MACRO_wasAddedAsSubview() \
__INTERNAL_METHOD_MACRO__didChangeSuperviewsSetup() \
-(void)__wasAddedAsSubview/*{ //perform extra processes here }*/
#endif
#ifdef __INTERNAL_METHOD_MACRO__didChangeSuperviewsSetup_wasSetup
///Called when UIView is removed as subview from superview or when its parent window is removed
#define __METHOD_MACRO_wasRemovedFromSuperview() \
-(void)__wasRemovedFromSuperview/*{ //perform extra processes here }*/
#else
#define __INTERNAL_METHOD_MACRO__didChangeSuperviewsSetup_wasSetup 1
///Called when UIView is removed as subview from superview
#define __METHOD_MACRO_wasRemovedFromSuperview() \
__INTERNAL_METHOD_MACRO__didChangeSuperviewsSetup() \
-(void)__wasRemovedFromSuperview/*{ //perform extra processes here }*/
#endif

- 1
- 1

- 17,282
- 18
- 107
- 195
-
Why would you use a macro that is basically an if condition? Macros are *bad*. – Sulthan Nov 17 '18 at 00:06
-
`Macros are bad` sounds subjective. I did it for fun; it's a neat way of having a viewWillDisppear equivalent that is clear what's happened, as opposed to `willMoveToWindow{if(!window){if(!superview){/*stuff*/}}}` which is not as clear – Albert Renshaw Nov 17 '18 at 00:09