objective C Basic question - objective-c

i made a simple application using view based template.and i put only nslog inside view didload method in viewController file and also inside applicationDidFinishLaunch method (in appDelegate )to checked which class file called first.
after the run i got: viewController Run first and then appdelegate ..but i think appdelegate should first then other's called according to the need ... plz give me the proper reasion.
Noted that --i did not call viewController (didnot make object) in my appDelegate(inside application didFinishLaunch) . i am using ios4

If your View Controller is a property of the AppDelegate, similar to the code reference
#interface AppDelegate_Shared : NSObject <UIApplicationDelegate, UIAlertViewDelegate, OMFDataLoadDelegate> {
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
UIWindow *window;
UITabBarController *tabBarController;
}
then it is probably getting allocated by the AppDelegate when it is being allocated. According to the Apple documentation viewDidLoad is run after the view is loaded into memory, which can be a little confusing, since the language can make you believe it's when it's loaded onto the screen.
http://developer.apple.com/iphone/library/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW25
Move your NSLog statement to viewDidAppear for the result you were expecting. Here's two sample snippets with the way you should expect the statements to load.
ViewController.m
- (void) viewDidLoad {
NSLog(#"1st - this occurs when appDelegate allocates this object");
}
- (void) viewDidAppear {
NSLog(#"3rd - this should appear after the applicationDidFinishLaunchingStatement");
}
AppDelegate_Shared.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"2. Starting AppDelegate_Shared");
[window addSubview:self.tabBarController.view];
[window makeKeyAndVisible];
NSLog(#"4. Leaving AppDelegate_Shared");
return YES;
}

If the initial view hasn't loaded then clearly the application has not finished launching.
The messages are sent in the right order.

Related

UIViewController method from AppDelegate

This is my 1st question in stackoverflow.com.
I'm trying to call upon a method [- (void)alterTime] from ViewController.m in AppDelegate.m. Yes, I have #imported "ViewController.h" in AppDelegate.h. Importing the controller into AppDelegate.m makes no difference. Also, "Background fetch" is ON.
Here is the code inside AppDelegate.m that I'm trying to implement:
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
{
NSLog(#"Current Time Altered");
//Get current view controller
ViewController *mainViewController = (ViewController *)self.window.rootViewController;
[mainViewController alterTime];
//Cleanup
completionHandler(UIBackgroundFetchResultNewData);
}
This is the piece of code giving me problems:
[mainViewController alterTime];
It states: "No visible #interface for 'ViewController' declares the selector 'alterTime'".
So that error means that it failed to find the method name (selector), in the class ViewController.
Make sure in your ViewController header you have the alterTime method declared there, effectively making it public.
If that is okay, then double check to make sure that your rootViewController is of type (owned by) ViewController
Declare - (void)alterTime in your ViewController.h file.
#interface ViewController : UIViewController
- (void)alterTime;
#end

Navigating from one UITableView to another inside appDelegate

The first UITableView is presented inside a Popover that is called from the RootViewController of the application.
I need to navigate to another UITableView inside the same popover. This is easy to do if you just instance an object of the second UITableView and push it from the first one.
In the next paragraph I write as taking for granted some facts, please correct me if I'm wrong.
The problem here is that this process should be done inside the appDelegate. This is because I'm implementing Dropbox API and I need the pushViewController to be done immediately after the login process is done, which means the navigation through UITableViews has to be done inside of the application:handleOpenURL. I asume that application:handleOpenURL has to be called right there and that's why I also asume the pushViewController has to be done there in order to have the navigation done after the Dropbox API validation window is presented, without having to make the user do anything else.
This is how my code looks like:
AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate>{
UINavigationController *navigationController;
NSString *relinkUserId;
UIWindow *window;
TableViewControllerForStorageList *rootViewController;
ViewController *viewController;
}
#property (nonatomic, strong) IBOutlet UIWindow *window;
#property (nonatomic, strong) IBOutlet UINavigationController *navigationController;
#property (nonatomic, strong) IBOutlet TableViewControllerForStorageList *rootViewController;
#property (nonatomic, strong) IBOutlet ViewController *viewController;
AppDelegate.m
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
[(TableViewControllerForStorageList *)self.window.rootViewController PushView];
}
return YES;
}
return NO;
}
TableViewControllerForStorageList.h
-(void)PushView;
TableViewControllerForStorageLost.m
-(void)PushView
{
TableViewControllerIpadStorage *tableViewControllerIpadStorage = [[TableViewControllerIpadStorage alloc]initWithNibName:#"TableViewControllerIpadStorage" bundle:Nil];
[self.navigationController pushViewController:tableViewControllerIpadStorage animated:YES];
}
Off course I got sure that Application:HandleOpenURL is running, but when calling PushView from there the error is [ViewController PushView]: unrecognized selector sent to instance
So, how can make the navigation be done from there? Which basics about objective c am I missing?
It is not clear from your question how your app is structured, so this answer may not be the best solution for your problem but hopefully it gives you some idea of how your view controller hierarchy is likely built up from your app delegate.
Lets say your first view controller class is named FirstViewController. Either your app delegate has a direct reference to an instance of this view controller, or it can access it through a parent view controller (perhaps via window.rootViewController).
Now lets say you have a method in FirstViewController named pushNextViewController that performs the task of pushing the second table view controller.
You can call that method from within the application:handleOpenURL: method of your app delegate.
This might look something like:
[self.window.rootViewController.firstViewController pushNextViewController];
There are other ways you could get a reference to your instance of FirstViewController and it would be cleaner if your rootViewController was a custom subclass so your could create a pushNextViewController method there and from that method tell your FirstViewController instance to pushNextViewController:
[self.window.rootViewController pushNextViewController];
Note that in both examples above, you will need to cast the rootViewController to whatever class it is actually an instance of or the compiler will warn you that it does not have the property firstViewController (example 1) or the method pushNextViewController (example 2).
EDIT: If your rootViewController is a UINavigationController, then your code might look more like:
UINavigationController* navController = (UINavigationController*)window.rootViewController;
FirstViewController* vc = navController.viewControllers[0];
[vc pushNextViewController];
EDIT 2: OK, It looks like the confusion here is that the window object has a rootViewController property (which appears to be pointing to your navigationController) and then you also have a rootViewController instance variable in your app delegate. These are two different objects, making your naming convention a bit confusing, but if I am right then the following should work:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
[rootViewController PushView];
}
return YES;
}
return NO;
}
You should consider changing the name of your app delegate's reference to your TableViewControllerForStorageList to something other than rootViewController to alleviate some confusion.

