why can't I set a new instance's delegate as self? - objective-c

I have a uipickerview, which appears with an ActionSheet. All this is in a class "MultiPicker". I create a new instance from "FirstViewController" this way:
multiPicker *multiPic = [[multiPicker alloc]init];
multiPic.delegate = self;
[multiPic action:aRunIndex];
And inside "multiPicker", in "action:"
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:title delegate:otroDelegate cancelButtonTitle:nil destructiveButtonTitle:#"Cancel" otherButtonTitles:#"Done", nil];
UIPickerView *pickerView = [[[UIPickerView alloc] init] autorelease];
pickerView.tag = 101;
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.showsSelectionIndicator = YES;
[actionSheet addSubview:pickerView];
[actionSheet showInView:self.view];
I need "FirstViewController" when MultiPicker finishes, so I can update a table in FirstView. I tried setting a new delegate to MultiPicker so, it tells FirstView when it finishes. But the instruction "multipic.delegate = self" in the first piece of code mades the app crash and says "Terminating due to uncaught exception".
If I simply put all "MultiPicker" code inside FirstViewController class, not in a separate one, the action sheet stay blocked when I try to push a button different from "Cancel"
Any idea?
Thank u

be sure that your class 'self' implement the require protocol
protocols have optional and required methods you must implement all required methods of delegate 'protocol' in you class 'self'

Related

Add UINavigationItem to UINavigationController that wraps Google Drive OAuth

Goal: For connection to iOS Google Drive, wrap the iOS Google OAuth view controller in a programmatically created navigation controller, and add a Cancel button to enable the user to cancel the Google OAuth process, should they choose to do so.
Problem: While I can successfully wrap the OAuth view controller in a navigation controller, I cannot seem to add a navigation item, such as the desired Cancel button.
I add a navigation controller that wraps the Google Drive OAuth view controller, as follows...
GTMOAuth2ViewControllerTouch *authViewController = nil;
if (!self.isAuthorized) {
SEL selectorFinish = #selector(viewController:finishedWithAuth:error:);
SEL selectorButtonCancel = #selector(buttonCancelTapped:);
authViewController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDrive
clientID:kClientID
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:selectorFinish];
UINavigationController *navController = [[UINavigationController alloc] init];
[navController addChildViewController:authViewController];
[self.parentTVC presentViewController:navController animated:YES completion:nil];
}
For clarity, the variable parentTVC is a public property,
#property (nonatomic, strong) UITableViewController *parentTVC;
and is set using a custom init method, as follows...
- (id)initWithParentTVC:(UITableViewController *)tvc {
self = [super init];
[self setParentTVC:tvc];
return self;
}
I have attempted to add UINavigationItems to the UINavigationController instance navController, however this does not work, and instead I seem to be stuck with the UIView with the two small buttons (< and >) in the nib file GTMOAuth2ViewTouch.xib, image included below...
I have read through the GTL file GTMOAuth2ViewControllerTouch.m to attempt to see whether there is a method I could possible use or whether I can override by subclassing, but I am not confident in my attempts to do this.
My best guess is that any navigation controller wrapping the OAuth view controller set by this code from GTMOAuth2ViewControllerTouch.m...
- (void)setUpNavigation {
rightBarButtonItem_.customView = navButtonsView_;
self.navigationItem.rightBarButtonItem = rightBarButtonItem_;
}
Assistance please?
This is my re-interpretation of Imran Khan's excellent answer provided in his response to this stack overflow question: Google Drive iOS SDK: Display Cancel Login Button
The googleAuthCheck method should be called in either the viewDidLoad or viewWillAppear method of the parent view controller. (I assume here a reasonable understanding of iOS Google Drive SDK, so let me know if I need to add further clarification.)
Also, albeit a small issue, using initWithBarButtonSystemItem:UIBarButtonSystemItemCancel requires that only the title text of the view controller then needs to be localised (if you are implementing localisation).
- (void)googleAuthCheck {
if (!self.isAuthorized) {
SEL selectorFinish = #selector(viewController:finishedWithAuth:error:);
SEL selectorButtonCancel = #selector(buttonCancelTapped:);
UINavigationController *navController = [[UINavigationController alloc] init];
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:<<localised string for title>>];
UIBarButtonItem *barButtonItemCancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:selectorButtonCancel];
UINavigationBar *navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 320, 63)];
[navigationItem setRightBarButtonItem:barButtonItemCancel];
[navigationBar setTranslucent:NO];
[navigationBar setItems:[NSArray arrayWithObjects: navigationItem,nil]];
[navController.view addSubview:navigationBar];
GTMOAuth2ViewControllerTouch *authViewController = nil;
authViewController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDrive
clientID:kClientID
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:selectorFinish];
[navController addChildViewController:authViewController];
[self.parentTVC presentViewController:navController animated:YES completion:nil];
}
}
For clarity, the buttonCancelTapped: method is as follows...
- (IBAction)buttonCancelTapped:(UIBarButtonItem *)sender {
[self.parentTVC dismissViewControllerAnimated:YES completion:^(void){}];
}
For clarity, the variable parentTVC is a public property,
#property (nonatomic, strong) UITableViewController *parentTVC;
and is set using a custom init method, as follows...
- (id)initWithParentTVC:(UITableViewController *)tvc {
self = [super init];
[self setParentTVC:tvc];
return self;
}
This custom init method is called from the parent view controller.

