Attempt to present <xViewcontroller> whose view is not in the window hierarchy - iphone

I am using the option to play some media, if I link it to an IBAction on ViewController.h it will play fine.
The problem occurs, when I try to call that, from another ViewController, for example;
ViewController *myViewController = [[ViewController alloc] init];
[myViewController showVideos];
This is called from SecondViewController and refers to the code in ViewController.m
-(void)showVideos {
[[ApplifierImpact sharedInstance] showImpact];
}
It works using it if I am viewing it on the ViewController, but the call using the
-(void)showVideos {
[[ApplifierImpact sharedInstance] showImpact];
}
Throws the error about window hierarchy when calling it from the SecondViewController.m file
Now, in the SecondViewController.h file, the only reference to ViewController, is a simple import of the .h file, should I be initialising it or giving it a property in there also?

This: ViewController *myViewController = [[ViewController alloc] init]; creates a new ViewController object. You then don't present it (i.e. don't give it access to the screen) but you ask it to showVideos.
I suspect what you really want is to get a reference to an existing ViewController. When you create your SecondViewController give it a reference to the first one to act as a delegate.

Related

Passing data between view controllers ios 7

I'm working on an app and I need to pass data between view controllers. I know this is a common question but I couldn't find an answer for my problem : I'm able to pass data from the FirstViewController (MasterViewController in my case) to the SecondViewController (SettingsViewController) but not the reverse. What happens is that I call a method from the FirstViewController in my SecondViewController.m file. This works and it logs the data. But when I quit the SecondViewController (using [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];) the data is reset.
I tried using other methods to pass data but it didn't work. I'm using this code to pass data:
MasterViewController *vc = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[vc setPorts:SelectedPorts];
I also tried replacing [vc setPorts:SelectedPorts]; with vc.selectedCellIndexes = SelectedPorts; but the same problem occurs.
the setPorts method is declared in the FirstViewController.h file and SelectedPorts is a variable I declared in SecondViewController.m (it's not nil I checked).
Here's the setPorts: in FirstViewController.m :
- (void) setPorts:(id)selectedPorts {
selectedCellIndexes = selectedPorts;
NSLog(#"selectedCellIndexes : %#", selectedCellIndexes);
}
This logs the good value but when I log it in viewWillAppear in FirstViewController.m it's reset to the value it has before I called the method from SecondViewController.m.
Just to clarify, if I DON'T quit the SecondViewController.m, the data isn't reset.
I did read all your comments, and I really thanks you for your help. for convenience, I used a global variable.
Thanks for your help.
You have a list of ports in MasterViewController and you expect to use it in the SettingsViewController.
The MasterViewController can hold this list and SettingsViewController should have an access to it.
In SettingsViewController, have a setSelectedPort method:
#property (nonatomic, retain) id selectedPorts
- (void) setPorts:(id)selectedPorts;
The method saves the selected ports list into a property.
In MasterViewController, call the SettingsViewController and give it the list.
SettingsViewController *vc = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
[vc setSelectedPorts:yourValue];
When the list is modified inside the SettingsViewController, the list of ports contained in MasterViewController won't move even if you leave the SettingsViewController.
In secondViewController, You create protocol
#import <UIKit/UIKit.h>
#protocol sampleDelegate <NSObject>
- (void)passValue:(id)selectedPorts
#end
#interface SecondViewController : UIViewController
#property (nonatomic, strong) id <sampleDelegate> passDelegate;
#end
In viewDidLoad or wherever method as per your need, call method like this,
[self.passDelegate passValue:selectedPorts];
In FirstViewController.h,
Import the delegate <sampleDelegate>,
#import "SecondViewController.h"
#interface FirstViewController : UIViewController<SampleDelegate>
#end
In FirstViewController.m,
-(void)passValue:(id)selectedPorts
{
id receivedValues = selectedPorts;
}
and set self in your SecondViewController allocation,
SecondViewController *vc = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
vc.passDelegate = self;
There is nothing unusual in the getting result. By doing
MasterViewController *vc = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[vc setPorts:SelectedPorts];
You are creating a new instance of MasterViewController from your SecondViewController. This is not the same from which you navigated to the SecondViewController. So you wont get the expected result. Since you are setting the ports([vc setPorts:SelectedPorts]) to the newly created instance of the Master.
Instead of creating a new instance,just hold the reference of the MasterViewController in SecondViewController in a property and assign it before moving to second VC. As a beginner I suggested this way. But using delegate is the prefferred way passing data back.
Either use delegate methods to communicate with the master VC from the modal VC, or you could do something like this if you want to retrieive some manipulated objects from the modal VC.
Set the object(s) as properties in the modal view controller's .h-file (so they are public).
Using unwind segues, in the master VC, just do this:
-(IBAction)exitModalVC:(UIStoryboardSegue*)segue
{
SomeObject *obj = ((YourModalVC*)segue.sourceViewController).someObject;
//Do what you want with obj
}
EDIT:
This will only work if you are using unwind segue (which is a neat way of dismissing modal VC when using story board)
And you are using this, which is not unwind segues:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
You were creating a new instance of the first view controller from the 2nd view controller not accessing the same instance of the original caller. That was the reason why while you could see the logs but data were not there when you got back to the original caller - your MasterViewController.
You need to use delegate method. Check my answer for this SO.
This is problem related to object ownership.
Follow the below steps:
As per understanding you want reverse value from "SecondViewController" to "FirstViewController"
Don't create new object of FirstViewController in SecondViewController, it will not work.
Create object of "FirstViewController" in "SecondViewController.h" file.
#property (nonatomic,strong) FirstViewController *firstViewController;
When you navigate from FirstViewController to SecondViewController, please pass the "self".
e.g. SecondViewController *vc = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
vc.firstViewController = self;
If you want pass the reverse value to FirstViewController then in SecondViewController.m file.
[self.firstViewController setPorts:SelectedPorts];
And in FirstViewController.m refresh your controls with latest values.
Try above code will defiantly work as per your requirement.

Can't access ViewController from AppDelegate

I tried to save or load some data when my app is terminating. In my ViewController.m I made 2 functions, one for saving and one for loading.
In my AppDelegate.m I tried to access my ViewController, but it doesn't seem to work..
I tried a couple of different ways that I found here on stack overflow, but the Delegate doesn't recognize it as a ViewController or something:
[self.ViewController myFunction];
[self.rootViewController myFunction];
[self.window.ViewController myFunction];
They all don't work. What am I doing wrong? Am I using the wrong name for the ViewController?
I'm using storyboards by the way.. Is the accessing method different here?
First You need to do initialization of object of your self.viewController such like
self.ViewController = [[ActualNameOfViewController alloc] init];
And then call method such like
[self.ViewController myFunction];
Might be this is helpful :)
First you need to make sure that ViewController is imported than do alloc and init
////#import "ViewController.h"
ViewController *MyVc = [[ViewController alloc]init];
[MyVc myFunction];
Import your UIViewController class in AppDelegate.m class :
#import SampleViewController.h
after that create an instance of UIViewController:
self.sampleViewController = [[SampleViewController alloc]
initWithNibName:#"SampleViewController"
bundle:nil];
[self.sampleViewController myFunction];
SampleViewController is xib name for that UIViewController.

Objective-c / xcode - Access button state in different class

So I tried this in many different ways but I can't get it to work. Im trying to change the state of a UIbutton in a different class.
class1.h
#property (strong, nonatomic) IBOutlet UIButton *monthly;
class2.m
- (void)viewDidLoad
{
ViewController *vc = [[ViewController alloc] init];
vc.monthly.enabled = NO;
}
Whatever I try and where ever I put the code, the button state is not changing. When I log the state in class2.m:
NSLog(vc.monthly.enabled ? #"Yes" : #"No");
It always returns No, even if I just stated it as YES in my class2.m. Long story short: My button property is not updating from a different class. Please tell me if you need to see any more code and i'll update asap.
i think problem is with class instance. the following line create new instance
ViewController *vc = [[ViewController alloc] init];
that's why your button state is not changing you have to get reference of your previously created intstace no need to create new instance.
for this you can use AppDelegate file to declare property of class1.
see following code
AppDelegate.h
#Property(nonatomic, ratain) ViewController *vc;
AppDelegate.m
#synthesize vc;
now alloc & initialize vc whenever you need it like following.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication
sharedApplication] delegate];
appDelegate.vc=[[ViewController alloc] init];
also don't forgot to import AppDelegate.h file where you write above code.
now using appDelegate.vc you can use all property of View Controller in all classes of you project.
The main problem is you are creating new instance each time when you are going to check the button state. But the button state is for the button which you have created in class1.h. So you have need that you should create button in Appdelegate class and fetch the instance from Appdelegate in the class where you are checking the status of button and check the status of button. I think it will help.
Access the button using the object of the ViewController class that is already in the stack. No need to creat a new object like ViewController *vc = [[ViewController alloc] init];. When you are doing this it creates a new object so you are not getting the write thing.

