Call child class method from instance of parent class - ios

I have about 8 view controllers in my app, and i have a function in each one that does the exact same thing. I was hoping to be able to condense it into one central function that can perform the task for all 8. The function would need to receive an instance of itself so that it could perform the task on the appropriate view controller, but since i have no idea which one is being passed i set the instance type as UIViewController *. That way, i'd be able to receive any of the view controllers. The problem is i have to execute a method from this method, and since each method is custom to those child classes to UIViewController and im PASSING UIViewController, i can't access the functions from the instance. Is there some way to do this? Access a child class method from an instance of the parent class? Here's some code:
- (void)changeIsFullscreen:(UIViewController *)viewController { // <-- Right here is the
// ^^^ instance of the class that's passed to the function. I
// can't pass the child because there are so many different
// children that will be using it.
if (isFullscreen == NO) {
[viewController setIsFullscreen:YES]; // Right here is the child
// class method that i need to call.
// They all have the method, and if they
// don't i could use try/catch blocks to
// catch the error if there was some way to do it.
} else {
[viewController setIsFullscreen:NO]; // Right here is the child
// class method that i need to call
}
}
I know one way to do this would be to extend UIViewController, create the method in THAT class, and extend all the other child view controllers from the new class i just extended. I don't know if that is the correct way to accomplish this task, though. Is it? Or should I do it another way?

I may be missing something obvious here, but if all of your view controller subclasses implement this method, it sounds like they should all derive from some intermediate class. So, you'd have a class that derives from UIViewController and implements -changeIsFiullscreen, and all of your view controllers are derived from that class.

Related

Calling functions from separate view controllers in swift

I think the solution to this is going to need to use delegation, but I'm unfamiliar with how to use them.
So in my project, I have my main viewcontroller/storyboard that contains a UIScrollView. That UIScrollview calls another storyboard (xib file) as a subview. The other storyboard (which is an xib file) is controlled with another swift file.
My question is, when I call an action inside of my other storyboard, how can I call a function from the main viewcontroller. Like say the viewdidload from the first viewcontroller.
I can't make the whole thing a global function, it needs to stay inside its class. So if I try to do ViewController.viewDidLoad() it needs (I think) an instance variable or something.
Thanks.
You can try:
Using weak variable (property) in the other class with type UIViewController
Assign the parent view controller to that property after the other view is initialized
Good reads about weak, strong, unowned references Here And Here
Firstly, if you want to call it with class name as you said above declare your method with "class". So its just like static in Java. It makes it generic to call it anywhere in your project. Make a separate extension.
class func myfunc(){
}
if you want to send data from B to A controller. You use what is called delegation. You give the work of B to A. Make a protocol above B for functions that you want to do or send with them. Call them in B. And then in A write code for those functions. So that you have the data from B to A
Else you demand something like common data. Create a singleton class and initialize properties methods there. You can use objects for that and call it in other controller to modify or make different instances.
You dont call viewDidLoad(). As the name says it loads once. If you want something that modify everytime you screen appears, use viewWillAppear

Not able to get the video if the stream is created first in OPENTOK

I am basically trying to implement a video conference functionality using opentok.
I have two view controllers.
Class A that has a grey image(to tell user is offline).
It calls setsession from class B to establish the session.
uses ClassADelegate and implements setUserOnlineImage that sets the class A grey image to green.
Class B holds a method useronline.
Has a class method sharedinstance that gives out the singleton instance of the class
viewdidload ->sets a variable type = 2;
setsession ->sets a variable type = 1;
It also has a protocol "ClassADelegate"
Protocol ClassADelegate has method setUserOnlineImage.
Has a callback method session:streamCreated: that is called when a subscriber is created and setupPublisher that publishes the video
The flow is like this.
first Class A calls the setsession from Class B to establish session.
Then when a connect button is clicked the viewdidload is called and then the setupPublisher is called, view is modified loaded and all that.
Now when a subscriber tries to connect session:streamCreated: is called. here when i try to print type value it comes as one, likewise many other variables also become nil which inturn results in just giving the audio and the video isnt seen.
where as if first session:streamCreated: is called (first video is received and then connect is clicked) the flow works fine and the print statement in session:streamCreated: correctly prints type value as 2.
Someone help me figure out whats happening.
I want to know why the type value is getting changed & various other variables become nil. This is preventing the video from showing. Am i missing something? Is any other instance is been taken(but I am using a singleton instance)?
The flow you describe doesn't follow any of the known patterns of how UIViewControllers should behave. Specifically, you shouldn't need to use a singleton instance of a view controller. I think you need to reconsider the architecture, specifically the relationship between these two view controllers.
By the way, the viewDidLoad method is called on the view controller as soon as its view property becomes available, which can be before its on the screen. If the view controller is loading its view from a storyboard or nib, viewDidLoad is called as soon as that view is ready. Otherwise if you are implementing loadView, viewDidLoad is called after that method is finished.
Can you describe what Class A and Class B are trying to accomplish? It sounds like Class A is a view controller for some type of status view that shows a user's online/offline status. Class B sounds like its the OTSessionDelegate as well as the view controller for where the publisher/subscriber views will be placed. Why are these not the same View Controller? (generally view controllers are meant to control a "screenful" of content, unless you are using View Controller Containment). If these two view controllers are not on the screen at the same time, can you use a segue to pass data between them when the transition occurs?
UPDATE:
The additional information is useful for me to give you a recommendation. The thing I'm still uncertain about is if you actually do have these 2 view controllers' views on screen at the same time. This solution should work in both cases.
Outside of a segue, one view controller should not really be calling another view controller's methods directly (so calling setsession as you described is a bad idea). You shouldn't even set one as the delegate of another. At most they should share a Model object to communicate. The OTSession can be seen as a Model object. The challenging limitation is that when using the delegation pattern, only one object (you chose Class B) can be informed of updates. Rather than using the delegation pattern, I think you should use NSNotifications. In order to accomplish this, you should "wrap" the OTSession model in your own model object, setting your own model object as the delegate. Then you can notify both controllers of interesting changes as they happen. I've created a diagram to demonstrate:
In this diagram, all the downward solid arrows are owning references. VideoConference would be your own class and it would implement the OTSessionDelegateProtocol. On initialization, the VideoConference instance would create and own an OTSession instance. When something happens that Class A or Class B need to know about (such as the remote user coming online), VideoConference can send an NSNotification, which both controllers can be observers. Here is a useful article about NSNotifications.

