iphone setRightBarButtonItem from AppDelegate - iphone

I am trying to set the right button of the navbar from within the appDelegate, the code compiles and executes without error but the button does not appear.
Any assistance would be appreciated.
Thanks.
NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init];
UIActivityIndicatorView *aiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
UIBarButtonItem *activityButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aiv];
[aiv startAnimating];
[aiv release];
[self.navigationController.navigationItem setRightBarButtonItem:activityButtonItem animated:YES];
[activityButtonItem release];
[apool release];

First a few pointers.
You use an NSAutoReleasePool in circumstances where you are creating a lot of autoreleased objects in a short time, e.g. in a loop. Quoting Apple:
If your application creates a lot of
temporary autoreleased objects within
the event loop, however, it may be
beneficial to create “local”
autorelease pools to help to minimize
the peak memory footprint.
Since you are not creating any autoreleased objects it's not necessary to have the NSAutoReleasePool.
Normally you would put the code to set the buttons of the navigation bar in viewDidLoad of the UIViewController that should respond to the button. When UINavigationController pushes a new UIViewController on to its stack it will ask that controller for whatever buttons should be displayed.
Let's say the root view controller of your UINavigationController is the default generated RootViewController. Then you should put the code in viewDidLoad of RootViewController. Or perhaps in viewDidAppear: since you are animating the insertion.
UIActivityIndicatorView *aiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
UIBarButtonItem *activityButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aiv];
[aiv startAnimating];
[aiv release];
[self.navigationItem setRightBarButtonItem:activityButtonItem animated:YES];
[activityButtonItem release];
If you really must have the code in the app delegate that it can be accomplished by:
UIActivityIndicatorView *aiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
UIBarButtonItem *activityButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aiv];
[aiv startAnimating];
[aiv release];
UIViewController *rootController = [self.navigationController topViewController];
rootController.navigationItem.rightBarButtonItem = activityButtonItem;
[activityButtonItem release];

Robert thanks for the advice.
I have taken out the autorelease and appreciate should normally be used in the ViewDidLoad and can confirm works perfectly when used there to start the activity animation.
The issue i have is:
i can use the example code in the relevant view controller to start the animation
UIActivityIndicatorView *aiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
UIBarButtonItem *activityButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aiv];
[aiv startAnimating];
[aiv release];
[self.navigationItem setRightBarButtonItem:activityButtonItem animated:YES];
[activityButtonItem release];
but i have a singleton object for IAP which is called from various view controllers within my app and i need to be able to stop the activity animation - think need to just set the rightBarButton = nil but struggling to work out how the singleton object can tell the corresponding view controller to stop the animation.
I thought about trying to use something like:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector (IAP_complete:) name: IAP_completeNotification object:nil];
but haven't figured out the complete process start to finish. Appreciate any help you can offer on;
viewController setting the rightBarItem and starting the animation (done)
setting up NSNotificationCenter to listen for IAP completed (if this is the best way to achieve)
setting up the singleton object NSNotificationCenter to broadcast the IAP is complete
To expand on this
I am using the MKStoreKit 3 by Mugunth Kumar # http://blog.mugunthkumar.com/coding/introducing-mkstorekit-–-version-3/
I have modified this to suit my needs but simply put;
In my VC i use the following to initiate the in app purchase
//display activity indicator
UIActivityIndicatorView *aiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
UIBarButtonItem *activityButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aiv];
[aiv startAnimating];
[aiv release];
[self.navigationItem setRightBarButtonItem:activityButtonItem animated:YES];
[activityButtonItem release];
//begin in app purchase
[[MKStoreManager sharedManager] buyFeature:appID];
Once this is complete i need to tell the VC that this is complete.
in the file MKStoreManager.m
-(void) provideContent: (NSString*) productIdentifier
forReceipt:(NSData*) receiptData
i unlock or download content here but need to stop the activity indicator also which is where i am missing the plot.
Thanks,
Mike

Related

Infobutton not Displaying ModalView