iPhone OBJ-C: Sharing a MutableArray and moving between two ViewControllers

Classes:
AppDelegate
AppViewController
OtherViewController
Currently the application opens in the AppViewController. I want to add a new view, the OtherViewController. However I want the a method in the AppViewController to save to a MutableArray that the OtherViewController can use to show information.
1- Where should I create the MutableArray, in the AppDelegate? And how do I then access it?
I would like the ability to swipe a object on the AppViewController to get the OtherViewController to slide on, and I would just use a back button on the OtherViewController to go back.
2- How can I switch between the Controllers?
Thanks for the help!
Create a NSMutableArray in otherViewController (say otherArray)...
Dont forget to set property for that Array.. Because it is used as getters and setters for that Object..In our case we need set the value for that Array object..
When you move from AppViewController you will present the viewcontroller as..
OtherViewController *obj=[[OtherViewController alloc] initWithNibName:#"OtherViewController" bundle:nil];
//Here
obj.otherArray = yourArrayInAppViewController;
[self presentModalViewController:obj animated:YES];
[obj release];
Just NSLog otherArray count in your ViewDidLoad of OtherViewController.. You can see the Array has been passed...

error: expected expression before 'createCharacter'

so i am using presentmodalviewcontroller to change the active views in an ipad app. however when i try to change it using the statement [self presentModalViewController:createCharacter animated:NO]; in an ibaction that is triggered by a button. however i get an error saying expected expression before 'createCharacter'. createCharacter is a custom view controller that i have created... does anyone know what i am doing wrong? if you need any more relevant code just let me know,thanks
additional relevant code:
#import "createCharacter.h";
-(IBAction) buildCharacter{
[self presentModalViewController:createCharacter animated:NO];
}
createCharacter.h :
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface createCharacter : UIViewController {
IBOutlet UIView *view;
}
#end
I'd love to see some code to look at, and without it maybe this advice will be wrong, BUT...in my experience I've always used IBActions with a single argument, and that argument has always been the sender, so something like tying a button press to `
-(IBAction) presentNewController:(id)sender`
where sender is the button that was pressed.
If you use a method like that to detect the button press from IB, then in code what you would want is something like:
// In your current view controller, the target where you wired up the button
-(IBAction) presentNewController:(id)sender
{
if([sender isEqual:<whatever button you expect>])
{
CustomController *con = [[[CustomController alloc] init] autorelease];
[selfpresentModalViewController:con animated:YES];
}
}
You need to allocate and initialise createCharacter before you can push it into the view.
Assuming createCharacter is a view controller:
createCharacter *customView = [[createCharacter alloc] initWithNibName:yourNibNameORnil bundle:yourBundleNameORnil];
[self presentModalViewController:customView animated:YES];
[customView release];
It appears that you are sending a class to presentModalViewController:animated:. You need to initialize the class as Rog showed. As for MahatmaManic's answer, I have no idea why that was getting rid of your error. He is correct for OS X, but the argument is not required for iOS.
There are a few reasons you could still be getting the error after following Rog's example:
You have a variable named createCharacter, which means it was already initialized. In this case, change the name of your class to CreateCharacter. Classes are usually capitalized, and this would ensure that it is not confused with a variable.
The createCharacter header file is not properly imported. If you change the name of the file in XCode, it does not actually change the name of the file. If you try importing the file using the new name, it will not work.
Your initialization code wasn't right. In Rog's example, he used the default argument names. You should change yourNibNameORnil to the name of your NIB file, or nil if you are not using a NIB. You should also change yourBundleNameORnil to nil, assuming the NIB is located in your application's bundle. Here is an example assuming the NIB is in the application and named createCharacter.xib:
createCharacter *customView = [[createCharacter alloc] initWithNibName:#"createCharacter" bundle:nil];