views:

734

answers:

3

I have 4 buttons on main screen, each one sends me to a viewController. The third one, sends me to a view on which I wanna set the managedObjectContext. If I use the class name to create an instance, it's all right. But I'm looking for a way to use just one method that uses an array to retrieve the name of the Class for the needed viewController. But it's leading to an error message, like it doesn't exist on the destination viewController??? Anyone have any ideas about this aproach??? Thanks in advance!

Here is the code:

NSArray *viewControllers = [[NSArray alloc]
initWithObjects:@"nil",@"OpcoesView",@"nil",@"TheNames", nil];

NSString *viewName = [viewControllers objectAtIndex:[sender tag]]; //the taped button tag

UIViewController *viewController = [[NSClassFromString(viewName) alloc]
initWithNibName:viewName bundle:nil];


if ([sender tag] == 3) {
    viewController.managedObjectContext = contexto;
}
A: 

To set a property that is only in the subclass view controller (such as "managedObjectContext"), you can take advantage of the fact that you know the type like this:

NSArray *viewControllerNames = [[NSArray alloc] initWithObjects:@"nil",@"OpcoesView",@"nil",@"TheNames", nil];

NSString *viewControllerName = [viewControllerNames objectAtIndex:[sender tag]]; //the tapped button tag

UIViewController *viewController = [[NSClassFromString(viewControllerName) alloc] initWithNibName:viewControllerName bundle:nil];

if ([sender tag] == 3) {
    TheNames *namesVC = (TheNames*)viewController;
    namesVC.managedObjectContext = contexto;
}
gerry3
Humm, seems that I need to back to some fundamentals of Objective C. Great to see it! Thanks Gerry!
Daniel Bonates
+1  A: 

You do not need to know the subclass at all. Because Objective-C is a dynamic language and messages are resolved at runtime, you can send the message without having to know anything about the subclass at all.

First I would refer to the subclass as an id (instead of UIViewController) and as long as you have its header imported you can call [viewController setManagedObjectContext:contexto] directly.

However if you don't want to or can't import the header then just use KVC as follows:

[viewController setValue:contexto forKey:@"managedObjectContext"];
Marcus S. Zarra
Good point. I have reworded my answer. I would probably argue that one should use specific classes when possible for clarity and help from the compiler, but that's just my opinion.
gerry3
Casting is generally unnecessary in Objective-C and it is a habit many form when coming from other strongly typed languages. The entire point of having an `id` is to be able to send it any message and allow the resolution to occur at runtime. This is at the heart of Objective-C and what allows binds, etc. to work. Getting to know and getting comfortable with KVC/KVO is a requirement to being an Objective-C developer. Without that knowledge you are just writing [Java|C#] with funny brackets.
Marcus S. Zarra
Thanks Gerry and Marcus, very helpfull and cleared my mind about my case. It was great, and I've learned much more than I could ever expected. You guys were great, and it pushed me more into objective C and I call it now as a passion! Thanks a lot!
Daniel Bonates
A: 

I would keep MOC in my app delegate instead of assigning it down to every of my viewControllers:

And in my viewController .m file:

#import "MyAppDelegate.h" // Assuming you have a property called managedObjectContext in your MyAppDelegate

@interface MyViewController (PrivateMethgods)
@property (nonatomic, readonly) NSManagedObjectContext * managedObjectContext;
@end

@implementation MyViewController
@dynamic managedObjectContext

- (NSManagedObjectContext *)managedObjectContext {
    MyAppDelegate *appDelegate = (MyAppDelegate *)[UIApplication sharedApplication].delegate;
    return appDelegate.managedObjectContext;
}

So I can use it in my viewController like this:

if ([self.managedObjectContext hasChanges]) {
    ...
}
digdog
This is a *very* fragile design. The recommended pattern is to pass down the `NSManagedObjectContext`, the `NSManagedObject` and/or the `NSFetchedResultsController` to the UIViewController. The promotes reuse and allows for the application flow to be re-arranged much easier.
Marcus S. Zarra
I've thouth about this aproach, although I heard that Its not recomended like Marcus said. Anyway, as I was living in a nightmare whith this problem, this would be my way to go, but now Im studing the possibilities, thanks for your help!
Daniel Bonates