Can't call controller method from delegate - iphone

I'm trying to do something like this: http://www.pushplay.net/2009/05/framework-for-having-multiple-views-in-an-iphone-app/
So far I've got this structure: appDelegate -> rootViewController -> welcomeViewController
I've a method (doSomething) in my delegate, which is called by an IBAction in welcomeViewController. It works, I can do an NSlog in doSomething and it shows the method is being called within the delegate.
The problem is when I run a command like [rootViewController loadNewView] in my doSomething method (in the delegate), it does nothing. It doesn't error, it just does nothing.
I've been reading and seen protocols and notifications are suggested, but I'd like to know why this method using the delegate doesn't work and if there is any way to fix it.
SurveyClientAppDelegate.h
#interface SurveyClientAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
RootViewController *rootViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
-(void)doSomething;
#end
SurveyClientAppDelegate.m
- (void)doSomething {
NSLog(#"Attempt: rootViewController loadLocationList");
[rootViewController loadLocationList];
}
RootViewController.h
#interface RootViewController : UIViewController {
WelcomeViewController *welcomeView;
}
#property (nonatomic, retain) WelcomeViewController *welcomeView;
#property (nonatomic, retain) SurveyListViewController *surveyList;
-(void)loadLocationList;
RootViewController.m
- (void)loadLocationList
{
NSLog(#"RootViewController: loadLocationList");
}
WelcomeViewController.h
#interface WelcomeViewController : UIViewController
-(IBAction)viewList:(id)sender;
-(void)loadLocationList;
WelcomeViewController.m
- (void)viewList:(id)sender
{
SurveyClientAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate doSomething];
}

Are you keeping a reference to rootViewContoller in your welcomeViewController? It's possible (and likely) that rootViewController will be released before you can call methods on it.
This is a good time to use delegates. You mention calling a method "in the delegate" but without seeing any of your code it's difficult to tell if you're using it correctly or not.

Related

How to call nsobject class on a button in view controller

i am doing an apps which i need to call nsobject class in a view controller class, i try a couple method but its not working either i get a sigabrt error or the apps crash.
please help me.
I'm lost for days now.
any one have a sample code for calling nsobject from view controller?
thanks in advance for you kind help.
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
-(IBAction)firstButton;
#end
#import <UIKit/UIKit.h>
#interface TutoAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
UIButton *firstButton;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) IBOutlet UIButton *firstButton;
#end
Please post some code where we can provide the correct solution. Even I don't get problem exactly but if you want to call class object then do the following.
-(void)buttoevent:(id)sender
{
nsobjectclass *obj = [[nsobjectclass alloc]init];
//if you want to call any method of that class then do the following.
[obj methodname];
}
First of all check if you have imported the class before using it

how to add a login screen before existing ViewController in Xcode3

I need to add a screen to capture username and password before loading the first view of an app on an iPhone. The whole app is coded and working except for this (late) addition. This is my first app in Xcode so I am not very familiar with the system at all.
I have a LoginViewController set up, but don't know how to add it to the front of the app so that it loads first and then loads my RootViewController afterwards (I need the login details before loading the next view).
The header of my appdelegate is presently
#import <UIKit/UIKit.h>
#class RootViewController;
#interface Online_HW_DiaryAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
RootViewController *viewController;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) IBOutlet RootViewController *viewController;
#end
but I'm not sure what I need to modify - or indeed what else will need to be modified? Any advice gratefully appreciated.
I think the fastest path is this: In viewDidAppear of RootViewController, detect the login needed condition and present a new LoginVC modally.
// RootViewController.m
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (/* user must login */) {
LoginVC *newVC = [[LoginVC alloc] initWithNibName:.....];
[self presentModalViewController:newVC animated:YES];
} else {
// your old viewwillappear logic
}
}
The LoginVC, upon determining that the user has logged in successfully, can dismiss itself.
// LoginVC.m
- (void)loginFinished {
// after some asynch call that validated the user credentials
[self dismissModalViewControllerAnimated:YES];
}

Overridden properties from superclass