creating a global NSMutableSet

In reference to the answer of this SO question: Keeping track of changes in a UIView
I need help setting up the global aspect of the NSMutableSet. In my appdelegate.h file I've got this:
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
ViewController *viewController;
NSMutableSet *statesTouched;
}
and this in my appdelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
statesTouched = [[NSMutableSet alloc]init];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
In my viewcontroller.h file I'm adding the object like this:
[statesTouched addObject:touchedStateName];
but I'm getting an undeclared identifier for statesTouched. I've never tried putting something like this into my app delegate and I'm a little confused at how this should be working. Thanks!
This is because is an instance variable of your AppDelegate, not your view controller. If you move the declaration and the initialization to your view controller, the error will go away. It would not make it a global variable, though, which is good if it works for you.
If it does not work for you, make the variable a truly global one: move the declaration out of the app delegate, and add extern keyword, like this:
extern NSMutableSet *statesTouched;
Now add the definition in the .m file, like this:
NSMutableSet *statesTouched;
Make sure the definition is outside the #implementation block.

How do I set a property of an object from another file in cocoa?

I'm coding an iPhone app.
Instead of writing all the code here, this is basicly what I want to do:
testViewController.m:
- (void)viewDidLoad { label.text=#"text"; }
This works.
Now I want to change the label text from the testAppDelegate file.
- (void)applicationDidBecomeActive:(UIApplication *)application {
testViewController *tvc=[[testViewController alloc] init];
tvc.label.text=#"another text";
[tvc release];
}
This isn't working!
How can I do this?
Thanks for all answers :)
In applicationDidBecomeActive you are creating a new instance of the view controller (this is what alloc / init) setting the label text in your new instance and then releasing it.
You need to be referring to the actual instance of your view controller that is on the screen. This is probably already referred to somewhere in your application delegate - is it the root view controller, for example? When is it created in the first place?
You may need to set a property on your application delegate to hold a reference to this view controller. The code you have is fine except that you are talking to a new controller instead of the one that is presented on the screen - assuming of course that your label is a property on the view controller.
In .h file: define property:
#property (nonatomic, retain) UILabel *label;
In .m file: implement set/get methods for that propery (for example, automatically):
#synthesize label;
Declare testViewController as outlet in testAppDelegate.h, perform its binding in xib, probably MainMenu.xib, now try changing value of its label in -
- (void)applicationDidBecomeActive:(UIApplication *)application
I'm sorry! Should have specified more what I was doing. Now I've learned.
I had a tab-bar view controller template.
I solved this by adding in the delegate .h file:
#class testViewController
#property(nonatomic,retain) UIViewController *testViewcontroller;
and in the .m file:
#synthesize testViewController=_tvc;
- (void)applicationDidBecomeActive:(UIApplication *)application
{
_tvc.label.text=#"another text";
}
And of course imported the testViewController.h and declearing the methods there too.
Thanks for all your responses :)

