Why doesntnt heightForRowAt find a value in the array after reloadRows is called?

时间:2018-01-15 18:11:31

标签: ios swift uitableview

Why does the function heightForRowAt always find the array containing row heights which is initially set to nil to sill be nil even after reloading the rows.

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

    let downloadURL = URL(string: self.imageURLS[indexPath.row])


    if cell.cellImageView.image == nil{
        URLSession.shared.dataTask(with: downloadURL!) { (data, _, _) in
            if let data = data {
                let image = UIImage(data: data)
                DispatchQueue.main.async {
                    cell.setCellImage(image:image!)
                    self.rowHeights?.insert((cell.imageView?.frame.height)!, at: indexPath.row)
                    tableView.reloadRows(at: [indexPath], with: .top)
                }
            }
            }.resume()
    }
    return cell
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    guard let rowHeights = self.rowHeights else{
        print("returned nil")
        return 500.0
    }
    print("the array exists at \(indexPath.row) with value: \(rowHeights[indexPath.row])")
    return rowHeights[indexPath.row]
}
}

UPDATED TableViewController

import UIKit
import Firebase
import FirebaseStorageUI

class TableViewController: UITableViewController {
var images:[UIImage]! = [#imageLiteral(resourceName: "rininger_2.jpg")]
var imageURLS:[String] = [String]()
var rowHeights:[CGFloat] = [CGFloat]()
var listener:ListenerRegistration?

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    listener = Firestore.firestore().collection("Posts").addSnapshotListener{
        querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error fetching snapshots: \(error!)")
            return
        }
        snapshot.documentChanges.forEach { diff in
            if (diff.type == .added) {
                print("New data: \(diff.document.data())")
            }
            if (diff.type == .modified) {
                print("Modified data: \(diff.document.data())")
            }
            if (diff.type == .removed) {
                print("Removed data: \(diff.document.data())")
            }

            guard let newImageURL = diff.document.data()["imageDownloadURL"] as? String else{
                print("Failed to get image download URL")
                return
            }
            print("downloadURL: \(newImageURL)")
            self.imageURLS.insert(newImageURL, at: 0)
            let indexPath = IndexPath(row: 0, section: 0)
            self.tableView.insertRows(at: [indexPath], with: .top)


        }

    }
    tableView.estimatedRowHeight = 100.0
    tableView.rowHeight = UITableViewAutomaticDimension
}


override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return imageURLS.count
}


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

    let downloadURL = URL(string: self.imageURLS[indexPath.row])


    if cell.cellImageView.image == nil{
        URLSession.shared.dataTask(with: downloadURL!) { (data, _, _) in
            if let data = data {
                let image = UIImage(data: data)
                self.images.insert(image, at: indexPath.row)
                DispatchQueue.main.async {
                    cell.setCellImage(image:image!)
                   // self.rowHeights.insert((cell.imageView?.frame.height)!, at: indexPath.row)
                   //tableView.reloadData()
                   tableView.reloadRows(at: [indexPath], with: .top)
                }
            }
            }.resume()
    }
    return cell
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    print("UITableViewAutomaticDimension: \(UITableViewAutomaticDimension)")
    return UITableViewAutomaticDimension
}

}

2 个答案:

答案 0 :(得分:0)

You have massive problems in your code

1- first you must download , save image and then reload the table

2- second you should use automatic table view height to accomplish that instead of array of heights like what you're currently do

solve 1

   NSString *getImagePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.jpeg",n1.Id]];

    if([[NSFileManager defaultManager] fileExistsAtPath:getImagePath])
    {
        UIImage *img = [UIImage imageWithContentsOfFile:getImagePath];
        cell.leftImageV.image =img;
        [cell.activity stopAnimating];
        cell.activity.hidden=YES;
    }
    else
    {

        [cell.activity startAnimating];
         cell.activity.hidden=NO;

        cell.leftImageV.image = nil;

        NSLog(@"xdasdxsadxa %@",n1.mainImgStr);

        dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

        dispatch_async(concurrentQueue, ^{
            __block NSData * imageData  = nil;
            dispatch_sync(concurrentQueue, ^{ 

                imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:n1.mainImgStr]];

                //Add the file name
                [imageData writeToFile:getImagePath atomically:YES]; //Write the file

            });

            dispatch_sync(dispatch_get_main_queue(), ^{

                if(imageData)
                { 
                    [self.tableView reloadData];

                } 
            });
        }); 

Solve 2

To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout. I just tested following steps and code and works fine.

  • Assign and implement tableview dataSource and delegate
  • Assign UITableViewAutomaticDimension to rowHeight & estimatedRowHeight
  • Implement delegate/dataSource methods (i.e. heightForRowAt and return a value UITableViewAutomaticDimension to it)

-

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

    // Set automatic dimensions for row height
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension
}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

答案 1 :(得分:0)

确保在为其添加值之前已初始化rowHeights数组 例如:

cell.setCellImage(image:image!)

if self.rowHeights == nil{ rowHeights = [CGFloat]() }

self.rowHeights?.insert((cell.imageView?.frame.height)!, at: indexPath.row)