Display Loading Image on didSelectRowAtIndexPath - iphone

I am trying to have my activity indicator start animating as soon as the user clicks on a row in my tableview. My problem is that the activity indicator doesn't start animating right away. My understanding is that the UI is not updated and the activity indicator does not start animating until all of the operations in the didSelectRowAtIndexPath are completed.
How can I edit this block of code to animate the activity indicator right when the user clicks a row?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
// Activity Indicator
[activityIndicator startAnimating];
NSDictionary *item;
if (tableView == self.searchDisplayController.searchResultsTableView) {
item = [[NSDictionary alloc] initWithDictionary:[filteredListItems
objectAtIndex:indexPath.row]];
} else {
item = [[NSDictionary alloc] initWithDictionary:[listItems
objectAtIndex:indexPath.row]];
}
//Push to New View Controller
DetailViewController *detailViewController = [[DetailViewController alloc]
initWithNibName:#"DetailViewController" bundle:nil];
profileViewController.newsArticle = item;
[self.navigationController pushViewController:detailViewController animated:YES];
}
I have been fiddling with these bits of code, but don't know how to tie it all together. Any help would be great! Thank you!
[self performSelector:#selector(pushDetailView:) withObject:tableView afterDelay:0.1];
- (void)pushDetailView:(UITableView *)tableView {
// Push the detail view here
}

Might not be a solution, but a possible workaround.
Move your "rest of the code here" to a separate method and call it with a delay using
self performSelector: withObject: afterDelay:
I hope this will let your loading image view to appear before performing the selector.
update:
I would suggest you to something like below, after determining item pass it to the delayed method and leave the rest to it.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath
{
// Activity Indicator
[activityIndicator startAnimating];
NSDictionary *item;
if (tableView == self.searchDisplayController.searchResultsTableView) {
item = [[NSDictionary alloc] initWithDictionary:[filteredListItems
objectAtIndex:indexPath.row]];
} else {
item = [[NSDictionary alloc] initWithDictionary:[listItems
objectAtIndex:indexPath.row]];
}
[self performSelector:#selector(pushDetailView:) withObject:item afterDelay:0.1];
}
- (void)pushDetailView:(id)item {
// Push the detail view here
//Push to New View Controller
DetailViewController *detailViewController = [[DetailViewController alloc]
initWithNibName:#"DetailViewController" bundle:nil];
profileViewController.newsArticle = item;
[self.navigationController pushViewController:detailViewController animated:YES];
}

Related

UIActivityIndicator in tableviewcell Showing Up Late when loading the detailview?

I have a tableview with responding detialview. In the detailview I have some images and labes that is loaded from a URL. I'm trying to add a UIActivityindicatorview to the cell to show that is loading. I have handled that but it shows up to late and does not disappear when I go back to the tableview. I have looked all over to find a simple solution, but failed...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ReaDetailViewController *reaDetail = [[ReaDetailViewController alloc] initWithNibName:#"ReaDetailViewController" bundle:nil];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIActivityIndicatorView *activityView =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[activityView startAnimating];
[cell setAccessoryView:activityView];
[activityView release];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
{
reaDetail.petImageString = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"image"]];
reaDetail.petLabelString = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"description"]];
reaDetail.petLabelString1 = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"description1"]];
reaDetail.petLabelString2 = [[NSString alloc] initWithString:[[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"description2"]];
reaDetail.title = [[exclusiveArray objectAtIndex:indexPath.row] objectForKey:#"name"];
}
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:reaDetail animated:YES];
[reaDetail release];
}
Any help is very helpful !
I understand that you want to make the activity view to be animated while you load your view controller. The problem is the activity view won't start animating until you return from this selection method... which is about the time when your controller is ready to be pushed.
2 options then:
You could exit from the method asap, calling perfomSelector:onMainThread to do the init steps of the view controller to be pushed
Or even better, push the view controller asap, and do its init process in the viewDidLoad or viewWillAppear methods of this controller (you can add the activity controller in this new view).
If you pick the 1st option, you should call the deselectRowAtIndexPath method after you've pushed the new view controller and call stopAnimating on the indicator view from this deselectRowAtIndexPath method.

Reusing detailed view controller in UISplitViewController

