Release memory used for UITableView.cell.image after leaving UIViewController - image

I have a UIViewController with UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate protocols. The UIViewController contains UITableView where I load some data from Core Data.
The loaded data include name, subtitle and an image.
They are set like:
cell.textLabel.text = [NSString stringWithFormat:#"%#", artist.title];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# year", artist.year];
NSString *fileName = [NSString stringWithFormat: #"%#/%#", [[NSBundle mainBundle] resourcePath], artist.imageSmall];
cell.imageView.image = [UIImage imageWithContentsOfFile:fileName];
As I figured out before, [UIImage imageNamed:] caches the image which causes memory leaks. That's why I applied imageWithContentsOfFile method in code, where I needed to load big-size images. And it worked great. But it doesn't seem to work fine within my UITableView. Or I do smth wrong of cause :)
Here my images are not so heavy, they're like 20-40kb per image. It's ok even if I load 50 images per UITableView. It takes about 5Mb of memory to show, for example, 50 artists' photos per category. But what I noticed is that when I leave my ViewController and load it again via another indexPath (I open some other category cell and going to view the artists from that category) the memory used by app continues to increase. If I browse through 20 categories, then I get 100Mb memory usage. It doesn't look like the ARC work fine here.
So, how can I release the memory or destroy UITableView after moving back from my UIViewController?

2 hours later I found solution %)
I figured out to declare UITableView as (weak, nonatomic) instead of (strong, nonatomic).
And in ViewDidDisappear method I call
[self.tableView removeFromSuperview];
and memory releases successfully.

Related

Using a URL to share an image with iOS 6 and UIActivityViewController

I am using iOS 6's UIActivityViewController.
I would like to share an image that is not available locally on my iPhone, but that it is available on a remote URL.
NSString *textToShare = _eventoTitle;
UIImage *imageToShare = [UIImage imageNamed:_iconUrl];
NSURL *url = [NSURL URLWithString:_permalink];
NSArray *activityItems = [[NSArray alloc] initWithObjects:textToShare, imageToShare, url, nil];
Unfortunately, this is not working. What am I doing wrong?
I have also tried to use the AFNetworking library:
UIImage *imageToShare = [UIImage alloc];
[*imageToShare setImageWithURL:[NSURL URLWithString:_iconUrl]];
This is not working too.
_iconUrl is something like http://www.mysite.com/picture.png
Thank you, Francesco
Try with:
UIImage *imageToShare = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", _iconUrl]]]];
Matteo
To use remote images, I implemented a UIActivityItemProvider subclass that downloads the image when requested by the UIActivityViewController. UIActivityViewController calls your UIActivityItemProvider on a background thread so at least it doesn't block the main UI. I use a synchronous call just like Matteo suggests inside my UIActivityItemProvider. However, it's really still not a great solution because it just delays when you have to go do the expensive download. UIActivityViewController doesn't request your data until the user picks one of the activity icons in the view controller. At that time, it calls the UIActivityItemProvider to get the data. So you get a delay at this time.

UIWebview is off loading url

so I have an odd approach for loading bookmarks in a UIWebView in a browser app I am making. For the didSelectRowAtIndexPath in the Bookmarks UITableView, I have this code:
NSUserDefaults *lString = [NSUserDefaults standardUserDefaults];
[lString setValue:[bookmarks objectAtIndex:indexPath.row] forKey:#"loString"];
and then I have a modal for the selected object in the UITableView to another view controller which loads a UIWebView based on this code. So the problem is that the first time I click the table view object, the UIWebview is blank, then the second time it shows the URL that I clicked the first time. PLEASE HELP!
Thanks,
Michael
- (void)viewDidLoad
{
[super viewDidLoad];
NSUserDefaults *lString = [NSUserDefaults standardUserDefaults];
loadString = [lString valueForKey:#"loString"];
NSURL *url = [[NSURL alloc] initWithString:loadString];
NSURLRequest *togo = [[NSURLRequest alloc] initWithURL:url];
[webView loadRequest: togo];
// Do any additional setup after loading the view.
}
The -loadRequest method is asynchronous, meaning that it starts the load in another thread while your main thread's execution continues.
So the first time it's called, it shows a blank screen (because the first request is still running in another thread). The second time, because the first request has now finished, it shows that (while the second request runs in another thread). And so on.
To refresh the screen with the URL contents as soon as they load, you need to implement the -webViewDidFinishLoad method of your UIWebViewDelegate. In that method, you know the URL has finished loading, so if you refresh the web view there it should show the contents.

XCode iOS 1 TableView for iPhone and iPad?

I have a UITableView with a custom cell and they are both for the iPad(size)
What is the best way to go? Should I create a new UITableView nib and a new Cell nib and call them or just resize them when needed?
Please also give me instructions how to either of these solutions :)
I created a new Cell nib only for the iPhone and in the VC of the tableview I checked if the app is running on an iPhone or iPad and called the right nib.
NSArray *objects;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
objects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell-iPad" owner:self options:nil];
}
else {
objects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell-iPhone" owner:self options:nil];
}
table views aren't generally used on their own on ipads due to them having a lot more space, generally the design pattern is to have a small table view along the left and a content area on the right. I believe there is a uisplitviewcontroller to handle this.

