I have a tabBar initilized in xib file,
question is, I want to deselect the item that I tapped before,
but I can't,
I tried
self.tabBar.selectedItem = 0;
self.tabBar.selectedItem = nil;
in any place I can, but it just does not work,
how can I deselect a tabBar item after I tapped it?
Thanks a lot!
Heres my solution to your problem below
.h
#interface DetailViewController : UIViewController <UITabBarDelegate>{
//..
IBOutlet UITabBar *myTabBar; //notice IBOutlet, hook this up to your tabBar in InterfaceBuilder
}
#property (strong, nonatomic) IBOutlet UITabBar *myTabBar;
.m
#synthesize myTabBar;
//..
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
actionTabBar.delegate = self; // This sets up tabbardelegate method
}
//..
#pragma myTableDelegates
// a Case for each button
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
switch (item.tag) {
case 0:
{
if (check for condition here) {
// do some tab stuff here, maybe load a view or something
}
else if (check for condition here) {
// do some stuff here like unloading views etc
[myTabBar setSelectedItem:nil]; //clears the previously selected cell
// this means only one cell can be selected at a time.
}
}
break;
case 1:
{
NSLog(#"item 1 selected");
}
break;
case 2:
{
NSLog(#"item 2 selected");
}
break;
default:
break;
}
}
This should get you started, its pretty much the same code I use in a project of mine so it should work, you will just have to use your own if statments to get that tabbutton selection and deselection.... if this is not what your looking for the
[myTabBar setSelectedItem:nil];
will be enough for you to clear any selected cells in the tabBar.. however you must remember myTabBar is an IBOutlet so you have to hook it up in Interface Builder to the tabbar you have in there, alternately you could do this in code also but it sounds like your working with a .xib file so the above solution should be sweet.
I have not built and run this specific code so there might be an error in it, let me know if you need any more help.
Anyway I hope this works out for you :)
Related
I know this should be a simple thing to fix, but I can't see what's going wrong. May be extra pair will help. Here is what I am trying to do.
In my table view controller, there is an (+) button on the navigation controller to add new item.
I have a modal segue that takes it to the next view controller. User fills in a form and hit saves the table view controller reloads with the newly added record.
To do this, I implemented protocol with a delegate.
MyFormViewController.h
protocol MyCustomDelegate <NSObject>
#required
- (void)addNewRecord:(myFormViewController *)formViewController itemToAdd:(Item *)item;
#end
#property (nonatomic,weak) id<MyCustomDelegate> delegate;
MyFormViewController.m
#synthesize delegate;
- (IBAction)addItem:(id)sender {
Item *item = [[Item alloc]init];
item.name = itemName.text;
item.desc = itemDescription.text;
// I am having problem here, self.delegate is being null even though, it's being set in prepareForSegue.
if ([self.delegate respondsToSelector:#selector(addNewRecord:)]) {
[self.delegate addNewRecord:self itemToAdd:item];
}
else{
// delegate is getting set to null for some reason.
NSLog(#"Delegate method not getting called...%#",delegate);
}
}
in MyTableViewController.h
#interface MyTableViewController : UITableViewController
MyTableViewController.m
-(void)addItem:(myFormViewController *)formViewController itemToAdd:(Item *)item{
if(item)
{
MyClass *_itemClass = [[MyClass alloc]initWithPath:#"items/"];
[_itemClass addItemForUser:item];
}
[formViewController dismissViewControllerAnimated:YES completion:nil];
}
in my prepareForSegue method I am setting my tableviewcontroller as delegate.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"addItemSegue"]){
myFormViewController *_showaddTopic = [[myFormViewController alloc]init];
_showaddTopic.delegate = self;
}
After all this, my delegate in myFormViewController is being set to "null". I am not sure why it's not working. It's pretty basic stuff but giving me hard time.
Thank you
myFormViewController *_showaddTopic = [[myFormViewController alloc]init];
_showaddTopic.delegate = self;
There's your problem. You are creating a new MyFormViewController. But that's the wrong MyFormViewController; you want to use the one that is already the segue's destination controller. So you are setting the wrong object's delegate.
(PS Notice my use of a capital letter to start the name of a class? Always do that.)
maybe _showaddTopic.delegate = self; can not written here and shuold this object alloc after at once
I have a question pertaining to why my UITableView won't load a detailView...
I've done it before with an interface builder, but now I'm just trying to do it programatically, purely.
In my tableView.h:
#property (strong, nonatomic) RLCASearchDetailViewControllerViewController *searchDetailViewController;
In my tableView.m:
#synthesize searchDetailViewController = _searchDetailViewController;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.searchDetailViewController)
{
self.searchDetailViewController = [[RLCASearchDetailViewControllerViewController alloc] initWithNibName:#"" bundle:nil];
}
SearchItem *item = [ content objectAtIndex:indexPath.row ];
[self.navigationController pushViewController:self.searchDetailViewController animated:YES];
self.searchDetailViewController.detailItem = item;
}
By the way, I'd tried the initWithNibName: value to be nil, empty string as above, and even #"RLCASearchDetailViewControllerViewController". Nothing works...
in my RLCASearchDetailViewControllerViewController.h:
#interface RLCASearchDetailViewControllerViewController : UIViewController
{
SearchItem *detailItem;
}
#property (strong, nonatomic) id detailItem;
#end
in my RLCASearchDetailViewControllerViewController.m:
#synthesize detailItem = _detailItem;
- (void)setDetailItem:(SearchItem*)newDetailItem
{
NSLog( #"GETS HERE" );
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem)
{
NSLog( #"GETS HERE" );
}
}
- (void)loadView
{
[super loadView];
// If you create your views manually, you MUST override this method and use it to create your views.
// If you use Interface Builder to create your views, then you must NOT override this method.
NSLog( #"DOES NOT GET HERE" );
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog( #"DOES NOT GET HERE" );
}
As seen above, when I'd implemented a few debugging prints... It does what it's supposed to in theory but for some reason does not load the views. This manifests itself in the GUI by nothing happening when a table cell is clicked, when the view should change into the subview.
What am I doing wrong? Please help... It's been driving me crazy, and I'd been rummaging through the interweb for a while now in hopes of answers.
Thanks a bunch - I really appreciate it! ;)
Sincerely,
Piotr.
If you aren't using a nib, change this line of code:
self.searchDetailViewController = [[RLCASearchDetailViewControllerViewController alloc] initWithNibName:#"" bundle:nil];
To
self.searchDetailViewController = [[RLCASearchDetailViewControllerViewController alloc] init];
Hope it helps !
Your table view is not embedded in a navigation controller, so it can't push a new view controller.
Since the detail view controller is never displayed on the screen, it never bothers loading its view, which is why you are seeing nothing from your loadView or viewDidLoad methods.
You don't show how you set up the initial view controller for your app, but it should be a navigation controller, with your table view controller as the root view controller.
If you're a beginner, storyboards are much better to use than trying to do it all in code. There are few benefits and lots of drawbacks to avoiding interface builder.
I have a tab bar controller (its a tab bar based application, so tab bar is on MainWindow.xib). In this xib, I have added 4 tab bar items and I have set the image of all tab bar item. Due to this, I am facing 2 issues:
1) The image is white-colored, but when I run the application, its showing all the images on tab bar item as gray colored. How can I make it look same as is in the original image.
2) I have a selected image, that I want to add on the tab bar item which is currently selected. How should I do this???
UPDATED AFTER NICK's CODE:
Hey, in iOS 5, you will have to write following code in your app delegate for setting tab bar item selected and unselected image (the category solution will work only on 4):
if ([[[UIDevice currentDevice] systemVersion] floatValue]>4.9) {
NSString *selectedImageName,*unselectedImageName;
for (int counter = 0; counter < [self.tabBarController.tabBar.items count]; counter++) {
if (counter==0) {
selectedImageName = <someImagename>;
unselectedImageName = <someImagename>;
}
else if (counter==1) {
selectedImageName = <someImagename>;
unselectedImageName = <someImagename>;
}
.
.
else {
selectedImageName = <someImagename>;
unselectedImageName = <someImagename>;
}
UIImage *selectedImage = [UIImage imageNamed:selectedImageName];
UIImage *unselectedImage = [UIImage imageNamed:unselectedImageName];
UITabBarItem *item = [self.tabBarController.tabBar.items objectAtIndex:counter];
if ([item respondsToSelector:#selector(setFinishedSelectedImage:withFinishedUnselectedImage:)]) {
[item setFinishedSelectedImage:selectedImage withFinishedUnselectedImage:unselectedImage];
}
}
}
Add this category to your project. It will force tab bar items to use your original image as the disabled state instead of applying a grey gradient to them:
#implementation UItabBarItem (CustomUnselectedImage)
- (UIImage *)unselectedImage
{
return self.image;
}
#end
This may seem like it is using private APIs but I've seen this used multiple times on apps that were approved. It's not actually calling a private method, just overriding one.
If you need to specify different images for the selected and unselected image, your best bet is probably to use the tag property of the UITabBarItem and a switch statement, like this:
#implementation UItabBarItem (Custom)
- (UIImage *)selectedImage
{
switch (self.tag)
{
case 1:
return [UIImage imageNamed:#"tab-selected1.png"];
case 2:
return [UIImage imageNamed:#"tab-selected2.png"];
etc...
}
}
- (UIImage *)unselectedImage
{
switch (self.tag)
{
case 1:
return [UIImage imageNamed:#"tab-unselected1.png"];
case 2:
return [UIImage imageNamed:#"tab-unselected2.png"];
etc...
}
}
#end
Then in interface builder, don't bother with setting the tab bar item images as they'll just be ignored. Instead, set their tags to match up with the images you've specified in your switch statements.
Note that if you have multiple tab bars in your app, and you don't want them to all be overridden in this way, you can define these methods on a subclass of UITabBarItem instead of as a category. Then you can set the class of the tab bar items in your nib file to be your custom subclass instead of regular UITabBarItems, and only those ones will be affected.
EDIT:
Note that as of iOS 5 there is a better way of doing this using the UIAppearance APIs. This technique should still work, but who knows if Apple might start cracking down on it now that there is an officially supported approach. Better to use the new method unless you really need iOS 4 support.
Based on http://blog.theanalogguy.be/ works for me. Add the category UItabBarItem (CustomUnselectedImage) - haven't effect =(
the *.h
#interface CustomTabBarItem : UITabBarItem {
UIImage *customHighlightedImage;
UIImage *customNormalImage;
}
#property (nonatomic, retain) UIImage *customHighlightedImage;
#property (nonatomic, retain) UIImage *customNormalImage;
- (id)initWithTitle:(NSString *)title
normalImage:(UIImage *)normalImage
highlightedImage:(UIImage *)highlightedImage
tag:(NSInteger)tag;
#end
and *.m
#import "CustomTabBarItem.h"
#implementation CustomTabBarItem
#synthesize customHighlightedImage;
#synthesize customNormalImage;
- (id)initWithTitle:(NSString *)title
normalImage:(UIImage *)normalImage
highlightedImage:(UIImage *)highlightedImage
tag:(NSInteger)tag{
[self initWithTitle:title
image:nil
tag:tag];
[self setCustomNormalImage:normalImage];
[self setCustomHighlightedImage:highlightedImage];
return self;
}
- (void) dealloc
{
[customHighlightedImage release];
customHighlightedImage=nil;
[customNormalImage release];
customNormalImage=nil;
[super dealloc];
}
-(UIImage *) selectedImage
{
return self.customHighlightedImage;
}
-(UIImage *) unselectedImage
{
return self.customNormalImage;
}
#end
happy coding =]-
So, I want to place a label in my fist view and place in a second one a UISwitch.
But the problem is I can't link together everything.. :/
in my first view i have that
- (void)onRoff {
if (mySwitch1.on) {
test.hidden = YES;
}
else (test.hidden = NO);
}
but here I have an error with mySwitch1 because it's declared in my secondView..
I don't know if it's clear, I want to link a label and a switch in different view..
Thanks !
Indeed you are not very clear. The first thing you might want to try is describe what you did:
how are your two views instantiated?
Let's assume your two views are instantiated from two different nib files.
what is the object you want to have access to your label and switch?
Let's assume it's a view controller. It's a bit unusual for a single view controller to control two views from two different nib files, but after all, why not?
In any case, you can set the owner class for your two nib files to be the class of your view controller. Then in Interface Builder, from the first view, you can bind the label to the file owner's UILabel outlet. And in Interface Builder, from the second view, you can bind the UISwitch to the file owner's second outlet, of type UISwitch.
But perhaps the onRoff methods of yours is actually a method of one of your two view class? The same idea apply: you can set the file owner in the second nib file to be the view class of the first view, and then bind the switch to the file owner's UISwitch outlet.
But it sounds like your design might be worth working on...
Edit: after your comment, here is a bit more...
The problem is that your two view controllers each control a different page and have no reason to know about each other. So you need a middle man object. That could be another controller. Let's use the Application delegate. Then, in the IBAction method of your SwitchViewController, you can do something like:
- (IBAction) switchChangedValue:(UISwitch *) sender {
NSString *newLabelText = sender.isOn ? #"On" : #"Off";
self.labelViewController.label.text = newLabelText;
}
Now how will everybody know about each other? First each view controller will inform the middle man. Here is it for the SwitchViewController:
- (void) viewDidLoad
{
[super viewDidLoad];
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.switchViewController = self;
}
Second, the app delegate will need to coordinate everything:
#interface MyAppDelegate : …
#property (nonatomic, retain) SwitchViewController *switchViewController;
#property (nonatomic, retain) LabelViewController *labelViewController;
#end
#implementation MyAppDelegate
#synthesize switchViewController = _switchViewController;
#synthesize labelViewController = _labelViewController;
- (void) setSwitchViewController:(SwitchViewController *) newSwitchController {
if (newSwitchController != _switchViewController) {
[_switchViewController release];
_switchViewController = [newSwitchController retain];
_switchViewController.labelViewController = _labelViewController;
if (_labelViewController)
_labelViewController.label.text = _switchViewController.switch.isOn ? #"On" : #"Off";
}
}
- (void) setLabelViewController:(LabelViewController *) newLabelController {
if (newLabelController != _labelViewController) {
[_labelViewController release];
_labelViewController = [newLabelController retain];
_labelViewController.switchViewController = _switchViewController;
if (_switchViewController)
_labelViewController.label.text = _switchViewController.switch.isOn ? #"On" : #"Off";
}
}
I left out a number of details, but I hope the big picture is clear.
So you have declared ur UISwitch in the second view and ur label in the first view. All u have to do is just use NSUserDefaults to achieve wat u want. Have the following method in the second view itself. Dont bring it to the first view.
- (void)onRoff {
if (mySwitch1.on) {
[[NSUserDefaults standarduserdefaults]setObject:#"off" forKey:#"state"];
[[NSUserDefaults standarduserdefaults]synchronize];
}
else {
[[NSUserDefaults standarduserdefaults]setObject:#"on" forKey:#"state"];
[[NSUserDefaults standarduserdefaults]synchronize];
}
}
Now in the viewWillAppear method of the first view just chk the value of the NSUserDefaults..
-(void)chkState{
NSString *tempStr=[[NSUserDefaults standarduserdefaults]objectForKey:#"state"];
if([tempStr isEqualTo:#"on"]) {
test.hidden=YES;
}
else {
test.hidden=NO;
}
}
Call this method in the viewWillAppear of the firstview like this....
[self chkState];
Hope this helps....If u want save the state of the switch too then just chk the userdefaults value again in the viewWilAppear method of the 2nd view and based
I have tried a bunch of different things and feel like I am missing something really small..
I am trying to pass a string to another view controller but when i NSLog it i get a return of (null)...
heres what It looks like, I have tried so many examples I am almost ready to give up..
//secondview.h
#interface SearchResultsViewController : UITableViewController {
NSString *setRequestString;
}
#property (nonatomic, retain) IBOutlet NSString *setRequestString;
//secondview.m
//...
#synthesize setRequestString;
//...
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", setRequestString);
}
//firstview.m
//...
#import "secondview.h"
//...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
//--- Idendify selected indexPath (section/row)
if (indexPath.section == 0) {
//--- Get the subview ready for use
secondview *sec = [[secondview alloc] initWithNibName:#"secondview" bundle:nil];
//...
switch (indexPath.row)
{
case 0: sec.title = #"Manufacture";
sec.setRequestString = [NSString stringWithString:#"yo"];
break;
//...
etc..
Declare a method in the class to which you want to send the data and call this method from the other class and pass the data as a parameter of the method. If u want keep it very simple u can try using NSUserDefaults. Hope this helps. Happy coding.... :)
Are you sure that "switch (indexPath.row) { case 0:" is getting called?
Try putting an NSLog in that case of your switch statement to make sure of that first.
First, you are using a pretty uncommon object name; "setRequestString" should better be named "requestString". Otherwise your synthesized setter will be called "setSetRequestString".
-- rest removed as that was bullshit, sorry, its late over here ;) ----