Basically when I implement a split view like the one presented in the Apple example 'MultipleDetailsViews', everything works fine, it allocates a new detailed view each time a row is selected. Here is the relevant code from the example:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:#"FirstDetailView" bundle:nil];
detailViewController = newDetailViewController;
}
// ...
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
// ...
}
But what I'm looking for is reusing detailed view controllers, that is lazily allocating a view controller when it is selected, and keeping a reference on it in my object. That way when another row is selected the view controller is not deallocated and when it is selected again it would be reused instead of allocating a new one. Here is the relevant code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
if (self.firstDetailViewController == nil) {
FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:#"FirstDetailView" bundle:nil];
self.firstDetailViewController = newDetailViewController;
[newDetailViewController release];
}
detailViewController = self.firstDetailViewController;
}
// ...
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
// ...
}
self.firstDetailViewController is instanciated the first time the first row is selected then it is reused.
When I'm doing that it works well in landscape mode but in portrait mode after a few clicks in the popover menu it raises an exception: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Popovers cannot be presented from a view which does not have a window.'
So why I care? and why I don't want to reallocate view controllers? because in some of them I want to perform tasks that wouldn't be interrupted (killed) if the user navigate in a new detailed view while the task isn't completed yet.
Is there someone with an idea of what happens or with a working implementation of what I'm trying to achieve?
The view controllers are designed to be created and thrown away, if you need something to run in the background for longer then best move it into the master view controller or a separate object.
If you do however want to experiment with reusing a view controller this can be achieved by setting the viewControllers property on the new navigation controller with the previous detail controller saved in the viewDidLoad:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
UINavigationController* navigationController = (UINavigationController*)[segue destinationViewController];
// reuse existing controller
navigationController.viewControllers = #[self.detailViewController];
// update the detail controller as normal.
[controller setDetailItem:object];
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
controller.navigationItem.leftItemsSupplementBackButton = YES;
}
}

How can I move to another view controller when the user clicks on a row?

