How to set a view's outlets' values from within another class - swift

In xcode, If we have a view controller that has some subviews' (eg: label) outlets, and we want to change its text from the AppDelegate.swift class whenever an app is becoming active after suspended, How can this be done? I have tried making an instance of this view controller class from the AppDelegate class, but that didn't work because it made another view instance instead of the view itself, and we can't set the outlet as static. I have also thought of making a static ViewController property observer, but since it is static I still can't set the outlet from inside it. So, how can we do such a thing?

The best way to achieve what you want - is notifications. In your view controller add observer which will change your label's text or whatever. From AppDelegate method post notification. If you need an example, I can help you.

If we have a view controller that has some subviews' (eg: label) outlets, and we want to change its text from the AppDelegate.swift class whenever an app is becoming active after suspended, How can this be done?
Don't. Never speak directly to another class's outlets. Give that class a method that you can call where that class will respond to the calling of that method by speaking to its own outlet.
I have tried making an instance of this view controller class from the AppDelegate class, but that didn't work because it made another view instance
Correct. You need to get a reference to the existing instance of the other class. To do that, you need to know your own view controller hierarchy / structure or else provide one class with a delegate / reference to the other class at the time of creation.

Related

Is it okay to define a custom view using Storyboard / NSViewController instead of XIB file

I always find it a little bit annoying (for lack of a better word) to define a custom NSView in a XIB file.
I have switched to using a custom Storyboard (one per class) and a corresponding NSViewController. When adding the view to my hierarchy I am simply using code that looks like this:
let viewController: CustomViewController = // Use my custom extensions to instantiate the NSViewController subclass.
self.view.addSubview(viewController.view)
Are there any drawbacks? Is it okay to use this approach or could there be any downsides (maybe a NSViewController instance receives additional events or is somehow added to another hierarchy by default).
As a general rule, a view controller in a Storyboard is backed by code in its controller class.
.instantiateViewController(...) is then used to load a view controller from a Storyboard and:
push it
present it
add it as a child view controller, most often followed by adding its view to the current hierarchy
If you do have code backing that view controller, and you haven't added it as a child or assigned it to a class var/property, then the controller code will no longer exist as soon as viewController goes out of scope. If you've connected any UI elements to that controller class, or you need to call any funcs in that class, you'll run into problems.
However, assuming you do not have any code associated with that VC, then it's really functionally equivalent to designing the view in a XIB and instantiating it with from the resulting Nib.

iOS & Swift: ViewController class is defined, but when is it created as an object?

Learning Swift as my first new language in many years, I've come across something I'm curious about using Xcode and creating a new iOS project using the single view template.
In the default ViewController.swift file, UIkit is imported, and then the class ViewController is defined, inheriting from UIViewController. But I can't seem to find out where or how this class is ever created or initialized as an object.
Default ViewController.swift example
If I define my own class, or even want to create another view controller, I must first initialize it as an object somewhere in order to use it. So where is this default ViewController getting made?
Thanks for any help you can offer for me to try to conceptualize this!
Open your "Main.storyboard" file. Make sure View Controller is selected on the left sidebar:
Then on the right sidebar you can see that your ViewController class is in the class field:
So, when your app is loaded, the default storyboard is loaded, and that storyboard is responsible for creating an instance of the ViewController class and set it up for you. To test this out, you could create a new class, say ViewController2 and make it inherit from UIViewController. ViewController2 would then be available in the right sidebar:
And then your ViewController2 code will be used instead of ViewController.
You have changed the location of the ViewControllerQuestion.app file
I believe that the UIApplicationDelegate takes care of the creation of the initial view controller. You still can manually create view controllers as you mentioned and segue to them.
Normally you can create a view controller in a storyboard and use the Interface Builder to set up a segue to that view controller.
I hope this answers your question.

Using object from one class in another