can I delete / remove a class instance programmatically in Swift

I have thousands of lines of chained animations code. I have moved it all to a GraphicsHelper class with references back to the data in my ViewController. Once I am through with the code I would like to jettison the class instance on the theory that I can keep memory (and my view controller code) small. The view controller stays in scope during the whole app which runs through several "phases". Is there a way to programmatically disconnect the class instance of the helper class? I have tried to assign nil but I get an error that the class does not conform to NilLiteralConverter protocol. Any way to disconnect the instance or an alternative to my perceived voluminous code problem? Thank you all in advance. Am I the only one in the world that wants to do something like this?
You need to declare the instance variable of your class as an optional,
class ViewController: UIViewController {
var helper: GraphicsHelper!
override func viewDidLoad() {
super.viewDidLoad()
helper = GraphicsHelper()
// some time later
helper = nil // no errors on this line, GraphicsHelper deinit called
}
}

Call a method across classes

I have two view's in my app. In the first view I have a table view which displays data downloaded from the Internet. The FirstViewController has a method to get the data and update the view:
- (void)viewDidLoad
{
// Create PlanGenerator
_planGenerator = [[PlanGenerator alloc] init]
[self loadPlan];
- (void)loadPlan
{
_plan = [_planGenerator getData]
// Updating the view
// Updating the table view
[self.tableView reloadData]
}
To download the data from the internet I have a class called PlanGenerator. This class has an instance method called getData, it returns an NSArray. The table view uses the instance variable _plan (array) to display data in the table view.
In the second view (controlled by the SecondViewController) you can make some adjustments on what to download. To tell these change the PlanGenerator I used the concept of class properties. Now when I changed something in the second view (actually it's just one parameter) I want to call the method loadPlan from the FirstViewController.
My first thought was to create a class method, but then I would have to creat "class properties" for every variable the method uses.
Is there an easier way to do this?
You are missing some basics.
Try this design, assuming that FirstVC is used to display data and has tableview. SecondVC (your PlanGenerator) is used to get/download data.
In SecondVC:
Create whatever property(parameter, etc. says criteria) that FirstVC will supply to decide what to download.
Create a public method getData.
In FirstVC:
Create an iVar (says _myPlanGeneartor) and allocate it.
Now from the instance of FirstVC, you have access to an instance of SecondVC (_myPlanGenerator). With that you can supply criteria parameter and request data (getData).

Best design/pattern to use for first-use tutorial in app?

The background:
I have an app with 5 tabs. The first time a user navigates to each tab, I would like to show a one-time "tutorial". I intend to do this by creating a "TutorialViewController" that will handle displaying these "tutorial" views and will have buttons for next/back etc...
The problem:
I'm not sure the best pattern to use for implementing the logic for whether or not to show these screens and instantiating the "TutorialViewController" to display them. The goal is to have a single line of code (a single method call) that would show the tutorial if necessary. I'm trying to avoid duplication of code across the 5 view controllers. The problem is where/how to implement this single method. As a class method on TutorialViewController? As a global C function?
Things I've considered:
1) Implementing a class method on TutorialViewController called "displayTutorialIfNecessary". In this case, each view controller that has a tutorial would call this class method from their "viewDidAppear" methods. This class method would check to see if the tutorial has already been shown, and if not, it would instantiate a TutorialViewController object to handle to display it. In this option, I guess I would have to pass in "self" from each calling view controller and the class method would use that to display the TutorialViewController.
2) Implementing a class method on TutorialViewController called "tutorialShouldBeDisplayedForScreen: ". In this option, each calling view controller would call this method, and if it returns true, each vc would instantiate and present the "TutorialViewController" which would handle displaying the tutorial.
I'm sure there is a "best practice" or a pattern that fits this scenario, but I'm not sure what the best implementation is. Thanks in advance for your recommendations.
To summarize: Instead of having something like this in each view controller:
if ([TutorialViewController shouldDisplayTutorialForScreen:<someEnum>])
{
TutorialViewController *myTutorialVC = [[TutorialViewController alloc] init];
[self displayModalViewController: myTutorialVC];
}
I'd like something more like this:
[FirstUseViewController displayTutorialIfNecessaryForScreen: <someEnum> forParentViewController: self];
store the tutorial has shown state into NSUserDefaults and use factory method design pattern to let each UIViewController you'll need create and return tutorial UIViewController like:
- (UIViewController *)tutorialVC {
return [[MYHomeScreenTutorialVC alloc] init];
}

Resources