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.
Related
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];
}
I want to build an app for playing local audio files on the iPhone but I'm stuck with some of my codes.
I'm wondering how you can push a view, come back to the uitableviewcontroller and use a button ( like the "NOW PLAYING" button in the media player) to come back to the view without pushing any new string into it..
THANK YOU
What should I change from my codes ?
in the uitableviewcontroller..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath {
selectedSong = [directoryContent objectAtIndex:indexPath.row];
NSString *storyLin = [[directoryContent objectAtIndex:[indexPath row]] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
patch = [NSString stringWithFormat:#"/%#", storyLin];
myDetViewCont = [[mPlayerViewController alloc] initWithNibName:#"mPlayerViewController" bundle:nil];
myDetViewCont.myProgLang = selectedSong; // assigning the correct value to the variable inside DetailViewController
[self.navigationController pushViewController:myDetViewCont animated:YES];
[myDetViewCont release]; // releasing controller from the memory
}
in mPlayerViewController.m
-(IBAction) backtoplayer{
myDetViewCont = [[mPlayerViewController alloc] initWithNibName:#"mPlayerViewController" bundle:nil];
}
If you have pushed a view onto the navigation controller, just pop it to review the view underneath.
That is, the view you push myDetViewCont should just be popped in the backtoplayer call.
- (IBAction)backToPlayer:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
To Add to what Mark said.
Once you've popViewControllerAnimated and the user want to push the same controller again, you just need to keep the mPlayerViewController rather than release it.
Such as:
if (!myDetViewCont)
{ // We only need to create it once.
myDetViewCont = [[mPlayerViewController alloc] initWithNibName:#"mPlayerViewController" bundle:nil];
}
myDetViewCont.myProgLang = selectedSong;
[self.navigationController pushViewController:myDetViewCont animated:YES];
// no longer release here, move the release call to the dealloc
i have a main table view. and a DetailView. when cell is clicked, DetailView of that cell comes which shows details of that cell. DetailView has two buttons next and previous. I wanna know how to disable a detail view button from RootViewcontroller.m. code looks like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *nextController = [[DetailViewController alloc] init];
int storyIndex = [indexPath indexAtPosition:[indexPath length] -1];
nextController = [nextController initWithObjectAtIndex:storyIndex inArray:stories];
NSString *storyTitle = [[stories objectAtIndex:storyIndex] objectForKey:#"title"];
nextController.title = #"Details";
UIBarButtonItem *tempButtonItem = [[[UIBarButtonItem alloc] init] autorelease];
tempButtonItem.title = #"Back";
self.navigationItem.backBarButtonItem = tempButtonItem ;
nextController.sTitle = storyTitle;
[self.navigationController pushViewController:nextController animated:YES];
[nextController release];
}
i have already tried nextController.next.enabled=NO and [nextController.next setEnabled:NO] after this line:
[self.navigationController pushViewController:nextController animated:YES];
where next is the UIBarButtonItem name which is in DetailViewController.
can anybody tell me how to disable that button.
thanx in advance
Viewcontrollers and views are not loaded at the same time. What this means is that when you instantiate an object of DetailViewController in your case, the views are not drawn(and if you are using Nib's) loaded, this is part of the lazy loading concept.
So the first time you send the message setEnabled = NO, the object will be nil(sending messages to objects that are nil is allowed in Objective C).
Example:
[nextController setEnabled:NO] is equal to [nil setEnabled:NO] and this is surely not what you want.
The next time, unless a memory warning and the views are unloaded, the views will be in memory and the reference to the button will no longer be nil so the second time you invoke it, it will work.
And add the code line above the pushViewController:animate
If you want to initialize the button to be disable you may put this code in the viewDidLoad/viewWillAppear depending on the context of your application.
This is only one possible solution.
Edited answer to request in comment:
In your initializer method in the DetailviewController add this:
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(backToRoot)] autorelease];
- (void)backToRoot {
[self.navigationController popToRootViewControllerAnimated:YES];
}
and also add the method-signature to your headerfile.
Reference to the UINavigationController: http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
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];
}
}
i have just converted an app i was making from a navigation controller app into a tab bar app.
an everything works fine apart from this one thing, the first of my tabs brings in a table view,and what i want to happen is when a user selects a cell i want it to push on a different view controller(like it did when it was a navigation app)
but this no longer seems to work, am i doing something silly
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
StoryDetailViewController *storyDetailViewController = [[StoryDetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
WorldCupAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
Story *aStory = [appDelegate.stories objectAtIndex:indexPath.row];
NSURL *url = [NSURL URLWithString:aStory.picture];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
storyDetailViewController.downloadedImage = img;
storyDetailViewController.story = [appDelegate.stories objectAtIndex:indexPath.row];
[self.navigationController pushViewController:storyDetailViewController animated:NO];
NSLog(#"view controller pushed");
[StoryDetailViewController release];
}
The problem is in self.navigationController. Since it's no longer part of a navigation controller, navigationController is nil. If you want to push new views onto the hierarchy, you can do so by creating a navigation controller with that view as its root view controller, and then adding the navigation controller's view to the tab bar instead.