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)];
Related
I use this code to display a one item Toolbar in UIViewController (which is pushed by UINavigationController). The toolbar shows up and immediately disappear:
UIBarButtonItem * logoutButton = [[UIBarButtonItem alloc] initWithTitle:#"Log out" style:UIBarButtonItemStylePlain target:self action:nil];
NSMutableArray * arr = [NSMutableArray arrayWithObjects:logoutButton, nil];
[self setToolbarItems:arr animated:NO];
[self.navigationController setToolbarHidden:NO animated:NO];
Do you know what the problem is?
where is this code? Doesn't seem to be anything out of the ordinary here so either has to do with where you are calling it, or something else that happens afterwards (like setting toolbarHidden to YES later or something)
I've programmatically created some UINavigationControllers and added them to a UITabBarController. Everything seems to work fine but I wanted to add a cancel button to the navigation controller but it never shows up. I've tried multiple ways but I can't seem to affect the display of the navigation items at all and I've followed multiple examples from here and other sites but nothing happens.
MyTableViewController *mtvc = [[MyTableViewController alloc] init];
UINavigationController *myNavController = [[[UINavigationController alloc] initWithRootViewController:mtvc] autorelease];
myNavController.navigationBar.barStyle = UIBarStyleBlackOpaque; // this works
[mtvc release];
// TODO: figure out why added buttons aren't showing
UIBarButtonItem *closeButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(shutDown)] autorelease];
myNavController.navigationItem.leftBarButtonItem = closeButton; // never shows up
I also tried adding the button this way
[myNavController.navigationItem setLeftBarButtonItem:closeButton animated:NO]; // also doesn't do anything
I started getting frustrated so I also tried some other things just to see if I could affect anything, but to no avail
myNavController.title = #"test"; // does nothing
I've tried doing it before and after the navigations controllers were added to the UITabBarController and that didn't help.
I've also tried rightBarButtonItem and tried using initWithTitle: instead of initWithBarButtonSystemItem.
Would someone please illuminate me? Clearly, I'm doing this the wrong way.
Try adding the bar buttons in the loadView method of MyTableViewController like the follwing.
UIBarButtonItem *closeButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(shutDown)] autorelease];
self.navigationItem.leftBarButtonItem = closeButton;
I guess that should work.
Have you tried setting the button of the current view controller's navigation item like this:
mtvc.navigationItem.leftBarButtonItem = closeButton;
If you need to do that in Swift 3.0, it is simple like that:
let closeButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel,
target: self,
action: #selector({Your-viewController}.{close-method}))
self.navigationItem.leftBarButtonItem = closeButton
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
I want to have the default shape of the back button, but that makes my program enter a loop at some point.
The code is this for modifying the text of the back button, written before the initialization of the view.
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: #"Back" style: UIBarButtonItemStyleBordered target: nil action: nil];
[[self navigationItem] setBackBarButtonItem: newBackButton];
[newBackButton release];
can I also change the target to another view? I really need that default shape and I don't know how else to get it. Thanks!
The UINavigationController does not work that way, you'll need to make a custom UIBarButton with an image.
If you want to customize the right-button in the navigation controller you usually set the backBarButtonItem on the parent view controller, i.e. the one you are going back to.
parentViewController.navigationItem.backBarButtonItem =
[[[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:nil action:nil] autorelease];
There is a solution to modify the target of the back button on this blog. The key idea is to subclass UINavigationController and override the popViewControllerAnimated: method. First paste in your custom code and then call [super popViewControllerAnimated:animated] at the end.
I have verified that this still works fine in SDK 4.3.
I'm using the template for a utility Application. In the FlipSideViewController, I added an IBOutlet for a UINavigationController, navController. In the code, I added the navController just fine. The rootViewController loads perfectly:
navController.viewControllers = [[NSArray arrayWithObject:rootViewController] retain];
[self.view addSubview:navController.view];
I changed the color of the navController just fine:
navController.navigationBar.tintColor = [UIColor colorWithRed:0.6 green:0.75 blue:0.6 alpha:1.0];
navController.navigationBar.translucent = NO;
I make a button (note: "done" refers to a IBAction that dismisses the modalviewcontroller):
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"TEST" style:UIBarButtonItemStyleDone target:self action:#selector(done:)];
I make a navItem using that button:
UINavigationItem *backNavItem = [[UINavigationItem alloc] initWithTitle:#"TESTTEST"];
[backNavItem setRightBarButtonItem:backButton animated:YES];
I try to add that button:
[navController.navigationBar pushNavigationItem:backNavItem animated:YES];
This above code fails miserably. I apparently can't add buttons to the navController because:
*** Terminating app due to uncaught exception
'NSInternalInconsistencyException',
reason: 'Cannot call
pushNavigationItem:animated: directly
on a UINavigationBar managed by a
controller.'
Do I have to make a separate UINavigationBar that's somehow connected to my navController? I tried going that route but with no avail.
I checked out "NavBar" here:
Excellent insight on how to do add buttons. You have to add buttons from the correct ViewController being displayed.