2015-02-19 4 views
2

Я хотел бы подклассифицировать UIPickerView, чтобы создать пользовательскую DatePicker. Я попробовал это, но есть ошибка в Swift говоря:Подкласс UIPickerView в Swift: ошибка необязательное значение в viewForRow

неожиданно нашел ноль в то время как разворачивание необязательного значения

на этой линии: (view.viewWithTag(1) as UILabel).text = array[row]

Вот код:

class MyPickerView : UIPickerView, UIPickerViewDataSource, UIPickerViewDelegate{ 

    let array = ["one", "two", "three"] 
    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
    override init(frame: CGRect) { 
     super.init(frame:frame) 
     self.delegate = self 
     self.dataSource = self 
    } 

    //components/row 
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { 
     return 1 
    } 
    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
     return array.count 
    } 

    //view for row 
    func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView { 
     if view == nil { 
      var view = UIView(frame: CGRectMake(0,0, 150,50)) 
      let label = UILabel(frame:CGRectMake(0,0, 80, 40)) 
      label.tag = 1 
      view.addSubview(label) 
     } 
     (view.viewWithTag(1) as UILabel).text = array[row] 
     return view 
    } 
    //did select row 
    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 
     println("has selected row \(row)") 
    } 

Thanks

ответ

3

Известная ошибка в UIPickerView (начата в iOS 7, я думаю), что представления никогда не используются повторно. Чтобы устранить проблему, избавиться от, если п (то нет никакой необходимости в теге),

func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView!) -> UIView { 
    var view = UIView(frame: CGRectMake(0,0, 150,50)) 
    let label = UILabel(frame:CGRectMake(0,0, 80, 40)) 
    view.addSubview(label) 
    label.text = array[row] 
    return view 
} 

Причина вы получите сообщение об ошибке, потому, что у вас есть два объекта под названием «вид». Тот, который вы создаете внутри предложения if, не виден вне этого предложения, поэтому «вид», который вы вызываете viewWithTag on, представляет собой представление, которое передается методу, и оно всегда равно нулю.

+0

Поблагодарите rdelmar, да, на самом деле это сработало, если var находится вне закрытия, но представление в параметре на самом деле всегда равно нулю, как вы сказали. Могу ли я спросить, почему 'return array [count]' in 'titleForRow ...' возвращает ошибку компилятора: '(Диапазон ) -> I.Distance не конвертируется в Int'? – Paul

+1

@Paul, Это неправильный синтаксис. Вы хотите array.count. Кроме того, вы используете titleForRow? Вам не должно быть, когда вы реализуете viewForRow. – rdelmar

+0

argh, я допустил ошибку, я хотел написать массив [row]. Да, спасибо за совет, который я пробовал один или другой, отлично, спасибо вам большое! – Paul

1

Сначала вы проверяете, является ли вид нулевым, но после закрытия вы пытаетесь получить к нему доступ, независимо от того, является ли оно нулевым или нет. Если я правильно понял ваши намерения, вы должны заменить

var view = UIView(frame: CGRectMake(0,0, 150,50)) 

с

view = UIView(frame: CGRectMake(0,0, 150,50)) 

, потому что в данный момент вы создаете новую переменную под названием представление в пределах объема, если заявление.

+0

Фактически вы правы, это работает, если я создаю mView = ... перед закрытием .... edit: но параметр в параметре всегда равен нулю. Который кажется ошибкой, как сказано в сообщении от rdelmar – Paul

Смежные вопросы