Как заставить строку ячеек обновлять высоту - PullRequest
1 голос
/ 18 июня 2020

У меня есть UITableView, над которым я работаю. Одна из строк позволяет пользователю загрузить фотографию. После того, как фотография загружена, она изменяет свойство описания alpha на 0 (делает невидимым), изменяет высоту изображения на 100 и устанавливает UIImage.

Я проверил, что высота изображения обновляется, но высота ячейки не обновляется, несмотря на то, что она установлена ​​на c автоматически. Есть ли способ сообщить представлению, что ему необходимо обновить высоту ячейки?

Перед загрузкой изображения пользователем:

image


После загрузки изображения пользователем:

image


Настройки ячейки TableView TableView Cell Settings

//
//  AddAssetTableViewController.swift
//  ItemizePro
//
//  Created by Tyler Wasick on 5/27/20.
//  Copyright © 2020 Tyler Wasick. All rights reserved.
//

import UIKit

class AddAssetTableViewController: UITableViewController {

    // TODO: Add image IBOutlet

    @IBOutlet weak var nameTextField: UITextField!

    @IBOutlet weak var descriptionTextField: UITextField!

    @IBOutlet weak var datePurchasedTextField: UITextField!

    @IBOutlet weak var manufactureTextField: UITextField!

    @IBOutlet weak var modelTextField: UITextField!

    @IBOutlet weak var serialNumberTextField: UITextField!

    @IBOutlet weak var costTextField: UITextField!

    @IBOutlet weak var roomTextField: UITextField!

    @IBOutlet weak var notesTextView: UITextView!

    @IBOutlet weak var imageLabel: UILabel!

    @IBOutlet weak var receiptLabel: UILabel!

    @IBOutlet weak var addUIButton: UIButton!

    @IBOutlet weak var assetImageUIImage: UIImageView!

    @IBOutlet weak var receiptImageUIImage: UIImageView!

    // TableView Rows
    @IBOutlet weak var imageTableViewCell: UITableViewCell!


    // Set variables
    var newAsset = Asset()
    let datePicker = UIDatePicker()
    var dateAdded = Date()
    var cost = 0
    var imagePickerField = ""

    // Setup number formater
    lazy var numberFormatter: NumberFormatter = {
        // Setup Currency Formatter
        let currencyFormatter = NumberFormatter()
        currencyFormatter.usesGroupingSeparator = true
        currencyFormatter.numberStyle = .currency

        // localize to your grouping and decimal separator
        currencyFormatter.locale = Locale.current
        return currencyFormatter
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem

        // Setup formatting


        // Setup Date Picker
        createDatePicker()

        // Use input data for cost field and update the cost data and formatting automatically
        costTextField.delegate = self
        costTextField.placeholder = updateCostField()

    }

    // MARK: - Table view data source

    /*
     override func numberOfSections(in tableView: UITableView) -> Int {
     // #warning Incomplete implementation, return the number of sections
     return 0
     }

     override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     // #warning Incomplete implementation, return the number of rows
     return 0
     }


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

     // Configure the cell...

     return cell
     }
     */

    /*
     // Override to support conditional editing of the table view.
     override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
     // Return false if you do not want the specified item to be editable.
     return true
     }
     */

    /*
     // Override to support editing the table view.
     override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
     if editingStyle == .delete {
     // Delete the row from the data source
     tableView.deleteRows(at: [indexPath], with: .fade)
     } else if editingStyle == .insert {
     // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
     }
     }
     */

    /*
     // Override to support rearranging the table view.
     override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {

     }
     */

    /*
     // Override to support conditional rearranging of the table view.
     override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
     // Return false if you do not want the item to be re-orderable.
     return true
     }
     */

    // When user taps on the image row, initiate "Show Action Sheet"
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.row == 0 {
            showActionSheet(title: "Upload an image of your item.", fieldName: Constants.InventoryVC.imageField)
        }

