I have set up a subview "popup" in my application and I want to show a navController if the user taps a button on the subview popup. I've set up the button so far, but if I tap the button the navigationController appears under my popup!? I've searched for some solution but I didn't found any. The whole controller is actually displayed in a folder which you can find here: https://github.com/jwilling/JWFolders So the viewDidLoad belong to the folder and the rootview.
I tried to make it as a subview of the popup but that doesn't work too. Does anyone know how to treat that? I've set up the popup programmaticaly and the navigationController too.
Thanks in advance.
My code:
The navController setup:
- (IBAction)dothis:(id)sender {
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
// Set browser options.
browser.wantsFullScreenLayout = YES;
browser.displayActionButton = YES;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:browser];
[self presentModalViewController:navController animated:YES];
NSMutableArray *photos = [[NSMutableArray alloc] init];
MWPhoto *photo;
photo = [MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"star" ofType:#"png"]];
photo.caption = #"The star is soo beateful...";
[photos addObject:photo];
self.photos = photos;
}
- (MWPhoto *)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
if (index < _photos.count)
return [_photos objectAtIndex:index];
return nil;
}
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
return _photos.count;
}
The popup code:
-(IBAction)mehr:(id)sender {
//the popup size and content
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 280, 440)];
CGRect welcomeLabelRect = contentView.bounds;
welcomeLabelRect.origin.y = 20;
welcomeLabelRect.size.height = 40;
UILabel *welcomeLabel = [[UILabel alloc] initWithFrame:welcomeLabelRect];
//an simple activityindicator
activityindi = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityindi.frame = CGRectMake(120, 200, 40, 40);
[activityindi startAnimating];
[contentView addSubview:activityindi];
//The Imageview
CGRect infoimagerect = CGRectMake(5, 70, 270, 200);
UIImageView *infoimage = [[UIImageView alloc] initWithFrame:infoimagerect];
//and the Button
cubut = [UIButton buttonWithType:UIButtonTypeCustom];
[cubut addTarget:self
action:#selector(dothis:)
forControlEvents:UIControlEventTouchUpInside];
[cubut setTitle:nil forState:UIControlStateNormal];
cubut.frame = CGRectMake(5, 70, 270, 200);
//retrieving data from parse.com
PFQuery *query = [PFQuery queryWithClassName:#"My-Application"];
[query getObjectInBackgroundWithId:#"My-ID"
block:^(PFObject *textdu, NSError *error) {
if (!error) {
//hide the Button if there is no image
cubut.hidden=YES;
//the headline of popup
UIFont *welcomeLabelFont = [UIFont fontWithName:#"copperplate" size:20];
welcomeLabel.text = [textdu objectForKey:#"header"];
welcomeLabel.font = welcomeLabelFont;
welcomeLabel.textColor = [UIColor whiteColor];
welcomeLabel.textAlignment = NSTextAlignmentCenter;
welcomeLabel.backgroundColor = [UIColor clearColor];
welcomeLabel.shadowColor = [UIColor blackColor];
welcomeLabel.shadowOffset = CGSizeMake(0, 1);
welcomeLabel.lineBreakMode = UILineBreakModeWordWrap;
welcomeLabel.numberOfLines = 2;
[contentView addSubview:welcomeLabel];
//the image from parse
if (!error) {
PFFile *imageFile = [textdu objectForKey:#"image"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
UIImage *image = [UIImage imageWithData:data];
infoimage.image = image;
infoimage.contentMode = UIViewContentModeScaleAspectFit;
//show the button when the image appears
cubut.hidden = NO;
[contentView addSubview:infoimage];
//stop the activityindicator
[activityindi stopAnimating];
}
}];
}
} else {
//show some text
welcomeLabel.text = #"No connection!";
[welcomeLabel sizeToFit];
//hide the button
cubut.hidden = YES;
[contentView addSubview:infoLabel];
//stop the activityindicator
[activityindi stopAnimating];
}
}];
//add the content to the KNGModal view
[[KGModal sharedInstance] showWithContentView:contentView andAnimated:YES];
}
My viewDidLoad
- (void)viewDidLoad
{
but.hidden = YES;
PFQuery *query = [PFQuery queryWithClassName:#"myapp"];
[query getObjectInBackgroundWithId:#"Rgq5vankdf"
block:^(PFObject *textu, NSError *error) {
if (!error) {
but.hidden = NO;
but.color = [UIColor colorWithRed:0.90f green:0.90f blue:0.90f alpha:1.00f];
} else {
//if failure
but.hidden = YES;
mol.text = #"No Connection";
}
}];
[super viewDidLoad];
}
Pictures:
The button to open the folder:
The folder itself:
The popup:
Thanks in advance.
From the so far discussion and debugging the code you want to have the photo browser on the pop-up with a navigation controller.
So here is the sample code which implements this functionality, have a look at it.
I have used the same KGModal sample code and extended as per the requirement. I have used Xib to have a view with navigation bar.
To dismiss the pop-up from any where in the app you can use the below line, as it is shared instance.
[[KGModal sharedInstance] hideAnimated:YES];
Update:
The reason for showing the photo browser with in folderView is, you are trying to present the photoBrowser within the folderView, so it was presenting within the folderView of very small height & not able to see any photo.
So my suggestion is, as the user taps on pop-up to view photoBrowser you just remove pop-up and present the photoBrowser from the viewController class, as other than this class everything is handled through views.
I have made the changes as per above & works fine, to the code given by you, download the code here and have a look at it.
Let me know if it fulfills your needs.
Thanks
I noticed this line of code:
[[KGModal sharedInstance] showWithContentView: contentView andAnimated: YES];
And I can only think that, since it is a singleton, it adds the contentView on the UIApplication's key window. If that is the case, then a modal view controller will always be below the popup. You can solve this by adding a new method to the KGModal class
- (void) showWithContentView: (UIView*) contentView
inViewController: (UIViewController*) controller
andAnimated: (BOOL) animated;
the method should show the popup in the specified controller's view; you should use that method instead.
Edit
After some more digging, I found that KGModal displays the popup on another window. The quickest fix would be to dismiss the popup, then show the nav controller.
Related
I am using AsyncImageView classes to apply lazy loading on UITableView. And want to apply activity indicator on image view until the image is loaded on cell. Below is my code i am trying.
// AsyncIamgeView.m
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection {
//[connection release];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
indicator.center = CGPointMake(15, 15);
connection=nil;
if ([[self subviews] count]>0) {
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImage *imgData = [UIImage imageWithData:data];
UIImageView* imageView = [[UIImageView alloc]init];
[imageView addSubview:indicator];
[indicator startAnimating];
if(imgData == nil)
{
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"NoImagenew.png"]];
//[indicator stopAnimating];
}
else{
imageView = [[UIImageView alloc] initWithImage:imgData];
// [indicator stopAnimating];
}
//imageView.contentMode = UIViewContentModeScaleAspectFit;
//imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight );
//[imageView sizeToFit];
[self addSubview:imageView];
imageView.frame = self.bounds;
//imageView.frame = CGRectMake(0, 0, 85, 94);
[imageView setNeedsLayout];
[self setNeedsLayout];
//[data release];
data=nil;
}
// cellForRowAtIndexPath method.
asyncImageView = [[AsyncImageView alloc]initWithFrame:CGRectMake(1, 3, 85, 54)];
[asyncImageView loadImageFromURL:[NSURL URLWithString:imageUrlString]];
[cell.contentView addSubview:asyncImageView];
This code shows activity indicator but when image is loaded after that not before loading images. Please guide for above.
You have to create AsyncImageView object instead of UIImageView, then it will automatically add indicator to your view
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(1, 3, 85, 54)];
[cell addSubview:imageView];
//cancel loading previous image for cell
[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget:imageView];
//load the image
imageView.imageURL = [imageURLs objectAtIndex:indexPath.row];
Here is an example of this
Currently you are adding activity indicator when your image is downloaded.
Here is the simple idea, hope you can implement this in your code
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// This method is called when your connection receives a response
// add your activity indication here and start animating
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// This method is called when your image is downloaded.
// remove your activity indicator or stop animating here
}
Hope u downloaded AsyncImageView from https://github.com/nicklockwood/AsyncImageView. By default, it has the feature to show activity indicator. You just dont need to add or remove any code by yourself to get this feature works. Just call loadImageWithURL.
I think u are using asynimageview classs, In that by default you will get the loader in the cell itself .
AysncImageView already has a loader.
You won't see it if your background is black since it loads the default activity indicator.
So, just set the activityIndicatorStyle property for your AsyncImageView object based on your background.
In my case, my background was black, so I used the following code :
asyncImgView.activityIndicatorStyle = UIActivityIndicatorViewStyleWhite;
Currently working on two introduction pages (First shows an image, second should show a website) for my iPhone app (like Pocket, for the user a little hands-on after first start).
Came across Matthew York's GitHub project which works perfectly with images and text.
Additionally I like to show a website as a part of the introduction but I can't get it working. My programmatically created UIWebView just doesn't show up.
Matthew York's GitHub Project:
https://github.com/MatthewYork/iPhone-IntroductionTutorial
Complete code for showing the two introduction pages is shown below.
Please mind that panelImage works as expected but not panelView.
I see the second page show up but without the UIWebView.
I think I add the subview to a view not visible on the screen therefore I don't see it. Am I right? Can you please have a look at: [view addSubview:aWebView]; in method: showWebView
ViewController.m
- (void)showIntro
{
MYIntroductionPanel *panelImage = [[MYIntroductionPanel alloc] initWithimage:[UIImage imageNamed:#"img.jpg"] description:#"TEST: IMAGE"];
MYIntroductionPanel *panelView = [[MYIntroductionPanel alloc] initWitView:[self showWebView] description:#"TEST: VIEW"];
MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) headerText:#"TESTING" panels:#[panelImage, panelView] languageDirection:MYLanguageDirectionLeftToRight];
introductionView.BackgroundImageView.image = [UIImage imageNamed:#"BG_iPad_1024.png"];
introductionView.delegate = self;
[introductionView showInView:self.view];
}
- (UIView *)showWebView
{
UIWebView *aWebView= [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 290)];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"]];
[aWebView loadRequest:requestObj];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 300)];
[view addSubview:aWebView];
return view;
}
MYIntroductionPanel.m
-(id)initWitView:(UIView *)view description:(NSString *)description{
if (self = [super init]) {
self.view = [[UIView alloc] init];
self.Description = [[NSString alloc] initWithString:description];
}
return self;
}
-(id)initWithimage:(UIImage *)image title:(NSString *)title description:(NSString *)description{
if (self = [super init]) {
self.Image = [[UIImage alloc] init];
self.Image = image;
self.Title = title;
self.Description = [[NSString alloc] initWithString:description];
}
return self;
}
The view to which you are adding your UIWebView is never added to the view hierarchy itself. You appear to be passing the UIWebView's superview to MyIntroductionPanel's initWithView:description: method, but that method just ignores its input view and creates a new one with self.view = [[UIView alloc] init]. Try setting self.view = view in your initWithView:description: method instead.
I didn't love all of the author's decisions, but followed his pattern to achieve what you're looking for.
Added the following:
// MyIntroductionPanel.h
#property (nonatomic, retain) NSURL *url;
-(id)initWithURL:(NSURL *)url;
// MyIntroductionPanel.m
-(id)initWithURL:(NSURL *)url {
if (self = [super init]) {
_url = url;
}
return self;
}
That was easy. This was less easy - hacking the layout method to deal with panels with urls. I didn't try too hard to understand this method, just added what I could to get it working. My additions are marked with // DANH
// MYIntroductionView.m
-(UIView *)PanelViewForPanel:(MYIntroductionPanel *)panel atXIndex:(CGFloat*)xIndex{
// snipped original code
NSInteger descriptionHeight = panelDescriptionTextView.contentSize.height;
int contentWrappedScrollViewHeight = 0;
if ((imageHeight + descriptionHeight + panelTitleLabelFrame.size.height) > maxScrollViewHeight) {
contentWrappedScrollViewHeight = maxScrollViewHeight;
imageHeight = contentWrappedScrollViewHeight-descriptionHeight - panelTitleLabelFrame.size.height - 10;
}
else if ((imageHeight+descriptionHeight + panelTitleLabelFrame.size.height) <= maxScrollViewHeight){
contentWrappedScrollViewHeight = imageHeight + panelTitleLabelFrame.size.height + descriptionHeight;
}
// DANH
if (panel.url) {
contentWrappedScrollViewHeight = 300;
// you can certainly do a better job than I did here, but just to get going
}
panelView.frame = CGRectMake(*xIndex, 0, self.ContentScrollView.frame.size.width, contentWrappedScrollViewHeight);
//Build image container
UIImageView *panelImageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 0, self.ContentScrollView.frame.size.width - 10, imageHeight)];
panelImageView.contentMode = UIViewContentModeScaleAspectFit;
panelImageView.backgroundColor = [UIColor clearColor];
panelImageView.image = panel.Image;
panelImageView.layer.cornerRadius = 3;
panelImageView.clipsToBounds = YES;
[panelView addSubview:panelImageView];
// DANH
// add webview on top if we have a url
if (panel.url) {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.ContentScrollView.frame.size.width, 300)];
[webView loadRequest:[NSURLRequest requestWithURL:panel.url]];
[panelView addSubview:webView];
}
// snipped original code
}
Now, to call it with example code....
// MYViewController.m
MYIntroductionPanel *panel3 = [[MYIntroductionPanel alloc] initWithURL:[NSURL URLWithString:#"http://www.google.com"]];
// ...
MYIntroductionView *introductionView = [[MYIntroductionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) headerText:#"MYIntroductionView" panels:#[panel, panel2, panel3] languageDirection:MYLanguageDirectionLeftToRight];
I have set up two barbutton items one on the right and one on the left. The right one successfully changes between two views, and the second one ont the right is a segmented control which is supposed to change between two views like wise. Here is my code, i want to know how to implement changing views with the segmented control.
- (void)setupNavigationBar {
UINavigationBar *navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44.0f)];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:#"ContainerView"];
navItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFastForward target:self action:#selector(switchViewControllers)];
navBar.items = [NSArray arrayWithObject:navItem];
segmented = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:
[UIImage imageNamed:#"seg1.png"],
[UIImage imageNamed:#"seg1.png"],
nil]];
segmented.frame = CGRectMake(0, 0, 50, 30);
segmented.segmentedControlStyle = UISegmentedControlStyleBar;
UIBarButtonItem * segmentedBarItem = [[UIBarButtonItem alloc] initWithCustomView:segmented];
navItem.leftBarButtonItem = segmentedBarItem;
[self.view addSubview:navBar];
}
- (void)viewDidLoad {
[super viewDidLoad];
// This is just for the purpose of calling the switch method.
[self setupNavigationBar];
CGRect rect = CGRectMake(0, 44, 320, 436);
currentViewController = [[FirstViewController alloc] init];
currentViewController.view.frame = rect;
nextViewController = [[SecondViewController alloc] init];
nextViewController.view.frame = rect;
[self addChildViewController:currentViewController];
[self addChildViewController:nextViewController];
[self.view addSubview:currentViewController.view];
}
- (void)switchViewControllers {
[self transitionFromViewController:currentViewController toViewController:nextViewController duration:3.0 options:UIViewAnimationTransitionFlipFromRight | UIViewAnimationOptionCurveEaseInOut animations:nil completion:^(BOOL finished) {
UIViewController *tempViewController = currentViewController;
currentViewController = nextViewController;
nextViewController = tempViewController;
tempViewController = nil;
}];
}
How would I implement the segmented control to change views?
For add UISegmentedControl on UINavigationBar
EDIT :
NSArray *itemArray = [NSArray arrayWithObjects:
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
nil];
UISegmentedControl* menuSegmentedButton = [[UISegmentedControl alloc] initWithItems:itemArray];
menuSegmentedButton.momentary = YES;
menuSegmentedButton.selected = NO;
menuSegmentedButton.segmentedControlStyle = UISegmentedControlStyleBar;
[menuSegmentedButton addTarget:self action:#selector(doMenu)
forControlEvents:UIControlEventValueChanged];
[menuSegmentedButton sizeToFit];
UIBarButtonItem* barButton = [[UIBarButtonItem alloc]
initWithCustomView:menuSegmentedButton];
self.navigationItem.leftBarButtonItem = barButton;
Add this method for segment button tapped
-(void)doMenu
{
/// code for segment button tapped
}
I guess performance issues may require having separate view controllers rather than two subviews but it is much more complex - You would have a very complicated navigation system and would need to set the segment control for each view. I am sure there is another way to subclass a view but I am unfamiliar with this so would suggest having one view controller containing your views.
Note: If you were to programmatically create all the objects in each view, you could achieve great performance by removing objects from any hidden views.
So first you have a UISegmentedControl (as created in iPatel's answer). But add in this line [ctrl addTarget:self action:#selector(switchViewControllers) forControlEvents:UIControlEventValueChanged];
Then in switchViewControllers put:
if (ctrl.selectedSegmentIndex == 0) {
NSLog(#"One");
self.viewOne.hidden = NO;
self.viewTwo.hidden = YES;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:#"showView" forKey:#"viewOne"];
[defaults synchronize];
}
else if (ctrl.selectedSegmentIndex == 1) {
NSLog(#"Two");
}
-(void)viewDidLoad {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([[defaults objectForKey:#"showView"] isEqualToString:#"viewOne"]) {
self.viewOne.hidden = NO;
self.viewTwo.hidden = YES;
}
else if (...) {
}
}
The above should work when you toggle the segment control. In each if you can toggle the visibility of two views. You would create the different views as a subview of the main view; one on top of the other. You would need to hide one view either in Interface Builder or in the viewDidLoad (I would suggest storing the current view in NSUserDefaults and showing that view when the user first loads the view controller).
I've made a project and implemented the folder project and now I've set up a subview which is displayed aboce the folder like on the picture. On the popup there's a image and I would like to do it like this that if I tap the image a new controller with the whole image will displayed. I've set up all correctly...However, I tried to change the subview etc. THIS Navigationcontroller never appears at the top of all "layers". it appears in the folderviewcontroller. By the way, the Navcontroller is set up by this project: https://github.com/mwaterfall/MWPhotoBrowser and the Popup was set up through this: https://github.com/kgn/KGModal
So here's my code:
-(IBAction)mehr:(id)sender {
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 280, 440)];
cubut = [UIButton buttonWithType:UIButtonTypeCustom];
[cubut addTarget:self
action:#selector(dothis:)
forControlEvents:UIControlEventTouchUpInside];
[cubut setTitle:#"Show View" forState:UIControlStateNormal];
cubut.frame = CGRectMake(5, 70, 270, 200);
[contentView addSubview:cubut];
- (IBAction)dothis:(id)sender {
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
// Set browser options.
browser.wantsFullScreenLayout = YES;
browser.displayActionButton = YES;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:browser];
[self presentModalViewController:navController animated:YES];
NSMutableArray *photos = [[NSMutableArray alloc] init];
MWPhoto *photo;
photo = [MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"star" ofType:#"png"]];
photo.caption = #"The star is soo beateful...";
[photos addObject:photo];
self.photos = photos;
}
- (MWPhoto *)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
if (index < _photos.count)
return [_photos objectAtIndex:index];
return nil;
}
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
return _photos.count;
}
And the picture:
(The button is set to custom so you cant see it...it has the same frame like the image)
So this was not finished so I have to awnser my own questions that I didnt found a solution for this.
I created a custom UITableViewCell class with a UIButton, a UIImage, and two UILabels. The button and the image are overlayed on top of each other, and only one is displayed at a time. The expected behavior is you touch on the button, the button disappears, and it displays the image. The UITableViewCells are set to be reused. Here's my code:
Constructor:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
unheartButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
unheartButton.backgroundColor = [UIColor clearColor];
unheartButton.frame = CGRectMake(10, 13, 20, 18);
[unheartButton addTarget:self action:#selector(onButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[unheartButton setBackgroundImage:[UIImage imageNamed:#"redheart.png"] forState:UIControlStateNormal];
imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(12, 13, 16, 16);
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int ndx = 1; ndx < 13; ndx++) {
[array addObject:[UIImage imageNamed:[NSString stringWithFormat:#"icon-loading-%d (dragged).tiff", ndx]]];
}
imageView.animationImages = array;
imageView.animationDuration = 1;
[array release];
[self.contentView addSubview:imageView];
[self.contentView addSubview:unheartButton];
return self;
}
}
- (void) setModel:(MyModel *)myModel {
model = myModel;
if (model.hideImage) {
imageView.hidden = YES;
unheartButton.hidden = NO;
else {
imageView.hidden = NO;
unheartButton.hidden = YES;
}
}
Button click:
- (IBAction) onButtonClick: (id) sender {
model.hideImage = NO;
unheartButton.hidden = YES;
imageView.hidden = NO;
[imageView startAnimating];
[self setNeedsDisplay];
[self.contentView setNeedsDisplay];
[self.unheartButton setNeedsDisplay];
[self.imageView setNeedsDisplay];
}
I'm calling setNeedsDisplay on everything, but nothing seems to happen. If I scroll off the screen and back up, the button is hidden and now the loading icon is shown, but this only happens after a scroll. I'm not sure what I need to do to get the cell to repaint.
The UITableView does some fancy caching to support scrolling and the like; I've had similar issues with refreshing a specific cell when I use custom views.
You can use reloadRowsAtIndexPaths:withRowAnimation: to make the table reload just that row. See this post for more information: Why won't my UITableViewCell deselect and update its text?