I have a superclass of UIViewController - MasterViewController which declares a property called itemsViewController. This declares a method called from the MasterViewController, and is wired up via a storyboard in IB.
I have a subclass of MasterViewController which redeclares this property as a specific iPad version, but I can't access the redeclared property from the parent class.
MasterViewController
#interface MasterViewController : UIViewController {
}
#property (nonatomic, strong) IBOutlet ItemsViewController *itemsViewController;
#end
#implementation MasterViewController
#synthesize itemsViewController;
-(void)viewDidLoad {
// I can access itemsViewController in viewDidLoad.
}
#end
MasterViewController_iPad
#interface MasterViewController_iPad : MasterViewController {
IBOutlet ItemsViewController_iPad *_itemsViewController;
}
#property (nonatomic, strong) IBOutlet ItemsViewController_iPad *itemsViewController;
#end
#implementation MasterViewController_iPad
#synthesize itemsViewController = _itemsViewController;
-(void)viewDidLoad {
[super viewDidLoad];
// when I call super viewDidLoad, itemsViewController is nil, as though the property hasn't been overriden
// _itemsViewController is not nil in viewDidLoad.
}
#end
Am I misunderstanding the way property inheritance works in Objective-C?
You can't change the type signature of a method when you override a superclass method.
MasterViewController has these methods:
(void)setItemsViewController:(ItemsViewController *)foo
(ItemsViewController *)itemsViewController
But you're trying to give MasterViewController_iPad these methods:
(void)setItemsViewController:(ItemsViewController_iPad *)foo
(ItemsViewController_iPad *)itemsViewController
Which you can't do: you can't overload the same method name but have different types for the arguments.
If ItemsViewController_iPad is a subclass of ItemsViewController, a quick solution would be to keep the same signature as in MasterViewController but simply use an ItemsViewController_iPad when you set the property.
You can use category if you'd like to override property. Here is example:
I have PDFFileChooserViewController with PDFFileModel and PDFFilesDataSource and some logic related to this properties.
#class PDFFileModel, PDFFilesDataSource;
#interface PDFFileChooserViewController : UIViewController
#property (nonatomic, strong) PDFFileModel* selectedModel;
#property (nonatomic, strong) PDFFilesDataSource*dataSource;
#end
Then I'd like to add specific ViewController for choosing files from Dropbox but my model have some additional fields for example dropboxPath and my DropboxDataSource gets files using another way. So I decided to create category and override this properties:
#import "PDFFileChooserViewController.h"
#class DropboxFileModel,DropboxDataSource;
#interface DropboxViewController : PDFFileChooserViewController
#end
#interface DropboxViewController (ModelCategory)
#property(nonatomic, strong) DropboxFileModel* selectedModel;
#property(nonatomic, strong) DropboxDataSource* dataSource;
#end
Notice that this category will be visible inside DropboxViewController only where I can manipulate with that properties but another classes see only super class interface

Read delegate from view controller in tab bar application

