How to set parentViewController in UIViewController?
Asked Answered
H

6

14

The parentViewController property of UIViewController is readonly, but I am nesting custom view controllers and would like to use this property.

However, since it is readonly, and I found no other way to set this property, my quesion is: how do I set it?

Obviously, UINavigationController can set the property somehow in -pushViewController, and so can -presentModalViewController, so it must be possible.

I am aware that I can just add my own UIViewController property, but I'm sure that parentViewController is, in principle, the correct property.

Hackler answered 7/9, 2009 at 21:39 Comment(2)
I think whoever down voted every answer in this thread could give a reason for it :)Didynamous
It wasn't me, but I suspect that they disagree with using private APIs, and voting down advice to use private APIs seems to be common on SO. Maybe they're Apple moles.Jenninejennings
O
0

However, since it is readonly, and I found no other way to set this property, my quesion is: how do I set it?

If it is readonly, you can't use dot notation without getting a compiler error.

However, you might be able to use categories to add a custom modifyParentViewController method to the UIViewController class.

Even if the property is readonly, the variable itself might be modifiable, if it is not @protected. If it is @protected, subclassing the view controller may allow you the option of modifying the variable.

Outcry answered 7/9, 2009 at 22:12 Comment(2)
Doing this is somewhat too dirty for my taste, but I guess if I were to insist on using parentViewController, this would be pretty much the only possible way.<br> I'll use a custom UIViewController propert though.Hackler
addChildViewController on the parent is how this should be done.Impersonal
B
11

Solution is:

   - (void)setParentController:(UIViewController*)parent{
 [self setValue:parent forKey:@"_parentViewController"];
    }

It does not cause problems with linker!

PS: Don't use "setParentViewController" as method name, because this method exists in private API and Apple say: "The non-public API that is included in your application is setParentViewController:.

If you have defined a method in your source code with the same name as the above mentioned API, we suggest altering your method name so that it no longer collides with Apple's private API to avoid your application being flagged with future submissions.

Please resolve this issue in your next update..."

Basuto answered 10/5, 2010 at 12:44 Comment(1)
Wouldn't this cause an App Store rejection? This solves some of my modal presentation problems, but it's scary.Committeeman
T
10

I realize this question was asked before iOS 5, but for the reference, you should use addChildViewController when you want to nest UIViewControllers. This will also automatically set the parentViewController property.

- (void)addChildViewController:(UIViewController *)childController NS_AVAILABLE_IOS(5_0);

You can read more about "Creating Custom Content View Controllers" at Apple.

Topper answered 20/2, 2013 at 22:2 Comment(1)
This works for me, sets the parentViewController property on the child View Controller. Not sure why it isn't the accepted answer.Sharrisharron
U
2

I tried Alex's suggestion buy making a category for UIViewController, and it worked in the simulator, but not on my phone. here is the category

@interface UIViewController (parentSetter) 
-(void)setParentUIViewController:(UIViewController*)parent;
@end

@implementation UIViewController (parentSetter)
-(void)setParentUIViewController:(UIViewController*)parent
{
 _parentViewController = parent;
}
@end

It compiles and works fine, but note the underscore member which is a bit off putting. That's what causes the linker error when compiling against the 3.0 SDK.

I have a container view that has 2 subviews and a table is one of them. The table needs a parent so it can interact with the navigation bar, among other things.

I'm going with this solution instead:

@interface AdoptedTableViewController : UITableViewController {
    UIViewController* surrogateParent;
}

-(UINavigationController*)navigationController;
@property (nonatomic, assign) IBOutlet UIViewController *surrogateParent;
@end

@implementation AdoptedTableViewController
@synthesize surrogateParent;

-(UINavigationController*)navigationController
{
    if( [super navigationController] )//self.navigationController ) 
    {
        return [super navigationController];
    }
    else
    {
        return surrogateParent.navigationController;
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

All of my table view controllers are now adoptedTableViewControllers. The main reason they need parents is so they can push view controllers on to the navigation stack, so that is handled transparently by the navigation controller getter.

It would be nice if parentViewController were not read only, but in my dabble with _parentViewController I discovered there is more to the ViewController hierarchy than just that property. I think there might be a lot of coupling and responsibilities in that relationship that Apple hasn't cleaned up enough for the masses. For instance, I noticed an odd deselection behavior when moving up the navigation hierarchy that I couldn't fix. Perhaps UINavigation controllers reflect the class of their top controller and behave differently?

In short, it really is read only and there is no clean or simple workaround. You just got to architect around it.

Unicef answered 7/1, 2010 at 9:25 Comment(0)
O
0

However, since it is readonly, and I found no other way to set this property, my quesion is: how do I set it?

If it is readonly, you can't use dot notation without getting a compiler error.

However, you might be able to use categories to add a custom modifyParentViewController method to the UIViewController class.

Even if the property is readonly, the variable itself might be modifiable, if it is not @protected. If it is @protected, subclassing the view controller may allow you the option of modifying the variable.

Outcry answered 7/9, 2009 at 22:12 Comment(2)
Doing this is somewhat too dirty for my taste, but I guess if I were to insist on using parentViewController, this would be pretty much the only possible way.<br> I'll use a custom UIViewController propert though.Hackler
addChildViewController on the parent is how this should be done.Impersonal
T
0

parentViewController is for the purposes of NavigationViewControllers and presenting modal view controllers , there is no way to set the property without the methods pushViewController or presentModalViewController. The parentViewController is a readonly property can only be read by the UIViewController class and UINavigationController class, subclasses of these will not have access to set the property.

Taylor answered 7/9, 2009 at 23:44 Comment(0)
T
0

It looks like calling the setParentViewController: method works.

[childViewController setParentViewController:self];

However this still generates a compiler Warning. Which, IMO, means don't do it (I subclassed instead).

Topical answered 17/2, 2010 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.