Last active
August 29, 2015 14:06
-
-
Save AndyDentFree/8e89cb4ca678d3d0bcea to your computer and use it in GitHub Desktop.
Using Objective-C++ for type-safe walking up parent views
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Sometimes in iOS code, you need to be able to walk up the chain of parent views, especially if working on legacy code. | |
This has been hardcoded in the past with horrible assumptions like this, which broke again in iOS 8: | |
if (IS_IOS7_AND_UP) { | |
spdVC = (SuperDuperViewController*)[(UITableView*)self.superview.superview.superview.superview.superview delegate]; | |
} else { | |
spdVC = (SuperDuperViewController*)[(UITableView*)self.superview.superview.superview delegate]; | |
} | |
Usage ONLY IN A .mm FILE eg: | |
UITableView* parentTable = safeParent<UITableView>(self); | |
or, for a UITableView delegate | |
SuperDuperViewController* spdVC = safeParentDelegate<SuperDuperViewController>(self); | |
if (spdVC) {...} | |
If you have never heard of Objective-C++ it allows you to use C++ within Objective-C code | |
so you can use templates like the following. | |
*/ | |
template <class ultimateParentViewT> | |
ultimateParentViewT* safeParent(UIView* ofView) | |
{ | |
if (ofView == nil) | |
return nil; | |
UIView* parent = ofView.superview; | |
if (!parent) | |
return nil; | |
Class parentClass = [ultimateParentViewT class]; | |
while (parent && [parent isKindOfClass:parentClass]==NO) { | |
parent = parent.superview; | |
} | |
return static_cast<ultimateParentViewT*>(parent); | |
} | |
template <class parentViewControllerT, class ultimateParentViewT=UITableView> | |
parentViewControllerT* safeParentDelegate(UIView* ofView) | |
{ | |
if (ofView == nil) | |
return nil; | |
UIView* parent = ofView.superview; | |
if (parent == nil) | |
return nil; | |
Class wantedParent = [ultimateParentViewT class]; | |
while (parent && [parent isKindOfClass:wantedParent]==NO) { | |
parent = parent.superview; | |
} | |
if (parent == nil) | |
return nil; | |
auto parentView = static_cast<ultimateParentViewT*>(parent); | |
id parentDelegate = [parentView delegate]; | |
return static_cast<parentViewControllerT*>(parentDelegate); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment