UIKit : UIPickerView внутри UICollectionViewCell становится невидимым

#swift #uikit #swift-playground

Вопрос:

Я хотел бы иметь пользовательское представление со строкой UIPickerView для отображения на нем одной цифры. Вот детская площадка, которая у меня есть :

 import PlaygroundSupport import UIKit import CoreGraphics  typealias DigitItemSize = (CGFloat, CGFloat)  class NumberViewItemArea {  private var digitWidth_ : CGFloat = 0  private var digitHeight_ : CGFloat = 0  private var numberOfDigits_ : Int = 0  private var area_ : CGRect? = nil  private var spaceBetweenDigits_ : CGFloat = 0    private func recalculateArea()  {  if numberOfDigits_ < 1 {  area_ = nil  } else {  area_ = CGRect(x:0,  y:0,  width : digitWidth_*CGFloat(numberOfDigits_)   spaceBetweenDigits_*CGFloat(numberOfDigits_-1),  height: digitHeight_)  }  }    init(itemWidth : CGFloat,  itemHeight : CGFloat,  numOfDigits : Int,  spaceBetweenDigits : CGFloat) {    digitWidth_ = itemWidth  digitHeight_ = itemHeight  numberOfDigits_ = numOfDigits  spaceBetweenDigits_ = spaceBetweenDigits    recalculateArea()  }    init() {}   public var digitWidth : CGFloat {  get {  return digitWidth_  }    set(newWidth) {  digitWidth_ = newWidth  recalculateArea()  }  }    public var digitHeight : CGFloat {  get {  return digitHeight_  }    set(newHeight) {  digitHeight_ = newHeight  recalculateArea()  }  }    public var numberOfDigits : Int {  get {  return numberOfDigits_  }    set(newValue) {  numberOfDigits_ = newValue  recalculateArea()  }  }    public var spaceBetweenDigits : CGFloat {  get {  return spaceBetweenDigits_  }    set(newValue) {  spaceBetweenDigits_ = newValue  recalculateArea()  }  }    public var area : CGRect? {  get {  return area_  }  } }  public class DigitControlItem: UIView {  lazy var categoryPickerView: UIPickerView = {  let pv = UIPickerView()  pv.dataSource = self  pv.backgroundColor = .white  pv.delegate = self  pv.translatesAutoresizingMaskIntoConstraints = false  return pv  }()    let dataArray = ["0", "1", "2", "3", "4","5","6","7","8","9"]    public override init(frame: CGRect) {  super.init(frame: frame)  commonInit()  }    public required init?(coder aDecoder: NSCoder) {  super.init(coder: aDecoder)  commonInit()  }    private func commonInit() {  setupSettingPickerView()  }    private func setupSettingPickerView() {  addSubview(categoryPickerView)    let constraints = [  categoryPickerView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 0),  categoryPickerView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: 0),  categoryPickerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0),  categoryPickerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0)  ]    NSLayoutConstraint.activate(constraints)  } }  extension DigitControlItem: UIPickerViewDataSource, UIPickerViewDelegate {  public func numberOfComponents(in pickerView: UIPickerView) -> Int {  return 1  }    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {  return dataArray.count  }    public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {  let row = dataArray[row]  return row  } }  class DigitItem: UICollectionViewCell {  private let digitArea : DigitControlItem = {  let view = DigitControlItem(frame : .zero)  view.translatesAutoresizingMaskIntoConstraints = false  return view  }()   override init(frame: CGRect) {  super.init(frame: frame)  setupViews()  }    required init?(coder: NSCoder) {  fatalError("init(coder:) has not been implemented")  }    func setupViews() {  contentView.addSubview(digitArea)    let constraints = [  digitArea.topAnchor.constraint(equalTo: contentView.topAnchor),  digitArea.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),  digitArea.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),  digitArea.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)  ]    NSLayoutConstraint.activate(constraints)  } }  class NumberView : UIView {  private var digitItemSize : DigitItemSize = (0, 0)  private var numberOfDigitItems : Int = 0  private var spaceBetweenItems : CGFloat = 0    private lazy var digitsCollection : UICollectionView = {  let layout = UICollectionViewFlowLayout()  layout.scrollDirection = .horizontal   let view = UICollectionView(frame: .zero, collectionViewLayout: layout)  view.register(DigitItem.self,  forCellWithReuseIdentifier: String(describing: DigitItem.self))  view.dataSource = self  view.delegate = self  view.backgroundColor = .white  view.translatesAutoresizingMaskIntoConstraints = false  return view  }()     public override init(frame: CGRect) {  super.init(frame: frame)  setupView()  }    public required init?(coder aDecoder: NSCoder) {  super.init(coder: aDecoder)  setupView()  }    convenience init(areaProvider : NumberViewItemArea) {  guard let rect = areaProvider.area else {  self.init(frame : .zero)  return  }    self.init(frame: rect)    numberOfDigitItems = areaProvider.numberOfDigits  spaceBetweenItems = areaProvider.spaceBetweenDigits  digitItemSize = (areaProvider.digitWidth, areaProvider.digitHeight)  digitsCollection.reloadData()  }    private func setupView()  {  addSubview(digitsCollection)    let constraints = [  digitsCollection.topAnchor.constraint(equalTo: topAnchor, constant: 0),  digitsCollection.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0),  digitsCollection.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0),  digitsCollection.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0)  ]    NSLayoutConstraint.activate(constraints)  } }  extension NumberView : UICollectionViewDataSource {  func numberOfSections(in collectionView: UICollectionView) -> Int {  return 1  }    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {  return numberOfDigitItems  }    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {  let cell =  digitsCollection.dequeueReusableCell(withReuseIdentifier:  String(describing: DigitItem.self),  for: indexPath) as! DigitItem   // cell.imageName = PhotoGalleryData.images[indexPath.row]    return cell  } }  extension NumberView : UICollectionViewDelegateFlowLayout {  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {  return CGSize(width: digitItemSize.0, height: digitItemSize.1)  }    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {  return spaceBetweenItems  }    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {  return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)  } }  let itemArea = NumberViewItemArea(itemWidth: 32,  itemHeight:32,  numOfDigits:1,  spaceBetweenDigits:2)    //let item = DigitControlItem(frame: CGRect(x: 0, y: 0, width: 50, height: 50))   let item = NumberView(areaProvider: itemArea)  PlaygroundPage.current.liveView = item  

Поэтому, если я просматриваю a DigitControlItem (что UIPickerView на самом деле является a), все работает нормально, но если это часть представления коллекции( NumberView класса), оно кажется невидимым. Есть какие-нибудь идеи, что здесь может быть не так?

Ответ №1:

Проблема возникает из-за делегата по умолчанию представления выбора. Я решил свою проблему, определив свой собственный ярлык :

 public func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {  var label = UILabel()  if let v = view as? UILabel { label = v }  label.text = dataArray[row]  label.textColor = UIColor.white  label.textAlignment = .center  return label }