When a view is dismissed, the presenting view throws EXC_BAD_ACCESS

I'm converting my iPhone app to an iPad version, creating new XIBs for the iPad and rigging them to the existing objective C classes using the ~ipad XIB name.
In the iPhone version, I use the navigation controller to step backwards to the app. This should work just fine in the iPad too, but while the navigation controller does appear, it doesnt respond. In fact its invisible to any interaction, if theres a map behind the navigation controller and you double click back, you just zoom on the map where you clicked.
So I'm including a button in the iPad view which should do the same thing. On press I call a
[[self navigationController] popViewControllerAnimated: YES];
When I call this I get the EXC_BAD_ACCESS. I've gone in to the spooky zombie mode which gives me this
*** -[UIWindowLayer superlayer]: message sent to deallocated instance 0x83bb9f0
Ive determined that 0x83bb9f0 is the presenting layers self.view.layer
I'm using ARC to handle my allocations and deallocs.
THE QUESTION IS: How can I prevent self.view.layer from deallocing? or how can I allocate it again at the proper time so that I dont get this error?
I can provide more code if needed. Thanks so much!!
Edit: Heres where the main page (landing page) is created, and the nav controller
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
landingPage *LandingPage = [[landingPage alloc] initWithNibName:#"landingPage" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:LandingPage];
self.window.rootViewController = self.navigationController;
// [self.navigationController pushViewController:LandingPage animated:YES];
[self.window makeKeyAndVisible];
return YES;
Then here is where the inner view is called:
mapView *MapView = nil;
MapView =[[mapView alloc] initWithNibName:#"mapView" bundle:nil];
[self.navigationController pushViewController:MapView animated:YES];
So I got it!
The XIBs I was creating for the iPad version were windows instead of views. I recreated all of these as views and rigged it up and it worked just fine!

WebView problem

My program have two classes, first of them is regular app delegate NSObject. The second one is a NSWindowController subclass with NSWindow and WebView on it, which shows html page from application bundle.
Here is how i call window from AppDelegate:
-(IBAction)showWebViewForm:(id)sender
{
webViewForm = [[WebViewForm alloc] initWithWindowNibName:#"WebViewForm"];
[webViewForm showWindow:self];
}
Here is how i render the webpage in WebViewForm : NSWindowController:
-(void)awakeFromNib{
[NSApp activateIgnoringOtherApps:YES];
[webview setUIDelegate: self];
[webview setResourceLoadDelegate: self];
[webview setPolicyDelegate:self];
[webview setFrameLoadDelegate:self];
[[webview mainFrame] loadRequest:
[NSURLRequest requestWithURL:
[NSURL fileURLWithPath:
[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html" inDirectory:#"data"]]]];
}
It's work fine, but only for the first time. When i close WebViewForm window and reopen it, webpage is disappearing from WebView. Why is so that, and how to fix it?
UPD Even if embed awakeFromNib code in special new method like -(void)refreshWebview and then call [webViewForm refreshWebview] right after [webViewForm showWindow:self];, still — page loads only for first time, and it's really weird ( Any ideas?
I figure it out by myself. The problem was, that webview closed when it's parent window closed. So, there is special method for case like that:
[webview setShouldCloseWithWindow:NO];

Resources