Table View Images Never Being Released

Table view images never being released

The possible reason here is because of your Settings view controller was not deallocated (not released from memory). No matter how many images are in that view controller when view controller release from memory it will deallocates (remove) all image object from memory.

How to check your view controller is de allocated (release) or not?

Steps:

  1. From Xcode long press on Run button. You get a small popup, Select Profile from that. And you can see new icon replaces the Run icon. (Similarly you can change it Run button to run the application).

Sample Image


  1. Click on this button will start to profile your application.

  2. Select Allocations section in Instruments window. There is a textfield above the allocation listing view. Click on that field and write your view controller name. (In your case SettingViewController).

Sample Image


  1. You can see only filter result related to that key word you just type. Now go to Simulator -> Simulate your flow. Pop back from your view controller and check in Instruments that after leaving that view controller if it's still in the list. If it is there in a list than your view controller is not release from memory and each time you open that view controller will increase memory and never release until application is running.

How we can de allocate view controller?

I'll try to explain some way which I know to de allocated controller.

[ 1 ] Override dealloc method in your view controller and release objects in that. Mainly mutable variable and delegates. Put a debug breakpoint on -dealloc method and make sure it is called when you left that controller.

Note: If you have create global variable for class like UIPickerView, UIPopoverController, UIImagePickerController etc. and set delegates for that than these delegates must be nil in -dealloc method.

e.g.

Objective C code:

//---------------------------------------------------------------

#pragma mark
#pragma mark Memory management methods

//---------------------------------------------------------------

- (void) dealloc {
[self.tableView setDelegate:nil];
[self.tableView setDataSource:nil];
}

Swift code:

deinit {
self.tableView.dataSource = nil
self.tableView.delegate = nil
}

[ 2 ] Global object of subclass also needs to override -dealloc method and release relevant objects and delegates. Similar their dealloc method must have to be called.

e.g.

Check this scenario: Let's say you have created a subclass of UIView (or any other view) with the name MenuView. And you have created a global variable of this class in your view controller, than it's dealloc method will be called before view controller's dealloc method.

@property (nonatomic, strong) MenuView    *menuView;

So here MenuView class needs to be override the -dealloc method and must be called before your view controller's dealloc method is called.

So that before leaving whole container its child views are release and removed from memory.

Check this in Instruments for MenuView class also that object is still their or not?

If it's dealloc method is not called than object of MenuView class is still in memory and your view controller class is referencing that object. So even if your view controller's -dealloc is called it will not deallocated because MenuView class object is live.


[ 3 ] You need to set weak reference to the IBOutlet. e.g.

Objective C code:

@property (nonatomic, weak) IBOutlet UITableView   *tableView;

Swift Code:

@IBOutlet weak var tableView: UITableView!

Feel free to ask if anything is not clear.

I'm having troubles displaying an image from JSON in a Table View

I think you should download your full data before loading tableview and reload tableview in the completion handler. Call loadData() method in your viewDidLoad().

fileprivate func loadData() {

let url = URL(string: "http://ws-smartit.divisionautomotriz.com/wsApiCasaTrust/api/autos")!

let task = URLSession.shared.dataTask(with: url) {
(data, response, error) in

guard let dataResponse = data, error == nil else {
print(error?.localizedDescription ?? "Response Error")
return
}

do {
let jsonResponse = try JSONSerialization.jsonObject(with: dataResponse, options: []) as? NSArray
self.arrAutos = jsonResponse!.compactMap({ Autos($0 as? [String:String])})

DispatchQueue.main.async {
self.tableView.reloadData()
}

} catch let parsingError {
print("Error", parsingError)
}
}
task.resume()
}

For loading images in tableView cell, download the image in background thread and then update the imageView in the main thread.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "carsCell", for: indexPath) as! CarsDetailTableViewCell

// Get valid string
let string = self.arrAutos[indexPath.row].RutaImagen
//print(string)
cell.lblBrand.text = self.arrAutos[indexPath.row].Marca
cell.lblPrice.text = self.arrAutos[indexPath.row].Precio
cell.lblModel.text = self.arrAutos[indexPath.row].Modelo
let url = URL(string: string)
if url != nil {
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
if data != nil {
cell.imgCar.image = UIImage(data:data!)
}
}
}
}
return cell
}

Hope this will work.

Swift 4 TableView Cell not Displaying correct images

Set imageView.image = nil in the beginning of cellForRowAtIndexPath method. You are reusing cells. Sometimes you need to reset cell components.

Swift tableview image from URL not showing until cell is selected

It's hard to say without seeing anything in your custom cell or your didSelectRow method, but my guess is that this is happening because cellForRowAt is being called on each of your cells before your Alamofire requests finish.

tableView(_:cellForRowAt:) is called very often - each time a cell is about to be dequeued and come onscreen. I'd advise against putting a network call in here as Mansi mentioned. You also probably don't want to be doing that loop to get restaurant info in this function either. Both the loop and the service call will be called for each cell, every time that cell is about to be dequeued and come onscreen - this is going to get very expensive very fast. It also looks by this code that when one of the table view's cells goes offscreen then is about to come onscreen again, that cell will attempt to re-download the image even if already was downloaded previously (because cellForRow will get call again for that cell).

The text label is showing up without issues because it doesn't rely on any network call and can be drawn right away. My guess is your didSelectRow or custom cell is telling the cell to re-draw itself when selected, which is why that image is showing up when you select it.

I'd suggest moving the loop and the request outside of this function and creating some sort of data structures to hold these values. You might need to implement a loading animation in your image views while waiting for the requests to complete, and a data structure for your images could act as a cache. There's a few different ways to go about this - these are just general suggestions. Good luck!

Swift, Stop Images from loading in table View

Solved this awhile back
You have to set the images to nil before loading new images on them

UITableViewCell image not shown until selected

The problem was that my Image wasn't set on the main thread. To solve the problem, I simply used the following code below which ensured that my image will be set immediately.

dispatch_async(dispatch_get_main_queue(), {
// do image functions here

)}

detailTextLabel and imageView not accessible on table view cells

You should change the cell style to a value other than UITableViewCellStyleDefault. Unwrapping isn't necessary as well in this situation AFAIK.

Regarding the other stuff you try:

By the way printing cell.subviews.count won't give you any usable value as all subviews in UITableViewCell should be added (and default subviews are) inside its -contentView (cell property).

Also using cells initialised using -initWithStyle:reuseIdentifier: has no extra drawbacks as you may still use the reusing mechanism as well as specify the required cell style at the same time. Dequeuing actually has more sense when reusing Storyboard-defined cells with attributes specified in the Interface Builder.



Related Topics



Leave a reply



Submit