I found several posts online stating that I could access my application delegate object from any view controller through the following call:
[[UIApplication sharedApplicaton] delegate];
(For instance: data between Views UIApplication, iOS - Calling App Delegate method from ViewController)
However, whenever I include this line in a function in one of my view controllers, the application crashes.
This is the first application that I'm writing, and I cannot see the difference between my code and how other posts have said I should be using this sharedApplication call. For completeness, below is an excerpt from my application delegate and view controller.
FirstViewController.h:
#class wStreamAppDelegate;
#define URL_ADDRESS #"http://google.com"
#interface FirstViewController : UIViewController <UIWebViewDelegate>{
IBOutlet UIWebView * webView;
wStreamAppDelegate* appDelegate;
}
#property(nonatomic,retain) wStreamAppDelegate* appDelegate;
#property(nonatomic,retain) IBOutlet UIWebView* webView;
FirstViewController.m:
#import "FirstViewController.h"
#import "wStreamAppDelegate.h"
#implementation FirstViewController
#synthesize webView,appDelegate;
#class wStreamAppDelegate;
- (void)viewDidLoad {
[super viewDidLoad];
NSString* urlAddress = URL_ADDRESS;
NSURL* url = [NSURL URLWithString:urlAddress];
NSURLRequest * requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
self.appDelegate = (wStreamAppDelegate*)[[UIApplication sharedApplicaton] delegate];
//This doesn't work either
// wStreamAppDelegate *appDelegate= (wStreamAppDelegate*)[[UIApplication sharedApplicaton] delegate];
wStreamAppDelegate.h:
#interface wStreamAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
If anyone has any thoughts on what may be going wrong, general advice for debugging problems like these, or tips, I'd really appreciate it. Thanks.
Typos get everyone sooner or later... in this case, you wrote "sharedApplicaton" instead of "sharedApplication".

Calling a function from another UIViewController

I'm a beginner programmmer, this is for xcode - iPhone. although i made alot of my iPhone app but i seem to lack some understanding of how a simple communication might work.
Specially when I've got 2 ViewControllers.
And I wana call one function of a ViewController from another ViewController. Both are under a tabbarController. What I want to achieve is When I'm in ViewA, after tapping on a tableCell, I Should Invoke a method of ViewB and the NavigationBar of ViewB pushes to viewDetail.
The Following is the code i'm using
in ViewControllerA.h (where I'm calling a method)
#class ViewControllerB;
#interface SmartDDxViewController : UIViewController {
IBOutlet UITableView *tableView;
ViewControllerB *xViewController;
}
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, retain) ViewControllerB *xViewController;
And this is what I use to invoke it..ViewControllerA.m
ViewControllerB *ddViewController = [[ViewControllerB alloc] init];
self.xViewController = ddViewController;
[xViewController InitialiseDetailWithId:2 title:#"HEYA"];
Heres the InitialiseDetailWithId code: in ViewControllerB.m
-(void)InitialiseDetailWithId:(NSInteger)pkey title:(NSString *)tt{
NSLog(#"InitialiseDetailC=========================================");
AppDelegate *appDelegate = (Smart_DifferentialsAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate GetConditionDetailsWithId:pkey];
DDisViewController *viewController= [[DDisViewController alloc] initWithNibName:#"DetailView" bundle:nil];
viewController.title = tt;
[self.NavBar pushViewController:viewController animated:YES];
//[tt release];
[viewController release];
viewController = nil;
[self say:#"HEYA"]; //this is ALERTVIEW box that displays HEYA
}
I'm getting all information fine, and the alertview does get displayed. But when I chose that View in TabBar, its not pushed.
Do not use direct access between view controllers, instead use the delegate pattern. Define your controller like this:
#protocol ViewControllerAInitDelegate;
#interface ViewControllerA : UIViewController {
IBOutlet UITableView *tableView;
id<ViewControllerAInitDelegate> initDelegate;
}
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, assign) ViewControllerAInitDelegate *initDelegate;
#end
#protocol ViewControllerInitDelegate
-(void)initializeDetailWithId:(NSInteger)pkey title:(NSString)tt;
#end
So in
Now let your application delegate conform to the ViewControllerInitDelegate protocol. It should look something like this:
#interface AppDelegate : NSObject <UIApplicationDelegate, ViewControllerInitDelegate> {
IBOutlet UITabBarControler* tabBarController;
IBOutlet ViewControllerA* controllerA;
IBOutlet ViewControllerB* controllerB;
}
#end;
The AppDelegate should know about both ViewControllerA, and ViewControllerB, but neither of the view controller should know about each other. This way it will be much easier to debug and extend your app.
//current view controller index
int currentVCIndex = [self.navigationController.viewControllers indexOfObject:self.navigationController.topViewController];
//previous view controller (index -1)
AccountViewController *account = (AccountViewController *)[self.navigationController.viewControllers objectAtIndex:currentVCIndex - 1];
(access to anything you want)
account.property = object;
[account doSmthng];
In each of your view controllers, you might want to add a instance variable/property to keep track of the other view controller.
you might have for example:
#interface ThisViewController : UIViewController {
SomeViewController *sViewController;
// other instance variables
}
#property (nonatomic, retain) SomeViewController *sViewController;
This not only makes it easier to call methods from the other view controller and access its public properties, but it also allows you an easier way of flipping between the two (with or without animation).