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:
- 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).
Click on this button will start to profile your application.
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).
- 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
Using Audiobufferlist with Swift
Uibutton Fails to Properly Register Touch in Bottom Region of iPhone Screen
Table View Images Never Being Released
Uicollectionview Remove Top Padding
iOS Swiftui: Pop or Dismiss View Programmatically
Get Utc Time and Local Time from Nsdate Object
Uisearchbar Presented by Uisearchcontroller in Table Header View Animates Too Far When Active
Gradient Polyline with Mapkit iOS
Swift Doesn't Convert Objective-C Nserror** to Throws
How to Present iOS Uiactionsheet in Swift
How to Detect Swipe Gesture in iOS
How to Add iPhone 5 Large Screen Support to iOS Apps in Xcode
Swift Function Returning a Value from Asynchronous Firebase Call
Creating a Reusable Uiview with Xib (And Loading from Storyboard)