How to use a ViewController as a AppDelegate? - objective-c

I made a book for children. Every page is a ViewController. In the beginning, I did all the switching of the ViewControllers in the AppDelegate, but after having troubles with AutoRotation i did all the switching in another ViewController called ViewControllerSwitch.
Before, the code was like this. In the AppDelegate:
- (void)goToNextPage3 {
self.view3 = [[[ViewController3 alloc] init] autorelease];
view3.view.frame = CGRectMake(769, 0, 768, 1024);
[window addSubview:view3.view];
[UIView …SomeAnimationStuff...];  
[UIView setAnimationDidStopSelector:#selector(animationDidStop3:finished:context:)];
}
 - (void)animationDidStop3:(NSString *)animationID finished:(NSNumber *)finished context: (void *)context {
[self.view1a.view removeFromSuperview];
self.view1a = nil;
}
And here is the code from one of my view controllers ("pages") called ViewController1a:
- (void)buttonClicked {
MyBookAppDelegate* next2 =(MyBookAppDelegate *) [[UIApplication sharedApplication] delegate];
[next2 goToNextPage3];
}
This worked like a charm.
Now all my switching is in ViewControllerSwitch. How should I change the code in ViewController1a to access goToNextPage3?
I tried this:
- (void)buttonClicked {
ViewControllerSwitch* next2 = (ViewControllerSwitch *) [[UIApplication sharedApplication] delegate];
[next2 goToNextPage3];
}
It gives me a SIGABRT at [next2 goToNextPage3].
Any ideas?
Update:
i am still trying, so now i did this:
in my Viewcontroller1a.h:
#import <UIKit/UIKit.h>
#import "ViewControllerSwitch.h"
#class ViewController2;
#class ViewControllerSwitch;
#protocol ViewController1Delegate;
#interface ViewController1a : UIViewController
{
id<ViewController1aDelegate>myDelegate;
}
#property(nonatomic, assign)id<ViewController1Delegate>myDelegate;
#end
#protocol ViewController1Delegate
-(void)goToNextPageV;
#end
and in my .m file:
- (void)buttonClicked {
[self.myDelegate goToNextPageV];
}
i know there is something missing in the ViewControllerSwitch but i don´t know what.

As LordTwaroog said, this line is returning an object (your app delegate) of type MyBookAppDelegate:
[[UIApplication sharedApplication] delegate];
Then you're attempting to cast it to be an object of type ViewControllerSwitch with this:
(ViewControllerSwitch *)
This is incorrect. Your app delegate is an NSObject subclass conforming to the UIApplicationDelegate protocol. It's not a view controller.
The correct code might look like this:
- (void)buttonClicked {
ViewControllerSwitch* next2 = [ViewControllerSwitch alloc] initWithNibName:#"ViewControllerSwitch" bundle:nil]
[next2 goToNextPage3];
}
But depending on your app structure this might not be what you want. This is creating a brand new object of type ViewControllerSwitch. It's not returning the possibly-already-existing other ViewControllerSwitch object.
When you were using the app delegate to perform the switching, you had the benefit of being able to retrieve the existing app delegate object (rather than retrieving a newly created object of it's type). The app delegate is a singleton object, easily retrieved by calling [[UIApplication sharedApplication] delegate]. However, your ViewControllerSwitch object might not be set up as a singleton. So your access to it will depend on your object ownership structure. We'd have to see more of your code to help you with that.

[[UIApplication sharedApplication] delegate] still returns MyBookAppDelegate. Why do you try to get ViewControllerSwitch object out of it? You should use your ViewControllerSwitch object. Can you provide more code details on this object?
Possible solutions (if I understand you well):
Put your ViewControllerSwitch as an object in AppDelegate, so you could use:
ViewControllerSwitch *switch = [[[UIApplication sharedApplication] delegate] viewControllerSwitch]
Each ViewController can have a reference to your ViewControllerSwitch
Each ViewController should have a delegate with protocol (e.g.) ViewControllerDelegate, which will have a method to perform switching. Then after setting the delegate to appropriate object, you'll be able to switch your pages

Related

iOS Appdelegate field population and object creation

I am new to iOS and was trying to wrap my head around the functionality of Appdelegate callback's and field population.
So here's what I am doing:
declaring a global property in Appdelegate's header
#property NSString* GlobalUsername;
Populating the value to this property in one on of the callbacks
- (void)applicationDidBecomeActive:(UIApplication *)application {
_GlobalUsername = #"username";
}
Now in the ViewControler's button click method, I am creating an object of AppDelegate, accessing GlobalUsername and showing it on the screen using textView.
- (IBAction)ShowDetails:(id)sender
{
AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSString* details=[NSString stringWithFormat:#"Username is : %#",appdelegate.GlobalUsername];
[_textView setText:details];
}
Now what I don't understand is that how is the value of GlobalUsername is being associated with the object of AppDelegate. GlobalUsername was populated when application became active and not when I created an instance of the Appdelegate so how does the object returned by sharedApplication method still has this information encapsulated with it?
delegate of UIApplication works according to singleton pattern. There is only 1 instance every time you try to get it. For example:
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
...Any API requests...
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
If UIApplication's delegate will be different every time it won't save state of network indicator.

How to get the user's choice properly when the choice is too complex to use UIAlertView

I have been struggling with this problem for a while now, so any help would be greatly appreciated.
Here is the situation: My application has a UIViewController subclass called InitialViewController. This view controller has a UIButton, and when that button is pressed it creates a NSObject subclass called MyEngine. Something like this:
#interface InitialViewController : UIViewController <MyEngineDelegate>
...
#end
#implementation InitialViewController
...
-(IBAction)pressedButton:(id)sender {
MyEngine *engine = [[MyEngine alloc] init];
[engine start];
}
Inside start, I present a ViewController (ConflictViewController) modally to get the user's choice:
#interface MyEngine : NSObject <ConflictViewControllerDelegate>
...
-(void) start;
#end
#implementation MyEngine
...
-(void) start {
ConflictViewcontroller *cvc = [[ConflictViewController alloc] initWithNibName:#"ConflictViewController" bundle:nil];
cvc.modalPresentationStyle = UIModalPresentationFormSheet;
cvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
cvc.delegate = self;
UIWindow *window = [(MyAppDelegate *) [[UIApplication sharedApplication] delegate] window];
[[window rootViewController] presentModalViewController:cvc animated:YES];
}
#end
ConflictViewController is really simple. It just waits for the user to decide, and when the user press the button, it send the message to the delegate, and dismiss itself.
-(IBAction)didSelectConflict:(id)sender {
UISegmentedControl *seg = (UISegmentedControl*) sender;
[self.delegate didResolveConflictChoice:seg.selectedSegmentIndex];
[self dismissModalViewControllerAnimated:YES];
}
I've checked every connection, all the delegates are working properly.
What is going wrong is:
When MyEngine receives the user's choice in it's implementation of didSelectConflict: it cannot continue properly because all of it's properties have gone null.
When the MyEngine presents the ConflictViewController, the program continues the execution and when start finishes, it goes back to pressedButton: and when this method is closed, the MyEngine object gets released.
What i want to know is if there is way around this ? Has anyone done something like this in another way ?
The question here is: How to get the user's choice properly when the choice is too complex to use UIAlertView.
Sorry for the long question, I simplified it as much as I could. Thanks for your time, any links, comments, or any kind of help is greatly appreciated
Why are you initializing MyEngine *engine in the IBAction, if you wish to use a MyEngine object why don't you make a global declaration in your InitialViewController and just call [engine start] in the IBaction. Then when the delegate method returns the selected index you can apply that to a global int in your initial view controller and continue on your way. Hope that makes sense
Make your method start as
-(void) startWithDelegate:(id)del {
ConflictViewcontroller *cvc = [[ConflictViewController alloc] initWithNibName:#"ConflictViewController" bundle:nil];
cvc.modalPresentationStyle = UIModalPresentationFormSheet;
cvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
cvc.delegate = del;
UIWindow *window = [(MyAppDelegate *) [[UIApplication sharedApplication] delegate] window];
[[window rootViewController] presentModalViewController:cvc animated:YES];
}
and
-(IBAction)pressedButton:(id)sender {
MyEngine *engine = [[MyEngine alloc] init];
[engine startWithDelegate:self];
}
implement didResolveConflictChoice: in InitialViewController and get the delegate call there.
OR you can use UIActionSheet if suitable.

Understanding sample code for adding a row to a table view

I was reading the docs to learn how to add a row in a table view, and I found this example :
- (void)save:sender {
UITextField *textField = [(EditableTableViewTextField *)[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]] textField];
SimpleEditableListAppDelegate *controller = (SimpleEditableListAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *newItem = textField.text;
if (newItem != nil) {
[controller insertObject:newItem inListAtIndex:[controller countOfList]];
}
[self dismissModalViewControllerAnimated:YES];
}
I don't understand the method : insertObject:inListAtIndex: or what [[UIApplication sharedApplication] delegate]; stands for; are we putting the data in a plist file? Could someone explain this to me? The UIApplication docs do not really help.
[[UIApplication sharedApplication] delegate] is the main application delegate, typically this is a class named AppDelegate. The main application delegate is the one that is created on application start-up and which is the main controller for your application.
I'm going to assume that you're using something similar to this class as your AppDelegate class.
[controller insertObject:newItem inListAtIndex:[controller countOfList]];
This assumes that your AppDelegate class has a method named insertObject:inListAtIndex: on it. For the class I linked the method looks like this:
- (void)insertObject:(id)obj inListAtIndex:(NSUInteger)theIndex {
[list insertObject:obj atIndex:theIndex];
}
So in this case, that method is adding the object to a member variable of your AppDelegate class called List.
There is no connection to plist. Just message exchange with help of delegates to change table view.
From apple documentation:
When a table view enters editing mode and when users click an editing control, the table view sends a series of messages to its data source and delegate, but only if they implement these methods. These methods allow the data source and delegate to refine the appearance and behavior of rows in the table view; the messages also enable them to carry out the deletion or insertion operation.
Read this:
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/TableView_iPhone/ManageInsertDeleteRow/ManageInsertDeleteRow.html
And one of the best books - Beginning iphone 4 (or 5)

Problems with storyboard

recently I started using storyboard and I've the following situation: I want to set the text of an UILabel from the AppDelegate. So I created an instance of my ViewController
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
ViewController *controller = (ViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: #"mainViewController"];
myViewController = controller;
[window addSubview:myViewController.view];
[window makeKeyAndVisible];
and called the following method from the delegate
- (void) updateParameterLabel:(NSString *)parameter {
NSLog(#"URL-2: %#", parameter);
parameterLabel.text = parameter;
}
But the parameter is not shown in the UI.
Another think, which is kind of strage:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(#"View did Appear");
}
The "View did appear" is logged twice ...
Any hints?
Regards,
Sascha
Setting the text of a UILabel from your application delegate isn't great design. Your view controllers should be managing the content of your views, hence their name. Typically your storyboard is instantiated automatically, and you don't need any of the storyboardWithName et code you've got, assuming you're working with Apple's default templates.
Maybe think about re-architecting your application to follow the 'model-view-controller' pattern more strictly, and also look at how Apple instantiate storyboards automatically (just create a new storyboard project in XCode to see this).
If you still want to make it work, make the UILabel a property of your viewcontroller and set the label by using
In delegate :
- (void) updateParameterLabel:(NSString *)parameter {
NSLog(#"URL-2: %#", parameter);
[myViewController updateParemeter:parameter];
}
In myViewController:
- (void) updateParameterLabel:(NSString *)parameter {
NSLog(#"URL-2: %#", parameter);
parameterLabel.text = parameter;
[self.view setNeedsDisplay];//edit
}
So use the viewController to update your label. Of course you need the label as a property in your viewController
For what I see you are trying to update the label before it appears, so why don't you try calling your updateLabel method in the viewWillAppear, it would be something like this
-(void)viewWillAppear:(BOOL)animated{
[self updateParameterLabel:#"Some Text"];
[super viewWillAppear:YES];
}
And updateParameterLabel has to be implemented in the viewController.

Accessing textview on viewcontroller.xib from another class

I have a textview on my viewcontroller.xib and I have a method to modify the text. I want to access that textview method on viewcontroller.m from a created object. I have a class called person that has in the init method to call the viewcontroller's method to update the text. Basically I want the textview to say "Person Created".
Here is the code I use inside my -init method of the person class which does not work:
ViewController * Viewscreen = (ViewController *) [[UIApplication sharedApplication] delegate];
[Viewscreen UpdateScreenText:#"Person Created!"];
ViewController * Viewscreen = (ViewController *) [[UIApplication sharedApplication] delegate];
This looks very strange to me, is your App Delegate really named ViewController? Are you trying to access a property declared in your App Delegate called Viewscreen?
If so then you would want to use the following to get a reference to it
ViewController * Viewscreen = [(ViewController *) [[UIApplication sharedApplication] delegate] Viewscreen];
Please clarify some more and we may be able to better assist.