Error when ViewController is implementing UITextFieldDelegate

When implementing the UITextFieldDelegate in my ViewController class, the following error is thrown when entering the first character in the text field:
-[MyViewController respondsToSelector:]: message sent to deallocated instance...
So, I tried creating a separate class (inheriting only NSObject) and implementing UITextFieldDelegate. Guess what, it worked perfectly. However, that introduces some other problems as I have to do a lot of ugly cross-class-communication that I'd like to avoid. Here's the relevant parts of my app delegate code:
#interface RMSAppDelegate : NSObject <UIApplicationDelegate,
UITabBarControllerDelegate>
#property (nonatomic, retain) UIViewController* myViewController;
#end
#implementation MyAppDelegate
#synthesize myViewController;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myViewController = [[MyViewController alloc]
initWithNibName:#"MyView" bundle:nil];
[self.window setRootViewController:myViewController];
[self.window makeKeyAndVisible];
return YES;
}
#end
.. and here's what is being displayed:
#interface MyViewController : UIViewController <UITextFieldDelegate>
#property (nonatomic, retain) IBOutlet UITextField* pinTextField;
- (void)viewDidLoad;
#end
#implementation MyViewController
#synthesize pinTextField;
- (void)viewDidLoad {
// DOES NOT WORK (WHY?)
//[pinTextField setDelegate:self];
// WORKS, BUT I'D LIKE TO AVOID
[pinTextField setDelegate:[[[MyTextFieldDelegate alloc] init] autorelease];
[pinTextField becomeFirstResponder];
[super viewDidLoad];
}
#end
And please, if you see any code (even off topic) that I could be doing better, leave a comment.
Since you asked for off-topic code comments: You forget to call [super viewDidLoad]. You also don't need to redeclare the prototype in order to override it. And the #synthesize textFieldDelegate is not valid, as you have no property in the class named textFieldDelegate. And your dealloc method is releasing an ivar named tfd which doesn't seem to actually exist in the class.
Your real problem is that you are not properly retaining the view controller at whatever point you allocate it. It may be that the view controller is being instantiated in a nib and associated with an ivar rather than a property declared retain, or is not being associated with anything. Or it could be that you are allocating it in code, adding its view as a subview of something, and then releasing it without ever retaining the view controller itself. Or it could just be that you are just releasing it when you shouldn't.
Your other class works specifically because you are leaking the object, so it never gets deallocated. The better solution, were you to go with this method, would be to store the object in an ivar when you allocate it and then release it (and set the ivar to nil) in both dealloc and viewDidUnload.
Okay, I finally solved this on my own. I have not changed the code. My NIB (.xib) was the culprit!
I thought that nested UIViewControllers was OK, and I still think they are in some cases (and maybe using another programmatic method). Anyway, I was initializing my class MyViewController with a NIB that in the Objects panel had a UIViewController as the first object.
I solved this by having the UIView as the first object in the Objects panel, and setting the File's Owner to be the UIViewController instead.
Correct code, incorrect NIB. Thank you for your help.