In app settings (application is closed)

My application crashes when I close the settings.
Even with a standard animation (UIModalTransitionStyleCoverVertical) button "Done" is not working..
What could be wrong?
-EDIT- Apparently I was not quite accurate in describing the problem: XCode does not receive notice of a crash. The application simply closes. As a result, achievements gained during the session are lost.
- (IBAction)BarButtonPageCurlAction:(id)sender {
IASKAppSettingsViewController *SettingsViewController;
SettingsViewController = [[[IASKAppSettingsViewController alloc] initWithNibName:#"IASKAppSettingsView" bundle:nil] autorelease];
SettingsViewController.delegate = self;
//SettingsViewController.showDoneButton = NO;
//SettingsViewController.showCreditsFooter = NO;
SettingsViewController.modalTransitionStyle = UIModalTransitionStylePartialCurl;
UINavigationController *NavController = [[[UINavigationController alloc] initWithRootViewController:SettingsViewController] autorelease];
//[NavController setNavigationBarHidden:YES];
[self presentModalViewController:NavController animated:YES];}
my class files: .m.h
You don't have the proper delegate methods implemented. Look at the documentation of Inappsettings, there are methods used for dismissing the settings view.

UINavigationController for table inside of UITabController

my app is built with a UITabController and works as imagined. However, for one of the views within my UITabBar, I would like to add a table that when something is pressed will take me somewhere. And I would like to do this just within this one view.
I know how to build a table and populate and get it to go somewhere but my issue is I can't seem to get my app to run with the table. I feel like my connections are off and specifically with appDelegates. I already had two appDelegate files (.h & .m) before adding the UINavigationController so from here I really don't know what to do. I took apple's simpleTableView tutorial files and copied them over to mine. It still crashes. I even copied there appDelegate files (so now I have 4) but the same deal. This is the error I am getting but in general I just feel lost with the delegates and connections.
2011-12-12 12:08:50.302 TabbedCalculation[68713:207] * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key delegate.'
* Call stack at first throw:
If anyone can offer any help, it would be much appreciated.
Thanks!
P.S. I have changed within the mainWindow.xib of the UITabController to point one of the tabs to the appropriate class and xib file so that is not the issue but I have noticed that many tutorials want within the app delegate this line to the navController:
[window addSubview:[navigationController view]];
but I have already set it to the tabBarController.
Your app can only use one set of app delegate files. So copying over a the example's app delegate files does not mean they are being utilized. You need a navigation controller inside the specific tab you want to contain the tableview. Here is an example of a navigation controller inside a tab bar controller, by modifying didFinishLaunchingWithOptions in the app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
AllTaskViewController *view1 = [[AllTaskViewController alloc] initWithNibName:#"AllTaskView" bundle:nil];
view1.title = #"All Tasks";
TodayTaskViewController *view2 = [[TodayTaskViewController alloc] initWithNibName:#"TodayTaskView" bundle:nil];
view2.title = #"Today's Tasks";
HistoryViewController *view3 = [[HistoryViewController alloc] initWithNibName:#"HistoryView" bundle:nil];
view3.title = #"History";
SettingsTableViewController *view4 = [[SettingsTableViewController alloc] initWithNibName:#"SettingsTableView" bundle:nil];
view4.title = #"Settings";
UINavigationController *nav1 = [[UINavigationController alloc] initWithRootViewController:view1];
UINavigationController *nav2 = [[UINavigationController alloc] initWithRootViewController:view2];
UINavigationController *nav3 = [[UINavigationController alloc] initWithRootViewController:view3];
UINavigationController *nav4 = [[UINavigationController alloc] initWithRootViewController:view4];
[view1 release];
[view2 release];
[view3 release];
[view4 release];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:nav1, nav2, nav3, nav4, nil];
[nav1 release];
[nav2 release];
[nav3 release];
[nav4 release];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Note: All 4 view controllers have an individual navigation controller, and each one is a custom view controller. I used nibs here, but you don't necessarily have to. And the app itself has no main window, you would need to modify this slightly if you are using a main window for the app.

Two UIPopovers in One View

I am trying to put two different UIPopovers in one view. I'm fairly new to objective-c, and programming in general, so instead of doing the smart, efficient method of having one popover and changing it's contents depending on how it is called, I just used the stupid, simple method of just creating two views, two delegates, two popovers etc... I don't know if that's why I'm having a problem, or if it's for some other reason.
So here's the problem. In the viewdidload of the view where the popovers appear, I have this code:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
optionsViewController =[[OptionsViewController alloc]init];
optionsViewController.delegate = self;
popoverController = [[UIPopoverController alloc] initWithContentViewController:optionsViewController];
popoverController.popoverContentSize = CGSizeMake(320, 216);
[popoverController setDelegate:self];
newCurrencyViewController =[[newCurrencyViewController alloc]init];
newCurrencyViewController.delegate = self;
newCurrencyPopoverController = [[UIPopoverController alloc] initWithContentViewController:newCurrencyViewController];
newCurrencyPopoverController.popoverContentSize = CGSizeMake(320, 216);
[newCurrencyPopoverController setDelegate:self];
}
Obviously optionsViewController is the vc that appears inside popover 1 (with popover controller called "popoverController"), and newCurrencyViewController is the vc that appears inside popover 2 (with popover controller called "newCurrencyPopoverController").
Every time the view loads, the app crashes with a SIGABRT error, and the console says:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPopoverController initWithContentViewController:] must not be called with `nil`.'
Also, there's a warning saying "instance method -alloc not found (return type defaults to id)" for the line that
saysnewCurrencyViewController =[[newCurrencyViewController alloc]init];
My first thought was that I had misspelled the name of a file somewhere, since I think the problem is that it isn't finding the file called newCurrencyPopoverController, but I've checked everything and can't find any misspellings or anything. Any ideas?
Thanks very much!
LUKE
You are calling methods alloc + init of your variable newCurrencyViewController but you should call them to the class of that variable!
Line with bug:
newCurrencyViewController =[[newCurrencyViewController alloc]init];
The result of this line will be newCurrencyViewController == nil. And when you will try to init UIPopoverController with that view it will crash as you described.
If variable newCurrencyViewController is of class, for example, CurrencyViewController then you should replace that line with this one:
newCurrencyViewController =[[CurrencyViewController alloc] init];
you dont have an object to call alloc and init on when you are calling newCurrenceViewController.
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
optionsViewController =[[OptionsViewController alloc]init];
optionsViewController.delegate = self;
popoverController = [[UIPopoverController alloc] initWithContentViewController:optionsViewController];
popoverController.popoverContentSize = CGSizeMake(320, 216);
[popoverController setDelegate:self];
//Here is your problem---------------------------------------------
newCurrencyViewController =[[newCurrencyViewController alloc]init];
//-----------------------------------------------------------------
newCurrencyViewController.delegate = self;
newCurrencyPopoverController = [[UIPopoverController alloc] initWithContentViewController:newCurrencyViewController];
newCurrencyPopoverController.popoverContentSize = CGSizeMake(320, 216);
[newCurrencyPopoverController setDelegate:self];
}
you probably want something more like
newCurrencyViewController = [[UICurrencyViewController alloc] init];
Or w/e the name of your custom view controller is

UITabbarcontroller in IOS5 throws UIViewControllerHierarchyInconsistency exception

I have the following code for the UITabbarcontroller:
NSMutableArray *arr = [[NSMutableArray alloc] init];
tabBarController = [[UITabBarController alloc] init];
FirstViewController *firstview = [[FirstViewController alloc] init];
[tabBarControllerViews addObject:firstview];
[firstview release];
SecondViewController *secondview = [[SecondViewController alloc] init];
[tabBarControllerViews addObject:secondview];
[secondview release];
[tabBarController setViewControllers:arr animated:YES];
[arr release];
self.view = tabBarController.view;
This code runs fine on IOS4. I tried it on IOS5 beta and get the following error when tapping on a UITabbarItem:
*** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency',
reason: 'child view controller:<FirstViewController: 0x6e03be0> should have parent view
controller:<MainViewController: 0x6816d20> but actual parent is:<UITabBarController: 0x6b0c110>'
replace:
self.view = tabBarController.view;
with:
[self.view addSubview:tabBarController.view];
This will also be backwards compatible with IOS3&4.
Had the same pattern (and problem) in my code. Joe's solution didn't work for me. Looking at the snippet, I'm guessing that you derive a class from UIViewController to allow you to customize something.
The thing to do here, and it is quite simple, is to derive from UITabBarController rather than UIViewController, don't create tabBarController, and anywhere you reference tabBarController, substitute self.
5 minutes and you're no longer throwing the inconsistency exception and you remain backwards compatible with iOS 4. You can still do all of your customization in your derived class (monkeying with the nav controller, etc).
If you have built a complex derivation of UIViewController you need to use, this could be more work.
One small gotcha - if you override LoadView, you'll find that it gets called during the init for the UITabBarController. Makes it hard to set members prior to LoadView, so you may need to split up your initialization.
Good luck!
You cannot push or present a UITabbarViewController. Is your First View Controller a UITabBarController ?
I struggled with the same problem.
When you create a new Master-Detail Application(without story board), you can see this codes below from AppDelegate.m.
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
"BE NOT DEPENDENT ON MainWindow"
Just start from your own ViewController and set it to delegate.
And don't forget to unlink view from MainWindow.xib else the view will called 2 times.