I am new to iPhone development, and I want to move to another page when the user clicks on a particular row. So, if they click on first row, I want the page to redirect to the first view controller, and so on. Each row has its own view controller.
first of all you don't need to set different view controller for each row (unless you have a very good reason for doing that).
the correct way is to set 1 view controller that will fit all the cells in the raws and change its data according to the selected row.
the way you do that is:
in the - DidSelectRowAtIndexPath function in your implementation file you shuld:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//allocate your view controller
DetailedViewController *detailedViewController = [[DetailedViewController alloc] init];
//send properties to your view controller
detailedViewController.property1 = someProperty1;
detailedViewController.property2 = someProperty2;
//push it to the navigationController
[[self navigationController] pushViewController:detailedViewController animated:YES];
[detailedViewController release];
}
i do recommend that you will start by using apple examples, they are great and there are a lot of them :
http://developer.apple.com/library/ios/#samplecode/TableViewSuite/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40007318
Good luck
#kashyap in didSelectRowAtIndexPath delegate of the UITableView you have to check the conditions that on which indexPath you are clicking and open the viewControllers you had made accordingly
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here -- for example, create and push another view controller.
FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
switch (indexPath.row) {
case 0:
[self.navigationController pushViewController:firstViewController animated:YES];
[firstViewController release];
break;
case 1:
[self.navigationController pushViewController:secondViewController animated:YES];
[secondViewController release];
break;
}//Likewise do for the no of rows you have in your `UITableView`
Hope you get my point.....Good Luck!
Dig into the docs:
http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/TableView_iPhone/ManageSelections/ManageSelections.html#//apple_ref/doc/uid/TP40007451-CH9-SW6
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
switch (indexPath.row) {
case "X"
// Allocate the viewController
[navigationcontroller.pushViewController:"yourviewcontroller" animated:YES];
[release "yourviewcontroller"];
break;
default:
break;
}
}
EDIT: Didn't realize of what you're trying. As shani said, you should not create a viewcontroller for each row if there is no need to. Try changing the datasource for each row but using the same viewcontroller. So forget this implementation.
Easy:
Create and push your view controller in this delegate function:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
It sounds like using a UINavigationController is what you want.
You then push your "first view" on to the navigation controller's stack from the table view, e.g., from you UITableView delegate:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
// indexPath.row == 0
FirstViewController* firstVC = [[FirstViewController alloc] initWithNibName...];
[self.navigationController firstVC animated:YES];
[firstVC release];
...
}
This was the one the things that I got problem when I first start. Here is my code that I use for this.
In subviewcontroller I have my own constructor like
-(id)initWithName:(NSString*)naMe
{
name=naMe;
return self;
}
And in didSelectRowAtIndexPath Delegate method Of UITableView. I alloc it
MyListView mylistview=[[MyListView alloc] initWithName:#"name"];
[self.navigationController pushViewController:mylistview animated:YES];
[mylistview release];
NSInteger row = indexPath.row;
UIViewController *newFrontController = nil;
if (row == 0)
{
YourViewController *yourViewController = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
newFrontController = [[UINavigationController alloc] initWithRootViewController:peopleViewController];
[self.navigationController setNavigationBarHidden:YES];
} else if(row == 1){
//do your code
}
do this in didSelectRowAtIndexPath in tableView.
You can move to another page when user tap on row by simply making segue by "Control Drag" from cell to ViewController and make segue type "Push".

TableView help pushing a custom view

So I am trying to simple traverse to the next level of a table view by doing this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 1) {
FiltersController *aFiltersCont = [[FiltersController alloc] init];
aFiltersCont.displayedFilters = [appDelegate.groupedBusiness allKeys];
aFiltersCont.currentLevel = self.currentLevel + 1;
[self.navigationController pushViewController:self animated:YES];
}
}
is there any reason why this would not be pushing the controller? I had a similar problem before, but solved it by displaying the view modally. However, this time, this is in a popover and needs to slide to the next screen inside that popover. Any Ideas? Thanks in advance.
OK I am going to put some more source up here to try and help...
Inside the main view controller I have this code to make the popover from a button:
// Create and configure the filters controller.
FiltersController *aFiltersController = [[FiltersController alloc] initWithStyle:UITableViewStylePlain];
self.filtersController = aFiltersController;
filtersController.appDelegate = self.appDelegate;
UINavigationController *filtersNavController = [[UINavigationController alloc] initWithRootViewController:filtersController];
UIPopoverController *filtersPopover = [[UIPopoverController alloc] initWithContentViewController:filtersNavController];
self.filtersPopoverController = filtersPopover;
filtersPopoverController.delegate = self;
and then I have the code I first posted in my filtersController class. Does that help at all?
[self.navigationController pushViewController:self animated:YES];
Should be
[self.navigationController pushViewController:aFiltersCont animated:YES];
If you are just displaying your sublcass of UITableViewController inside a UIPopoverController, the UINavigationController will not be created for you automatically. You may need to modify the code where you are creating the UIPopoverController with something like this:
MyTableViewController *table = [[[MYTableViewController alloc] init] autorelease];
UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:table] autorelease];
myPopover = [[UIPopoverController alloc] initWithContentViewController:nav];
Then you should be able to push and pop navigation controllers on the stack no problem.
you are pushing self which is a reference to the current view controller. you should change the line with the push to the following if aFiltersCont is the viewController you are trying to drill to.
[self.navigationController pushViewController:aFiltersCont animated:YES];
You might be confused about the index. The first index is 0 not 1, so maybe you want indexPath.row == 0?
Also, you should release aFiltersCont before returning (you're leaking a FiltersController and anything it owns every time you run this method.
So maybe this?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
FiltersController *aFiltersCont = [[[FiltersController alloc] init] autorelease];
aFiltersCont.displayedFilters = [appDelegate.groupedBusiness allKeys];
aFiltersCont.currentLevel = self.currentLevel + 1;
[self.navigationController pushViewController:aFiltersCont animated:YES];
}
}

commit object to next TableViewController

i got a tableview controller.
if a cell is selected i perform the following:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ablogSingleCatTableViewController *singleCatTableViewController = [[ablogSingleCatTableViewController alloc] initWithStyle:UITableViewStylePlain];
// Push the detail view controller.
[[self navigationController] pushViewController:singleCatTableViewController animated:YES];
[singleCatTableViewController release];
}
i want to commit an object to the next view controller that slides in after this row is selected.
do i have to do something like this?
ablogSingleCatTableViewController *singleCatTableViewController = [[ablogSingleCatTableViewController alloc] initWithStyle:UITableViewStylePlain];
[singleTableViewController setMyObject:superDuperObject];
or is there an easier way to do something like that?
i need this object directly after this tableviewcontroller is initialized, to fill it with specific data that belongs to this object.
please give me some advices.
thanks
You can also pass the object to the next view controller when you init the view controller.
To do so, you need to implement your own initializer for the view controller.
For example:
- (id)initWithStyle:(UITableViewStyle)style superDuper:(SuperDuper*)superDuperObject {
if (self = [super initWithStyle:style]) {
superDuper = superDuperObject;
}
return self;
}
Then,
ablogSingleCatTableViewController *singleCatTableViewController =
[[ablogSingleCatTableViewController alloc] initWithStyle:UITableViewStylePlain superDuper:superDuperObject];