Функция вызова UITableViewCell из родительского TableView - PullRequest
0 голосов
/ 26 мая 2020

У меня есть виджет пользовательского интерфейса:

class ProfileBubbleCell: UITableViewCell {

    var roundImageView: UIImageView?

    override func awakeFromNib() {

        super.awakeFromNib()
        self.contentView.backgroundColor = Color.red
        initImage()
    }

    private func initImage(){

        let imageView = UIImageView()

        let width = self.frame.width
        let height = self.frame.height

        let img_width  = height - 4
        let img_height = img_width

        let y = 2
        let x = width/2 - img_width/2

        imageView.frame = CGRect(
              x: x, y: CGFloat(y), width: img_width, height: img_height
        )

        let rounded = imageView
            .makeRounded()
            .border(width:2.0, color:Color.white.cgColor)

        // attach and save reference
        self.addSubview(rounded)
        self.roundImageView = rounded
    }

    private func loadImage(){
    // @TODO: call parent function

    }
}

И в loadImage я хотел бы вызвать представление загрузки родительского изображения, и когда изображение загружено, отобразить его в roundImageView. ProfileBubbleCell действительно должен быть как можно более общим c, его единственная задача - сделать изображение круглым и центрировать его.

Это похоже на очень распространенный вариант использования, и я хотел бы delegate задача загрузки изображения для родителя, но я не уверен, как express это сделать.

В родительском элементе я создаю экземпляр ячейки следующим образом:

let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileBubbleCell", for: indexPath) as! ProfileBubbleCell

1 Ответ

2 голосов
/ 26 мая 2020

Здесь вы узнаете об использовании делегата.

// 1) define delegate.
protocol ProfileBubbleCellDelegate { 
  func getImage() -> UIImage?
}


class ProfileBubbleCell: UITableViewCell { 

  // 2) declare a variable of ProfileBubbleCellDelegate
  weak var delegate: ProfileBubbleCellDelegate?

  //  
  func configure() {
    self.roundImageView.image = delegate.getImage()
  }
}

// when dequeueReuseCell on cellForRow(at:)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {  
  guard let cell  = tableView.dequeueReusableCell(withIdentifier: "ProfileBubbleCell", for: indexPath) as ProfileBubbleCell else { return UITableView() }
  // 3) assign delegate to tableView's superView, maybe it's a UIViewController or UIView on your class.
  cell.delegate = self
  cell.configure()
  return cell
}

// 4) extension Your class who be assigned delegate of ProfileBubbleCellDelegate
//    and implement delegate's method.
extension YourClass: ProfileBubbleCellDelegate { 
  func getImage() -> UIImage? { 
    // 5) provide image.
    return hereProvideYourImage
  }
}

// or if you want immediately download image when cell.roundedImageView need it.
// modify the getImage() of Delegate like this.
protocol ProfileBubbleCellDelegate { 

  func getImage(completion: @escaping ((UIImage?) -> Void))
}

// then the extension implement will be 
extension YourClass: ProfileBubbleCellDelegate { 
  func getImage(completion: @escaping ((UIImage?) -> Void)) { 
    downloadImageTask.downloadImage(url: imageUrl, completion: { downloadedImage in  
      // because completion will be passed on other closure of downloadImage(completion:), 
      //   so delegate method need add `@escaping` that means the completion can escape from itself closure.
      completion?(downloadedImage)
     })
  }
}

// don't forget replace called method on cell. 
class ProfileBubbleCell: UITableViewCell { 
  // ...   
  func configure() { 
    delegate.getImage(completion: { downloadedImage in 
      DispatchQueue.main.async { 
        self.roundImageView.image = downloadedImage
      }
    })
  }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...