Show tableView popover as soon as data is loaded - ios

i want to show a my Popover with a TableView just from the beginning, when the app loads. Problem is that the tableView doesn't have any content then. I am using that method:
UIBarButtonItem *barItem = [self.toolbar.items objectAtIndex:0];
[self.popoverController presentPopoverFromBarButtonItem:barItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
Now, my idea was to have a delegate method which is fired when the tableView finished fetching the data, but unfortunately nothing happens:
RootViewController.h:
#protocol RootDelegate <NSObject>
#optional
-(void)didFinishLoading;
#end
RootViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView initWithFrame:self.tableView.frame style:UITableViewStyleGrouped];
self.clearsSelectionOnViewWillAppear = NO;
[self setTitle:#"Zielscheiben"];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(dataSaved:) name:#"DataSaved" object:nil];
[[self delegate] didFinishLoading];
}
DetailViewController.m (conforms to the protocol)
- (void)didFinishLoading
{
UIBarButtonItem *barItem = [self.toolbar.items objectAtIndex:0];
[self.popoverController presentPopoverFromBarButtonItem:barItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

The table view methods are threaded so your call at the end of viewDidLoad will happen at an unpredictable time, apparently here before the table is filled. I can't see any delegate method refering to the event "table is filled", so my best guess would be to keep your code and delay its execution :
[[self delegate] performSelector:#selector(didFinishLoading) withObject:nil afterDelay:1]
assuming 1 second will be enough for the table to be filled.
Another option you could explore is to fire it sometime in cellForRowAtIndexPath when you reckon the table has got enough data, but this is somehow more complex.

You need to place your popover in viewDidAppear:
- (void)viewDidAppear {
UIBarButtonItem *barItem = [self.toolbar.items objectAtIndex:0];
[self.popoverController presentPopoverFromBarButtonItem:barItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
viewDidAppear gets called after your UITableView has finished calling its datasource and tableview delegate methods.

Related

PresentViewController takes a lot of time

I have a really strange situation: a view controller, called by presentViewController takes a lot of time to load. I mean that preparation stage takes a lot of time, though whole animation performed quickly. Going back from the presented controller to the previous one is fine.
What clues to I have?
First af all, I prepared my next view controller in first viewWillAppear:
METAddEventViewController *controller = [self.storyboard
instantiateViewControllerWithIdentifier:#"addEventView"];
self.nextController =
[[UINavigationController alloc] initWithRootViewController:controller];
Where self.nextController is nonatomic and strong.
So, my method that calls the next controller is pretty simple:
- (IBAction)addMeetingButtonPressed:(id)sender {
[self.addMeetingButton setImage:[UIImage imageNamed:#"addMeeting-pressed#2x.png"] forState:UIControlStateNormal];
[self presentViewController:self.nextController animated:YES completion:^{
NSLog(#"Completed");
}];
}
METAddEventViewController is just a UITableViewController with static cells of 4: 2 Basic cells, 1 cell with UIDatePicker and 1 with UITextView.
So, my viewDidLoad and viewWillAppear:
- (void)viewDidLoad
{
self.appointMeetingButton.enabled = NO;
self.title = #"Create Meeting";
self.commentaryView.delegate = self;
[super viewDidLoad];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[self navigationController] setNavigationBarHidden:NO animated:NO];
self.commentaryView.text = #"Enter comment for the meeting if needed";
self.commentaryViewFilled = NO;
self.commentaryView.textColor = [UIColor lightGrayColor];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateSelectedPersonCalled:)
name:#"updateSelectedPersonLabel"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(updateSelectedPersonCalled:)
name:#"updateSelectedLocationLabel"
object:nil];
[self.datePicker addTarget:self action:#selector(meetingAppointable) forControlEvents:UIControlEventValueChanged];
}
I ran Profiling and noticed that the most time consuming operations are allocation ones. Though, both viewDidLoad and viewWillAppear of METAddEventController are fine - about 10 ms. Most of the time in them takes configuring self.commentaryView
What can I do? Which additional information can I present to find the solution?

UITableView does not refresh after returning from its child view

I'm reading the Big Nerd Ranch's book and I have written a little app using UITableView. Let the UITableView shows the items in the inventory. When didSelectRowAtIndexPath:, it enters a subview and you can edit the properties of item here, which is detailViewController. Afterwards you can go back to UITableView via the navigation controller's back button.
However it doesn't refresh after pressing back button at first. You have to go to a detailViewController and come back to see the change, it's not important whether it is same item.
Navigation goes like: ItemsViewController > DetailViewController
ItemsViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:#"UITableViewCell"];
UIView * header = self.headerView;
[self.tableView setTableHeaderView:header];
self.tableView.delegate = self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
}
DetailViewController.m
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
// Clear first responder
[self.view endEditing:YES];
// Save "changes" to the item
BNRItem * item = self.item;
item.itemName = self.nameField.text;
item.serialNumber = self.serialNumberField.text;
item.valueInDollars = [self.valueField.text intValue];
}
Thoughts?
You should change the values in viewWillDisappear: method in DetailViewController. viewWillAppear: method of ItemsViewController executes before viewDidDisappear: of DetailViewController, therefore your BNRItem changes after the table is refreshed.

Dismissing UIPopoverController with UINavigationController

I'm currently building an iPad app in which I need to implement a pop over view.
I have set up a view controller like I always do:
Create UIViewController wit xib file
set the xib up and do the necessary programming in it's .h & .m files
now in the view controller I'm loading it from (from a UIBarButtonItem), I have this code:
- (void) action
{
ItemContent *newItem = [[ItemContent alloc] initWithNibName:#"ItemContent" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:newItem];
_popover = [[UIPopoverController alloc] initWithContentViewController:nav];
[_popover setPopoverContentSize:CGSizeMake(557, 700) animated:YES];
_popover.delegate = self;
[_popover presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
This properly displays my view- and UINavigationController in a UIPopOverController. So far so good!
In the newItem view controller, I have made a bar button in my navigation bar that says "Done". When that button is pushed, I want the UIPopOverController to disappear. How do I do this:
Set a method for when te button is pushed. In this method I want to call a function on the view controller that loaded the Popover to dismiss it again.. but how do I do this?
Put things shortly
How do I make my UIPopOverController call a method on the view controller that loaded the UIPopOverController?
I have been searching SO for a while but none of the solutions and answers solve my problem. If I missed something please inform me ;)
Thank you so much in advance!
You can do this by delegate...
In NewItem.h declare a protocol
#protocol NewItemDelegate
-(void)onTapDoneButton;
#end
Now create a delegate property like this
#property (nonatomic, assign) id<NewItemDelegate>delegate;
In NewItem.m in doneButtonPuhsed method call this
[self.delegate onTapDoneButton];
Change this method a bit
- (void) action
{
ItemContent *newItem = [[ItemContent alloc] initWithNibName:#"ItemContent" bundle:nil];
newItem.delegate =self;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:newItem];
_popover = [[UIPopoverController alloc] initWithContentViewController:nav];
[_popover setPopoverContentSize:CGSizeMake(557, 700) animated:YES];
_popover.delegate = self;
[_popover presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
Now implement NewItemDelegate method below this action method.
-(void)onTapDoneButton{
//dismiss popover here
}
I had this problem too and solved it using notifications.
In your parent controller, in viewDidLoad method, you have to add an observer:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(closePopover)
name:#"closePopoverName"
object:nil];
Then, in your viewDidUnload method you remove the observer like this:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Of course, you have to create the function which actually dismisses the popover:
- (void) closePopover
{
[_popover dismissPopoverAnimated:YES];
}
Then, in your ItemContent controller, you just post a notification when you want to close the popover:
[[NSNotificationCenter defaultCenter] postNotificationName:#"closePopoverName" object:self userInfo:nil];
You could define a protocol on ItemContent and use it on your CallerViewController. If you want to close your Popover, just call your delegate method, which you will implement on your CallerViewController

How to send a next button, to a UITableView

I am trying to get a UITableView to show up after I tap a next button, I can't get it to work...
I don't know why TimesViewController.m isn't working, how do I link it...
-(IBAction)nextView:(UIBarButtonItem *) sender{
[self pushViewController:TimesTableViewController.m animated:YES];
}
You need to read through View Controller programming guide. Essentially, it depends more on your application design. The most common ways of doing this are:
Tap on nextView should present TableView controller modally.
Tap on nextView should push TableView controller in the navigation stack.
With either of the approach, you need to create a separate view controller for your table view which will manage the table view and act as delegate/data source for it.
From within your button action handler you need to do it this way:
-(IBAction)nextView:(UIBarButtonItem *) sender{
MyTableViewController *tableController = [[MyTableViewController alloc] init];
// For #1 above
[self presentViewController:tableController animated:YES completion:^{
// Any code that you want to execute once modal presentation is done
}];
// For #2 above
[self.navigationController pushViewController:tableController animated:YES];
}
EDIT:
Create a initialize method on your MyTableViewController and pass the values while calling it.
- (id)initWithData1:(NSString *)iData1 data2:(NSString *)iData2 {
if ((self = [super init])) {
self.data1 = iData1;
self.data2 = iData2;
}
return self;
}
MyTableViewController *tableController = [[MyTableViewController alloc] initWithData1:#"Some String" data2:#"Another string"];
PS: You could also expose the string property in your header file of MyTableViewController and set it from the callee class
or if you wanna do it programmatically, in your viewDidLoad, after you created your button
[firstsessionButton addTarget:self action:#selector(showtable:) forControlEvents:UIControlEventTouchUpInside];
-(void)showtable:(UIButton *)sender{
TableViewController *tableViewController=[[TableViewController alloc]init];
[self.navigationController pushViewController:tableViewController animated:YES];
}

UIPopoverController deallocated issue

I used a Popover to display image in it. When the user touch a button, the popover appears with a slideshow inside.
I initialize the Popover like this : `
- (IBAction)showPopover:(UIButton *)sender {
myPopover *content = [[myPopover alloc] init];
detailViewPopover = [[UIPopoverController alloc] initWithContentViewController:content];
detailViewPopover.popoverContentSize = CGSizeMake(600., 400.);
detailViewPopover.delegate = self;
[detailViewPopover presentPopoverFromRect:sender.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[content release];
}
`
detailViewPopover is a UIPopoverController, I declare it my .h.
I dismiss the Popover like this : `
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
// If a popover is dismissed, set the last button tapped to nil.
[popoverController release];
}`
When I run my app, it works until I got "-[UIPopoverController release]: message sent to deallocated instance 0x1b29b0" and my apps crashes...
I understand I release too much time my UIPopoverController, but I don't know where. Is my implementation good ?
Thanks for your help
Let me know if you need more information, I will edit the post
You shouldn't release your popoverController here.
You need to call release on detailViewPopover in your current view controllers dealloc method
- (void) dealloc
{
[detailViewPopover release];
[super dealloc];
}

Resources