I have a UILabel in interface builder that I've connected to a property, but it's staying nil through the viewDidLoad on that view controller. I've been stepping through and as soon as the DetailViewController is initialized, the label property is there but it is nil and it never seems to be initialized.
It was working until I switched from using segues to doing pushViewController on the navigation controller.
// DetailsViewController.h
#import <UIKit/UIKit.h>
#import "TLitem.h"
#interface DetailsViewController : UIViewController
#property (nonatomic, strong) TLitem *entry;
#property (weak, nonatomic) IBOutlet UILabel *entryLabel;
#end
Then in a table view in another view controller:
// EntryListViewController.m
DetailsViewController *details = [[DetailsViewController alloc] init];
[details setEntry:entry];
[self.navigationController pushViewController:details animated:YES];
And in the viewDidLoad:
// DetailsViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor yellowColor]];
TLitem *entry = [self entry];
UILabel *label = [self entryLabel];
label.text = [entry valueForKey:#"text"];
[[DetailsViewController alloc] init] is not loading the view controller from the storyboard. It creates a new DetailsViewController, but nothing from IB will be connected. Look into -instantiateViewControllerWithIdentifier:
It will look something like
DetailsViewController *details = [self.storyboard instantiateViewControllerWithIdentifier:#"Some Storyboard Identifier You Create"];
details.entry = entry;
[self.navigationController pushViewController:details animated:YES];
Related
I have label in my secondviewcontroller. I would like to pass button index from firstviewcontroller to secondviewcontroller label. When I press button, it goes to second viewcontroller but label is nil
// FirstViewController.m
NSInteger index = [carousel indexOfItemViewOrSubview:sender];
int ind=index;
SecondViewController *sVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:[NSBundle mainBundle]];
sVC.myLabel.text=[NSString stringWithFormat:#"%d",ind];
[self presentModalViewController:sVC animated:YES];
//SecondViewController.h
#property (strong, nonatomic) IBOutlet UILabel *myLabel;
//SecondViewController.m
#synthesize myLabel;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"%#",myLabel.text);
}
In the SecondViewController.h add another property:
#property (nonatomic) NSInteger index;
Then in the FirstViewController.m pass the value of index to the index of the second view:
NSInteger index = [carousel indexOfItemViewOrSubview:sender];
int ind=index; //now you don't need this
SecondViewController *sVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:[NSBundle mainBundle]];
sVC.myLabel.text=[NSString stringWithFormat:#"%d",ind];
// New line
sVC.index = index;
[self presentModalViewController:sVC animated:YES];
.h
#interface DetailViewController : UIViewController
{
IBOutlet UILabel *sname;
IBOutlet UIImageView *sImage;
}
#property (strong, nonatomic)id titletwo;
#property (strong, nonatomic)id Viewimage;
.m
#interface DetailViewController ()
#end
#implementation DetailViewController
{
[super viewDidLoad];
UIImage* theImage = [UIImage imageNamed:[self.Viewimage description]];
sImage.image = theImage;
sname.text = [self.titletwo description];
}
Viewcontroller.m
- (void)tableViewUITableView *)tableView didDeselectRowAtIndexPathNSIndexPath *)indexPath
{
NSDictionary *tmpDict = [myObject objectAtIndex:indexPath.row];
DetailViewController *view2 = [[[DetailViewController alloc] initWithNibName:nil bundle:nil] autorelease];
view2.Viewimage = [tmpDict objectForKey:thumbnail];
view2.titletwo = [tmpDict objectForKey:name];
[self.navigationController pushViewController:view2 animated:YES];
}
my title can get a data and show it! but the image can 't what can i do?
Thee problem is with following line of code
DetailViewController *view2 = [[[DetailViewController alloc] initWithNibName:nil bundle:nil] autorelease];
as you are initialising DetailViewController with nib pointed to nil.
Specified nib name here
DetailViewController *view2 = [[[DetailViewController alloc] initWithNibName:#"SPECIFIED NIB NAME HERE" bundle:nil] autorelease];
First, you should consider using only ARC in your program. In .h you're defining your property as:
#property (strong, nonatomic)id titletwo;
using stong but then in ViewController you're using autorelease:
DetailViewController *view2 = [[[DetailViewController alloc] initWithNibName:nil bundle:nil] autorelease];
Second: things to check: put a breakpoint at view2.Viewimage = [tmpDict objectForKey:thumbnail];and print the content of [tmpDict objectForKey:thumbnail]writing in lldb window:
po [tmpDict objectForKey:thumbnail]
That will print the value returned. If it's nil, there's no key thumbnail in that object. Maybe you misspell that thumbnail constant.
Third: self.ViewImage looks like a UIImage, but you're using description here. Are you sure you know which type is everything? You're using ids...
I am using following code to set the text of a UILabel in SViewController, From another ViewController FViewController
SViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SViewController"];
[vc setTextForLabel:[NSNumber numberWithInt:1];];
[self.navigationController pushViewController:vc animated:YES];
The setTextForLabel method:
-(void) setTextForLabel: (NSNumber *)text {
textLabel = [[UILabel alloc] init];
[textLabel setText:[NSString stringWithFormat:#"%#",[text stringValue]]];
NSLog(#"The text is %#", textLabel.text);
}
I have declared the property for textLabel in .h file is as follows:
#property (nonatomic, retain) IBOutlet UILabel *textLabel;
And I have also set the IBOutlet in storyboard.
Now in console I see "The text is 1", but the UI is not showing anything!
What am I doing wrong?
remove this line
textLabel = [[UILabel alloc] init];
Also, you need to link the UILabel on interface to your #property (nonatomic, retain) IBOutlet UILabel *textLabel;
Or you may add this label manually to view
textLabel = [[UILabel alloc] init];
[textLabel setText:[NSString stringWithFormat:#"%#",[text stringValue]]];
[self.view addSubView:textLabel];
First of all go put
[vc setTextForLabel:[NSNumber numberWithInt:1]];
after you push the vc.
In your xib/storyboard if your label has something written in it, remove it, leave it blank.
If that doesn't work ... leave the setText method before the push one (as you wrote it initialy) and create a NSNumber member that will hold your value and apply it in viewDidAppear like so
-(void) setTextForLabel: (NSNumber *)text{
numberValue = text; // declared in .h as NSNumber *numberValue (only make it a property if you need acces to it from outside your class)
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated]; //this is important
[textLabel setText:[NSString stringWithFormat:#"%#",[numberValue stringValue]]];
}
Your problem is linked to the view lifecycle of SViewController. When you call [.. setTextForLabel] you don't know if the controller has loaded its views (And thus your UILabel have a good chance of not being created yet)
What you should do is use a NSString property on your controller, set it with the desire text and assigned it to the UILabel in the viewDidLoad of SViewController.
in SViewController.h
#propery (strong, nonatomic) NSString *textToDisplay;
in SViewController.m
-(void)viewDidLoad
{
[super viewDidLoad];
// Here you know all Outlet are loaded and connected
textLabel.text = textToDisplay
}
I did like this
#import "FViewController.h"
#import "SViewController.h"
#interface FViewController ()
#end
#implementation FViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)do:(id)sender
{
SViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"SViewController"];
[self.navigationController pushViewController:vc animated:YES];
[vc setTextForLabel:[NSNumber numberWithInt:1]];
}
// in SViewController.h
#import <UIKit/UIKit.h>
#interface SViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
-(void) setTextForLabel: (NSNumber *)text;
#end
// SViewController.m file
#import "SViewController.h"
#interface SViewController ()
#end
#implementation SViewController
#synthesize label;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
-(void) setTextForLabel: (NSNumber *)text{
// label.text = [text stringValue];
NSLog(#"%#",label);
[label setText:[text stringValue]];
}
#end
also check your label properties in storyboard are properly set
edit: solved. see my comment why.. sorry this mess, not able to post an answer myself yet as a newbie..
iPad App: I have a table view and instantiate from the accessoryView a popover with another tableview. in the popover I want to select a cell and pass that index back to the rootView.
I implemented a protocol in PopoverController and conform RootViewController to it.
Why is that backPopover method in the root view not being called?
Any hint much appreciated!!
Edit: That storyboard reference points to a navigation controller. The popover itself works fine..
RootViewController.h
#import "PopoverViewController.h"
#interface rootViewController : UITableViewController <UIPopoverControllerDelegate, UITableViewDelegate, AddDelegate>
{
UIPopoverController *popOverController;
}
#property (nonatomic, retain) UIPopoverController *popOverController;
#property (nonatomic) PopoverContent *popoverContent;
RootView.m
-(void) backPopover:(int)index
{
NSLog(#"index sent:%i", index);
[popOverController dismissPopoverAnimated:YES];
}
// accessoryView Button
- (void) popOver:(UIButton*)paramSender
{
UITableViewCell *cell = (UITableViewCell*)paramSender.superview;
if (cell != nil)
{
//Table position for popover
UIButton *button = (UIButton *)cell.accessoryView;
if(![self popoverContent])
{
popoverContent = [[self storyboard]instantiateViewControllerWithIdentifier:#"PopoverContent"];
[popoverContent setDelegate:self];
popOverController = [[UIPopoverController alloc]initWithContentViewController:popoverContent];
popOverController.popoverContentSize = CGSizeMake(320.0, 600.0);
[popOverController setDelegate:self];
}
CGRect rect = button.frame;
[popOverController presentPopoverFromRect:rect inView:cell permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
PopoverController.h
#protocol AddDelegate <NSObject>
- (void)backPopover: (int)index;
#end
#property (nonatomic, weak) id <AddDelegate> delegate;
PopoverController.m
#synthesize delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.delegate backPopover:indexPath.row];
}
Please try this.
MyViewController *viewController=[[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
UIPopoverController* aPopover = [[UIPopoverController alloc]
initWithContentViewController:popupController];
The problem was that storyboard reference, it actually pointed to a navigation controller. Above code works like a charm.
I have a problem like this:
I have a root view which has a UIPopoverController and a button, when I click on that button, it present a tableView. My app display OK but now when I click in any row, the UIPopoverController still display and I want it dismiss.
Any help? Thanks!
This is my code:
ViewController.h
#import <UIKit/UIKit.h>
#import "UIPopoverIphone.h"
#import "TableViewController.h"
#interface ViewController : UIViewController <UIPopoverControllerDelegate, TableViewPopoverDelegate> {
TableViewController *popoverView;
IBOutlet UIButton *popButton;
UIPopoverController *pop;
}
#property (strong, nonatomic) UIPopoverController *pop;
+(void)hidePop;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize pop;
-(void)dealloc {
[pop release];
[super dealloc];
}
-(IBAction)showPop {
popoverView = [[TableViewController alloc] init];
popoverView.delegate = self;
pop = [[UIPopoverController alloc] initWithContentViewController:popoverView];
[pop setPopoverContentSize:CGSizeMake(100, 200)];
[pop setDelegate:self];
[pop presentPopoverFromRect:popButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
-(void)hidePop {
[pop dismissPopoverAnimated:YES];
}
....
#end
TableViewController.h
#import <UIKit/UIKit.h>
#protocol TableViewPopoverDelegate <NSObject>
-(void) dismissPopover;
#end
#interface TableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
NSMutableArray *itemsArray;
UITableView *tableView;
id<TableViewPopoverDelegate> delegate;
}
#property (nonatomic, retain) NSArray *itemsArray;
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, assign) id<TableViewPopoverDelegate> delegate;
#end
TableViewController.m
#import "TableViewController.h"
#implementation TableViewController
#synthesize itemsArray;
#synthesize tableView;
-(void) dealloc {
[itemsArray release];
[tableView release];
[super dealloc];
}
-(void)loadView {
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 200)];
self.view = mainView;
[mainView release];
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 100, 200) style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
}
....
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
NSLog(#"%#",[self.itemsArray objectAtIndex:indexPath.row]);
[self.delegate dismissPopover];
}
#end
With your current work flow, the ViewController have no connection with TableViewController. It looks like you are presenting the UITableViewController from the UIPopoverIphone not from the ViewController. So the delegate callback method dismissPopover needed to be implemented within the UIPopoverIphone class not the ViewController class. If you still want to dismiss the UIPopoverIphone from the ViewController, there are two options:
Using NSNotificationCenter: In the TableViewController, you can post a notification when you are ready to dismiss the popover. Then in the ViewController, you can observer that notification and dismiss the popover. In this scenario, no delegate is involved.
Setup the delegate callback from your UIPopoverIphone class and the ViewController class. So when you tap the button in the popover, it makes a callback to ViewController, you then dismiss the popover and prepare your TableViewController and present it. Here your TableViewController and the ViewController have a connection.
It appears that your root view ViewController doesn't correctly implement your TableViewPopoverDelegate. You've declared a method in that delegate called dismissPopover, but you haven't implemented it in ViewController.m.
In ViewController.m, change the hidePop function to:
-(void)dismissPopover {
[pop dismissPopoverAnimated:YES];
}
Popovers by default dismiss themselves when a tap is detected outside of their bounds.