I have a two UIViewControllers, on one of which I want a custom button to be displayed. I have written the code for this. I have also written the code for a popover segue to the other ViewController, and as both controllers belong to my 'ViewController' class, the button is also displayed on the second ViewController, which I do not want.
Obviously I can create another class and make my second ViewController a member of this class, however I want the code for my second ViewController to change the colour of the button in the first ViewController, so how can I use an object from my first class in the second class implementation file?
I have a two UIViewControllers, on one of which I want a custom button
to be displayed. I have written the code for this. I have also written
the code for a popover segue to the other ViewController, and as both
controllers are subclasses of my 'ViewController' class, the button is
also displayed on the second ViewController, which I do not want.
Why don't you make few property private in first cass so that it doesn't get inherited.
Obviously I can create another class and make my second ViewController
a member of this class, however I want the code for my second
ViewController to change the colour of the button in the first
ViewController, so how can I use an object from my first class in the
second class implementation file?
Your main problem is to access object of ClassA from ClassB.
Here are a lot of ways, and answers here, to do :
Update a label through button from different view
Xcode - update ViewController label text from different view
Setting label text in another class
Set label on another view to stored NSDate

Where is the best place for... [iPhone]

In UIViewControllers I have several methods such as viewDidLoad, viewWillAppear, viewDidAppear, etc.
The question is: "what is the best place to, for example, set the background color of my view, instantiate, and set the background color of a UILabel, or instantiate an object that I set as #property in my class and things like that? "
Thanks!
So many questions at once!
The first time the view is loaded, in viewDidLoad you will already have access to all the readily initialized UI elements, so it is a great place to configure the view and to set your class properties.
If you come back to the view if it is already loaded (say, by popping a view from a navigation controller, or dismissing a modal view controller), viewDidLoad will not be called. Thus, if you want to change something (background, add a label, change the background of a label, etc.) based on something that might have happened since the view controller was initialized, you have to use viewWillAppear.
You would use viewDidAppear if you want to animate a change so the user can see it after the view has already become visible.
Edit: this is pertinent for if you use IB or storyboard. See CitronEvanescent's answer for the case that you create your view in code.
The feasible method would be viewDidLoad or -(id)init,-(id)initWithNibName constructors of the class.
viewWillAppear and viewDidAppear should be avoided,since you would not like to instantiate your variables again and again since they get called every time the view appears(from pop or tabSwitch).These two methods can be useful in case you want to change some variable values on reappearance
If you are creating your view programaticaly, you can set your properties on - (void) loadView this method will be call once before anything is displayed.
Generally i prefer instantiating the UI elements in the -(id) init and update their UI in loadView.
For further details : View construction reference

How to embed a UIViewController's view from one xib inside a view in another xib?

MyViewController.xib has File's Owner class set to MyViewController (a subclass of UIViewController) and File's Owner view connected to a UIView containing some subviews.
OtherViewController.xib has File's Owner class set to UIViewController and File's Owner view connected to an empty UIView.
Is it possible in Interface Builder to embed MyViewController's view inside the view in OtherViewController.xib?
I tried adding an instance of MyViewController into OtherViewController.xib, but I can't drop it inside the view (because it's not a UIView) and I can't get to the view that was associated with MyViewController in MyViewController.xib (only the view controller itself, and nothing it's connected to, makes it over to OtherViewController.xib).
You probably do not want to do this. Follow the warning in the View Controller Programming Guide:
Note: If you want to divide a view hierarchy into multiple subareas and manage each one separately, use generic controller objects (custom objects descending from NSObject) instead of view controller objects to manage each subarea. Then use a single view controller object to manage the generic controller objects.
A UIViewController subclass whose view does not fill the window will not behave as you might expect. It will not receive view controller lifecycle messages, rotation messages, or have its parentView/navigation/tabBarController properties set correctly.
A UITableViewCell should not be the view for a UIViewController. It might have some controller object responsible for managing its behavior (though I suspect this behavior can probably all be contained within the cell view itself) but that controller should not inherit from UIViewController.
This has changed since some of the other answers were posted - you want to take a look at the latest documentation for UIViewController, particularly the guide section "Presenting View Controllers from Other View Controllers" and the class reference guide section "Implementing a Container View Controller". Also, there's a video from WWDC 2012 covering the topic on iTunes: Session 236 - The Evolution of View Controllers on iOS. (The video is very useful, it's not just a general overview.)
You can put it all in one xib. For example, just put it all in your MainWindow.xib.
This can be done programmaticly by adding a reference in OtherViewController to MyViewController. This is perhaps a bit messy and does in some way lead me to ask why you would want to do this but... I will trust that you know what you're doing.
Warning. Because 'Other' will contain a reference to 'My' you will want retain My inside Other. but Do not, I repeat do not retain 'Other' inside of 'My' this kind of cycle will lead to errors.
Good luck and don't forget to vote
ps if you have a little more detail I may be able to help you sort out a better design so that this sort of thing can be avoided :)