How can I access an instance of a view controller? - ios

My problem is:
I've created a project object. In this project object I need to call a method in a ViewController.
The method I need to call draws some objects in the ViewController principal view using a modified -
(void)drawRect:(CGRect)rect method.
The only thing I need to do is call this method on the actual instance (the instance that is created when the app starts) of the ViewController from a method in the project class.
The method created (to draw the objects) works. I tested it by calling it from the ViewDidLoad method of the ViewController. In the project method I tried for example this code:
-(void)drawProject {
UIStoryboard *mainStoryboard =[UIStoryboard storyboardWithName:#"Main" bundle:nil];
IYViewController *projectViewController = [[IYViewController alloc] init];
projectViewController = (IYViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"project"];
[projectViewController drawProject];
}
I named the principal, the target ViewController "project" in interface builder.
The problem is that anyway the ViewController instance that I create is not the instance of IYViewController that is displayed at runtime.
I didn't find any real good solution that works for me, so please help! Maybe the solution is create a delegate of a class but I didn't really understand that so please if this is the right solution help me code it!

Yes, the instance that you alloc and init is not the one that you load from the storybaoard. There is no need to alloc and init it. If you don't ARC then you even created a memory leak there.
-(void)drawProject {
UIStoryboard *mainStoryboard =[UIStoryboard storyboardWithName:#"Main" bundle:nil];
IYViewController *projectViewController;
projectViewController = (IYViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"project"];
[projectViewController drawProject];
}
Well, this will not solve the issue. (If comments could be formatted properly then I added a comment rather than an answer). Your real problem is somewhere else and I fear that you may not yet know how to explain it so that we understand it.
Give it a try. Explain in a bit more detail.
Are you sure that your drawProject is really executed? To which class belongs the drawProject Method that we are looking at?
What exactly do you do in drawRect.
Besides, drawRect is a method of a view, not a view controller. If you implemented that for a view controller then it may not be called at all.

Related

Can't initializing a delegate in the AppDelegate but inside a class method it works

I am trying to initialize a delegate (MyDelegate) in the AppDelegate inside the didFinishLaunchingWithOptions method as follows:
UIStoryboard *myStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
[[someClassName instance] setMyDelegate:[myStoryboard instantiateViewControllerWithIdentifier:#"someVcName"]];
While debugging, all the calls perform well but when it returns to the AppDelegate after the above calls, MyDelegate is nil.
What is interesting is that when I try to set the delegate inside a class method I wrote, it works - the exact same code above.
Why the initializing doesn't work in the AppDelegate while it works in the class method ?
Thanks.
EDIT:
Basically #Leo solved the problem but the solution was really straightforward since I was using Storyboard then the first ViewController is automatically initiated (assuming you assigned the entry point arrow icon):
The solution:
[[someClassName instance] setMyDelegate:[self.window rootViewController]];
About method instantiateViewControllerWithIdentifier
From the document
This method creates a new instance of the specified view controller each time you call it.
So,in didFinishLaunchingWithOptions,you create a local viewController instance.
And,it will be dealloced after the method is done.

Change/Modify Runtime User defined attribute before Instantiating ViewController

In short, I want to know "How to change Runtime User defined attributes before instantiating a View Controller"
Why I Need this
I am creating an application which uses multiple storyboards. I have a main storyboard with a UIViewController designated as LinkViewController. It has a string attribute, which tells it which storyboard has to be linked. now what I want to do is, I want to change that attribute at appDelegate & then instantiate the viewController. So far not able to do it.
This is what I am doing:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
EffLinkHomeVC *rootController = [storyboard instantiateViewControllerWithIdentifier:#"linkView"];
rootController.storyBoardName = #"wxyzForiPhone";
self.window.rootViewController = rootController;
I have found several other ways to work around. But I just want to know more clearly about altering "Runtime User defined attributes". Thank you all. :)
As far as I know you can only do this with proxy/external objects available in nibs.
Check the answer here to see a nice example of their usage.
By the looks of it this functionality is hidden or removed from storyboards. The only documented ways of configuring are static. In your case it would be statically configured with the properties from the storyboard you are using. If this suffices, you could use the key value mechanism to statically configure a different value for each storyboard.
Other than that you only have the normal post init viewController methods.

Do I have my Singleton Correctly setup? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What should my Objective-C singleton look like?
I am trying to understand the use of singletons. I have red to be careful with them, but also that they can have their positive uses.
My Scenario:
At the moment I have a test Project set up. One ViewController has a button that needs to perform an action.
The FirstViewController has a UIWebView on it.
I am using Storyboard and ContainerView, so I am able to see both ViewControllers at the same time.
In the First ViewController I have this code in my .m file:
static FirstViewController *sharedController = nil;
+ (FirstViewController *)sharedController {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
//BBCSermonTabBarViewController *myVC = (BBCSermonTabBarViewController *)[storyboard instantiateViewControllerWithIdentifier:#"BBCNews"];
if(sharedController == nil)
sharedController = (FirstViewController *)[storyboard instantiateViewControllerWithIdentifier:#"firstViewController"];
return sharedController;
}
And I also have a method that changes the alpha it like so:
-(void)hideWebView
{
_webView.alpha = 0.3;
}
Now in my Second View controller I have this code:
-(IBAction)hideWebViewFromAnotherViewController
{
[[FirstViewController sharedController] hideWebView];
}
Should that action button now change the alpha of the webView in the other ViewController?
if not what am I doing wrong??
Thanks in advance:-)
I can appreciate your goal to understand singletons better, but I would suggest not using a singleton unless you have to.
I don't think it is appropriate in most UI scenarios(I have never needed one) to have singletons. I suggest one of the following methods for communicating between objects:
Hold a reference to objects that you want to communicate with. Simply add a property and save a reference to the class that needs to be called later. You can make it a weak reference if it works in your scenario.
Use the delegate pattern that is common with iOS/Objective-c apps. Same as above, except define a protocol instead. Normally the property is called delegate. This allows other views to communicate using a common interface.
Use notification center. I don't prefer this option for most cases, but if there is an event that a lot of views might need to know about, and you don't want to deal with passing references to objects, it might be a good option.
Singletons work best for non-UI code in my experience, when you actually need to rely on the singleton behavior of instantiating the class upon first use. In your situation it looks like the only reason you're using a singleton is to make that view controller accessible across your entire app.
For safety's sake, and because with libdispatch it's so easy, you should protect the singleton creator with a dispatch_once() call instead of doing an if() check.
+ (FirstViewController *)sharedController {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
static dispatch_once_t token;
dispatch_once(&token, ^{
sharedController = (FirstViewController *)[storyboard instantiateViewControllerWithIdentifier:#"firstViewController"];
});
return sharedController;
}
The token is used like a semaphore to protect the block and make sure it only gets called once during the run of your program; it's protected from races and simultaneous reads.
It should work. Potential problems: _webView is nil, [FirstViewController sharedController] is not returning a valid reference. Set a breakpoint on hideWebViewFromAnotherViewController and step through, making sure everything is defined when you think it is.

viewController's dealloc don't be called when called navigationController popViewControllerAnimated

I have a MyViewController, it's based on UIViewController, and I used it like the following code:
MyViewController *nextViewController = [[MyViewController alloc] init];
[self.navigationController pushViewController:nextViewController animated:YES];
[nextViewController release];
And in the MyViewController, with a user event, have the following code:
[self.navigationController popViewControllerAnimated:YES];
Now, I find that, the MyViewController's dealloc don't be called, but, when I switch the App to background, for example, pass the home button, the dealloc method has been called! This a big problem! There will be got a lot of MyViewController wouldn't be release, when user go to a MyViewController, and go back, again and again, and just, the lots of memory could be release only when the App goto background.
So, can anyone help me about this, thanks!
The obvious reason is that something is retaining your viewController. You will have to look closely at your code. Do you do anything that in your class that uses delegates, since they sometimes retain the delegate. NSURLConnection will retain your class, and so does NSTimer. You can scatter code in you class and log your class's retain count, and try to find out where. In the code you showed so far the retain could should just be 1, since the class is only retained by the navigation controller.
Also, before you pop your view, get a reference to it, pop it with NO animation, and then send it some message that has it report the retain count (this would be some new method you write). That new method could also log other things, like whether it has any timers going, NSURLConnections, etc.

iOS storyboards instantiate viewController and IBAction

I may go mad very soon.
This is the reason:
- I started up with Single View Application project with storyboards. Then I set the view controller class name in the storyboard for my viewController.
- Next step I created one pointer for this viewController in AppDelegate method ...didFinishLaunchingWithOpt... and filled it up by calling [myStoryboards instantiate...]. It works pretty good because I can call method like [vc1 setMyName] which does smthng like self.myName = #"Johnny";
- But here it comes. When I create IBAction method joined with button, this method doesn't know anything about "Johhny". And this is because I'm in another instance. When I check the address of "self" it is another one...
WhyWhyWhy??? Please help, how can I use still the same object - the one instantiated in AppDelegate by storyboards and the one from storyboards in "interface builder".
Thank you.
Oh my. I think I really underestamated it...
When we were talking about getting pointer of other viewControllers from storyboard...
I have initialViewController got by calling rootViewContr... And another one connected with segue (modal) where is UITableView. A get data on rootViewController and I want to show them on the other one in the list (UITableView). So I call segue (performSegueWithIdentifier), the other controller is shown but the list is clear. Because the method I call is working with tableView variable which is null :/ Because, again, I'm in another object. That is because I call that method storyboard instantiate... How can I get exactly the same viewController which I'm working in storyboard with. It is quite confusing for me :/
I read something about prepareForSegue and getting the pointer by destinationViewController but that is not what exactly I want. I need the pointer before I call segue method and the viewController is shown...
Thank you.
If you've set up your initial view controller properly in the storyboard, you don't need to assign it to the windows rootViewController property in -applicationDidFinishLaunchingWithOptions: as this is done for you automatically. It sounds like you're creating a second instance. To access the original instance setup by the storyboard simply do this in -applicationDidFinishLaunchingWithOptions:
InitialViewController *viewController = (InitialViewController *)self.window.rootViewController;
viewController.myName = #"Johnny";

Resources