When pressing infobutton it is not displaying ModalView
UIBarButtonItem *infoItem = [[UIBarButtonItem alloc]
initWithTitle:#"Info"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(displayModalView:)];
- (void)displayModalView
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[Infoviewcontroller alloc] init];
UINavigationController *navigationController=[[UINavigationController alloc] init];
navigationController.navigationBar.tintColor = [UIColor brownColor];
[navigationController pushViewController:_viewController animated:YES];
[_window addSubview:navigationController.view];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
}
Anyone can help me please what is the problem in this.
Thanks a lot in advance for helping me out
In your question you didn't specify how you created your objects (the toolBar and the buttons on it), are you creating them from Xcode by dragging and dropping or from pure code, therefore I will try to point out the common issues for both cases.
First, I am assuming that you are using Xcode and dragging the components that you like. In this case you need to create in the .h file an Outlet that will be linked to the button on the bar as follows:
#interface yourViewController : UIViewController
{
UIBarButtonItem *barButton;
}
#property (nonatomic, retain) IBOutlet UIBarButtonItem *barButton;
- (void) barButtonPress;
Notice that I added a function that will handle the bar button press. Now you need to link this Outlet to the bar button item, simply in Xcode in the Connection Inspector where it says New Referencing Outlet drag to the File's Owner box (the yellow cube).
Now in the viewDidLoad add the following:
[barButton setTarget:self];
[barButton setAction:#selector(barButtonPress)];
This code will link your bar button to the function that you want to be called when you press it. Now for the view that you like to view Modal, I assume that you already #import it also in the .h file, lets call it MyViewModal.
Inside the function that will be called when you press the bar button:
- (void) barButtonPress
{
MyViewModal *myViewModal = [[MyViewModal alloc] initWithNibName:#"MyViewModal" bundle:nil];
[self presentModalViewController:myViewModal animated:YES];
}
That's all, it will be displayed in Modal View. Keep in mind the allocating the new view is done based on your needs, here I did the simplest case just for illustration.
UPDATE: If not using Xcode
If you are not using Xcode then you should have a toolbar already defined say it is named myToolBar. To add buttoms to the tool bar we use the myToolbar.items way therefore we need to prepare the buttons with their targets before adding them. Here is a workflow:
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:self action:#selector(barButtonPress) forControlEvents:UIControlEventAllEvents]; //same function as above
UIBarButtonItem *btn = [[[UIBarButtonItem alloc] initWithCustomView:infoButton] autorelease];
myTool.items = [NSArray arrayWithObjects:btn, nil];
This should do it for you.

“Application tried to present modally an active controller” Error in iOS5

I have an error which is causing my app to crash under iOS5 only on the iPad.
The below code is called when the user taps on an item in a uibarbutton item :
- (void)optionSelected:(NSString *)option {
[self.optionPickerPopover dismissPopoverAnimated:YES];
if ([option compare:#"Map View"] == NSOrderedSame) {
NSLog(#"Map View");
MapView * map = [[MapView alloc] initWithNibName:#"MapView" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:map];
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleDone target:self action:#selector(removeCurrent)];
map.navigationItem.rightBarButtonItem = rightButton;
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[map release];
[rightButton release];
[split presentModalViewController:map animated:YES];
}
Can anyone suggest why this occurring in iOS5 ?
You are getting this error because you are attempting to display the 'map' view controller twice. The first time is as the root view controller of 'navigationController' and the second time is via [split presentModalViewController:map animated:YES].
iOS 5 is being a bit more picky than iOS 4 when you try to do strange things with view controllers. Trying to show the same controller twice is a design problem - you need to work out what you are really trying to do and fix it.
(Also, calling a map view controller 'MapView' rather than 'MapViewController' is really confusing)
This error will also occur if you don't follow these guidelines: Creating Custom Content View Controllers
Basically, you need to call:
[yourVC removeFromParentViewController];
if you've
[parentVC addChildViewController:yourVC];
This error may often be paired with something about "UIViewControllerHierarchyInconsistency"

ApplicationWillEnterForeground's inconsistent behaviour

I have password authentication for my application. My application is window based. I have five view: MyApplicationAppDelegate,MainViewController, HelpViewController, SettingViewController and ErrorViewController.
When the application starts, I navigate to MainViewController. I have two buttons on toolbar for Help and Setting which direct to respective pages. Now, I have written following code in MyApplicationAppDelegate:
- (void)applicationWillEnterForegroundUIApplication *)application {
[self showMyView];
}
-(void)showMyView{
if (![Global timeSet]) {
if (errorviewFlag) {
if (![Global show]){
ErrorPageViewController *bViewController = [[[ErrorPageViewController alloc]
initWithNibName"ErrorPageViewController" bundle:[NSBundle mainBundle]] autorelease];
[self setError:bViewController];
self.error = bViewController;
//[window addSubview:[error view]];
[[self navigationController] pushViewController:bViewController animated: NO];
UIBarButtonItem *_backButton = [[UIBarButtonItem alloc] initWithTitle"Back" style:UIBarButtonItemStyleDone target:nil action:nil];
[self.navigationController setNavigationBarHidden:YES];
[self.navigationController setToolbarHidden:YES];
[_backButton release], _backButton = nil;
[window makeKeyAndVisible];
errorviewFlag=FALSE;
[Global setShow:TRUE];
}
}
}
}
Now, this method is called for all times except the first.
The problem is this only works in desired way, i.e. shows ErrorPage, when I minimize the application from MainView. If I minimize from Help or setting, it does not show the error page, but instead the mainpage with no navigation controls. Why?
He was able to find the answer. I used NSNotificationcenter with didEnterBackground. I used this in all other view than MainView. And in my didEnterBackground method i used
[self.navigationController popViewControllerAnimated:NO];
This forced all other view to come to MainView when application is minised and this solved the problem.

navigationbar title not getting set iphone

In my app, I'm presenting a modalviewcontroller as follows and I'm not able to change the navigationbar's title or any of its properties for that matter.
fullListTopCompanies *fullListTopCompaniesInstance = [[fullListTopCompanies alloc] initWithNibName:#"fullListTopCompanies" bundle:nil];
UINavigationController *cntrol = [[UINavigationController alloc] initWithRootViewController:fullListTopCompaniesInstance];
[fullListTopCompaniesInstance setTitle:#"TEST"];
UIBarButtonItem *submit = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(displayViewForPosts)];
fullListTopCompaniesInstance.navigationItem.rightBarButtonItem = submit;
[submit release];
[self presentModalViewController:cntrol animated:YES];
[cntrol release];
I tried instantiating application delegate and assigning its navigationcontroller to local navigationcontroller instance but no use.
Somehow that navigationcontroller is not accessible. It can't be accessed by using "self.navigationitem". Whenever I present modalviewcontroller with the navigationcontroller, this navigation comes below the actual navigationcontroller.
For Example, if you are trying to set title of navigation bar for the ViewController called "ABCViewController", then add
self.Title = #"";
in viewWillAppear Method of the ABCViewController and try to rebuild and Run.
Hope this helps. :)
Whenever I present modalviewcontroller with the navigationcontroller, this navigation comes below the actual navigationcontroller.
That problem is because calling presentModalViewController: on self, you should call it on self.navigationController that way the navigation controller won't be shown below the other one.
As to why you can't set the navigationController's properties, I don't know. It looks Ok to me. But I expect it is because you are setting the properties before viewDidLoad is called by the nib-loader. I think I remember having problems like this myself a long time ago.
You should set the title etc. in the UIViewController subclass's viewDidLoad method and I think you worries will be over.
I've created a simple view based app with xcode template, then i've added your code and it's working for me...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Add the view controller's view to the window and display.
TestViewController *fullListTopCompaniesInstance = [[TestViewController alloc] initWithNibName:#"TestViewController" bundle:nil];
UINavigationController *cntrol = [[UINavigationController alloc] initWithRootViewController:fullListTopCompaniesInstance];
[fullListTopCompaniesInstance setTitle:#"TEST"];
UIBarButtonItem *submit = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(displayViewForPosts)];
fullListTopCompaniesInstance.navigationItem.rightBarButtonItem = submit;
[window addSubview:viewController.view];
[window makeKeyAndVisible];
[viewController presentModalViewController:cntrol animated:YES];
[cntrol release];
[submit release];
return YES;
}

UIBarButtonItem crashes iphone app when button is clicked

UIBarButtonItem *rButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:NULL];
rButton.action = #selector(refreshAction);
self.navigationItem.rightBarButtonItem = rButton;
[rButton release];
The above code works fine to create a button and add it to the navigation bar, but when I click on the button it crashes the app with a EXC_BAD_ACCESS. If I comment out rButton.action = #selector(refreshAction); clicking the button won't do anything but it doesn't crash either.
- (void)refreshAction {
NSLog(#"refreshAction");
}
This code is in a TableViewController's viewDidLoad method which is pushed onto the navigationController stack from the NavigationViewController viewDidLoad method.
I've spent probably 3 hours trying to get this to work, to no avail.
As usual memory management was the culprit. Loading the tableViewController from the navigationController:
NearbyTableViewController *tableController = [[[NearbyTableViewController alloc] initWithNibName:#"NearbyTableViewController" bundle:nil] autorelease];
self.nearbyTableController = tableController;
[self pushViewController:self.nearbyTableController animated:YES];
[tableController release];
releasing an object set to autorelease... must be the most common error in memory management.
Deleting that line [tableController release] solved the problem
Any luck if you specify #selector(refreshAction) when you create the button, i.e.:
UIBarButtonItem *rButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(refreshAction)];
Maybe the target doesn't get saved if you don't also specify the action to the initializer.
I'm not exactly 100% sure why your code does not work, but setting the selector directly in the constructor does work:
UIBarButtonItem *rButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:#selector(refreshAction)];