        if indexPath.row == 10 {
            showActionSheet(title: "Upload a receipt for your item.", fieldName: Constants.InventoryVC.receiptField)
        }
    }

    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        //if let detinationVC = segue.description as? RoomListViewController

        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
        if let target = segue.destination as? RoomListViewController
        {
            target.selectionDelegate = self
        }

    }


    // MARK: - Functions
    // Date picker
    func createDatePicker() {

        // Setup the UIToolbar
        let toolbar = UIToolbar()
        toolbar.sizeToFit()

        // Setup "Done" button
        let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneTapped))
        toolbar.setItems([doneButton], animated: true)

        // Format date text field
        datePurchasedTextField.inputAccessoryView = toolbar
        datePurchasedTextField.inputView = datePicker
        datePicker.datePickerMode = .date
    }

    // Obj-C Date Picker Action
    @objc func doneTapped() {

        // Format date field
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        formatter.timeStyle = .none
        let dateString = formatter.string(from: datePicker.date)
        dateAdded = formatter.date(from: dateString)!

        // Set the date text field
        datePurchasedTextField.text = dateString

        // Close date picker
        self.view.endEditing(true)

    }

    func updateCostField() -> String {

        // Format number into currency data
        let num = cost
        let decimalNum = Double(num) / 100
        let numString = numberFormatter.string(from: NSNumber(value: decimalNum))

        // Return formatted number
        return numString!
    }

    func showActionSheet(title:String, fieldName:String) {

        // Create the action sheet
        let actionSheet = UIAlertController(title: title, message: "Select a source to upload an image", preferredStyle: .actionSheet)

        // Create camera action if available
        if UIImagePickerController.isSourceTypeAvailable(.camera) {

            let cameraAction = UIAlertAction(title: "Camera", style: .default) { (action) in

                // Set the camera action
                self.showImagePicker(type: .camera)
            }

            // Add action to the action sheet
            actionSheet.addAction(cameraAction)
        }

        // Create photo library action
        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {

            let photoAction = UIAlertAction(title: "Select From Photo Library", style: .default) { (action) in

                // Set photo library action
                self.showImagePicker(type: .photoLibrary)

            }

            // Add action to the action sheet
            actionSheet.addAction(photoAction)
        }

        // Create cancel actions
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)

        // Add the cancel action
        actionSheet.addAction(cancelAction)

        // Set the image field that is being manipulated to the "imagePickerField
        imagePickerField = fieldName

        // Present action sheet
        present(actionSheet, animated: true, completion: nil)

    }

    func showImagePicker(type:UIImagePickerController.SourceType) {

        // Create the image picker
        let imagePicker = UIImagePickerController()
        imagePicker.sourceType = type

        // Setup delegate
        imagePicker.delegate = self

        // Present it
        present(imagePicker, animated: true, completion: nil)
    }

    func setupFormatting() {

        // Set image previews to transparent
        assetImageUIImage.alpha = 0
        receiptImageUIImage.alpha = 0


    }

    // MARK: - IBAction outlets

    @IBAction func addButtonTapped(_ sender: UIButton) {

        // Name text field
        if nameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.name = nameTextField.text!
        }
        else if nameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.name = ""
        }

        // Description text field
        if descriptionTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.description = descriptionTextField.text!
        }
        else if descriptionTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.description = ""
        }

        // Date text field
        if datePurchasedTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.datePurchased = dateAdded
        }
        else if datePurchasedTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.datePurchased = Date()
        }

        // Manufacture text field
        if manufactureTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.manufacture = manufactureTextField.text!
        }
        else if manufactureTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.manufacture = ""
        }

        // Model text field
        if modelTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.model = modelTextField.text!
        }
        else if modelTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.model = ""
        }

        // Serial number text field
        if serialNumberTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.serialnumber = serialNumberTextField.text!
        }
        else if serialNumberTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.serialnumber = ""
        }

        // Cost text field
        if costTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines) != "" {
            let cost = costTextField.text!
            newAsset.cost = cost
        }
        else if costTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
            newAsset.cost = "$0.00"
        }

        // Room text field
        if roomTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.room = roomTextField.text!
        }
        else if roomTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.room = ""
        }

        // Notes text field
        if notesTextView.text?.trimmingCharacters(in: .whitespacesAndNewlines) != nil {
            newAsset.notes = notesTextView.text!
        }
        else if notesTextView.text?.trimmingCharacters(in: .whitespacesAndNewlines) == nil {
            newAsset.notes = ""
        }

        // TODO: - Receipt

        // TODO: - Image

        // Add to firebase
        let result = FirebaseDB.addAssets(asset: newAsset)

        print(result)
    }

}



// MARK: - Extensions
// Table delegate extension
extension AddAssetTableViewController : RoomDelegate {
    func tappedOnRoom(room: String) {
        roomTextField.text = room
    }
}

// Cost text field delegate
extension AddAssetTableViewController : UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        // Check if num is <= 1 billion
        if cost < 1000000000 {

            // Add new digit to the cost var
            if let num = Int(string) {
                cost = cost * 10 + num
                print(cost)
                costTextField.text = updateCostField()
            }
        }

        // If the user removes a digit, remove it from the cost var
        if string == "" {
            cost = cost / 10
            print(cost)
            costTextField.text = updateCostField()
        }

        // Return false for return (return is unused)
        return false
    }
}

// Image picker extension
extension AddAssetTableViewController : UIImagePickerControllerDelegate & UINavigationControllerDelegate {


    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

        // TODO: If image was selected successfully, set the image to "selectImage" object
        if let selectImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {

            // If image selected is the asset image, set the to the asset.image field
            if imagePickerField == Constants.InventoryVC.imageField {
                newAsset.image = selectImage
                assetImageUIImage.image = selectImage
                assetImageUIImage.frame.size.height = 180
                imageLabel.alpha = 0

            }

            // If image selected is the receipt image, set the to the asset.receipt field
            else if imagePickerField == Constants.InventoryVC.receiptField {
                newAsset.receipt = selectImage
                receiptLabel.text = "Image Uploaded"
            }

        }

        // Dismiss the picker
        picker.dismiss(animated: true, completion: nil)
    }
}

1 Ответ

2 голосов
/ 18 июня 2020

Вы можете сделать это, перезагрузив UITableView в методе didFinishPickingMediaWithInfo из UIImagePickerControllerDelegate и предоставив настраиваемую высоту для строки просмотра изображения, если изображение не пустое.

class AddAssetTableViewController: UITableViewController {

    @IBOutlet weak var assetImageUIImage: UIImageView!

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.row == 0 && assetImageUIImage.image != nil {
            return 100 // Larger height
        }
        return 44 // Usual height
    }
}
extension AddAssetTableViewController : UIImagePickerControllerDelegate & UINavigationControllerDelegate {

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        // ...
        tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
    }
}

Примечание : Лучшим подходом было бы добавить ограничения высоты, верха и низа к UIImageView в ячейке, и автоматическая компоновка сделает все остальное.

...