2016-12-03 2 views
0

Я работаю над учебным пособием «Начать разработку iOS», предоставленным Apple, и имеет проблемы в разделе Implement a Custom Control. Я пробовал все, чтобы заставить кнопку печатать что-то на консоль, но не может заставить ее работать. Я нахожусь в разделе в уроке «Добавить кнопки в представление» примерно на пятую часть вниз по странице.Учебник Apple iOS: проблемы с получением UIButton addTarget для работы

Все остальное отлично работает.

Я создал файл RatingControl.swift следующим образом:

import UIKit 

class RatingControl: UIView { 

    // MARK: Initialisation 
    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 

     // Create a square button 
     let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44)) 

     // Set the background colour of the button 
     button.backgroundColor = UIColor.darkGray 

     button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped(_:)), for: .touchDown) 

     // Add the button to the view 
     addSubview(button) 
    } 

    // MARK: Button Action 
    func ratingButtonTapped(_: UIButton) { 
     print("Button pressed") 
    } 
} 

Несколько вещей есть немного отличается от учебника, но это потому, что Xcode говорит все изменилось. В моем файле Main.storyboard я добавил View, используя класс RatingControl. Кнопка отображается, но ничего не происходит, когда я нажимаю на нее.

Любая помощь будет оценена по достоинству. Если вам нужна дополнительная информация, пожалуйста, дайте мне знать.

+1

Дайте вид в раскадровке, которая использует класс RatingControl цветом фона, чтобы вы могли видеть, полностью ли кнопка находится внутри представления. Он должен быть, или он не будет реагировать при нажатии. Кроме того, по той же причине убедитесь, что вы проверили User Interaction Enabled для управления рейтингами. - Также вы уверены, что хотите использовать '.touchDown'? Обычная вещь - .touchUpInside'. – matt

+0

Спасибо. Я попытался сделать это, добавив «self.backgroundColor = UIColor.cyan» сразу после «super.init (coder: aDecoder)», но он не изменил цвет фона в представлении. Я также попытался изменить цвет фона представления в инспекторе атрибутов раскадровки для представления. Ничто не изменило цвет фона. Что мне не хватает? Раньше я заметил «User Interaction Enabled», и он проверяется. Я использовал только .touchDown, потому что в учебнике сказано, что он использует это. Я удивился. Изменил его .touchUpInside, но он не запустил кнопку. – SuperDuperApps

+0

Я переместил вид из стека, в котором он находился, чуть ниже, и все работает. Цвет фона, установленный в раскадровке, работает, и кнопка делает то, что должна. Как только я верну его обратно в стек, он перестает работать. В представлении стека включено взаимодействие с пользователем, а управление над ним в стеке отлично работает. Не понимаю. – SuperDuperApps

ответ

1

Существует на самом деле иерархия трех представлений в этой истории:

  • Вид стека (не упоминается в оригинале вопрос)
    • The RatingControl
      • Кнопка

Ну, вид стека, сложный элемент управления, чья работа включает в себя много вуду с ограничениями его расположенными подвидов, уменьшает размер RatingControl до нуля. Таким образом, кнопка не находится за пределами рейтинга RatingControl (это легко доказать, если присвоить RatingControl фоновый цвет - цвет фона не отображается). РейтингControl не обрезает его границы, поэтому кнопка все еще видна - но, находясь вне ее супервизора, это не tappable.

Что касается почему вид стек уменьшающего размера RatingControl к нулю: это потому, что RatingControl не имеет intrisicContentSize. Причина, по которой нам это нужно, сложна и связана с тем, как представление стека манипулирует своими организованными подзонами и дает им ограничения. Но по сути, он принимает множество решений на основе упорядоченного вида intrinsicContentSize.

В комментариях вы сказали:

В размер инспектора он присущий размер установлен на заполнителя, ширина 240, высота 44. Или есть что-то, что нужно сделать, чтобы остановить вид стека, что делает его нулевого размера, ?

Главное, чтобы понять, является то, что эта настройка в инспекторе размера только заполнителя. Это просто закрыть раскадровку, чтобы она не стала жаловаться. На самом деле это не означает, что во время выполнения вид имеет собственный внутренний размер. Чтобы сделать это, вы должны фактически переопределить intrinsicContentSize property, в своем коде, как вычисленная переменная, возвращающая фактический размер.

+0

Спасибо за ваш ответ. Это точно определяет проблему, но как ее можно исправить? – SuperDuperApps

+0

О, о том, что мне нужно узнать гораздо больше о том, как настроены представление стека и представление RatingControl (и что еще, если что угодно, находится в представлении стека и как _that_ настроен). Вы можете задать совершенно новый вопрос, дающий эту информацию. Кажется, я ответил на этот вопрос, поэтому кнопка не могла быть использована. – matt

+0

Спасибо. Но я не могу отметить ответ, принятый, когда он не устраняет проблему. Я отметил это, хотя это, безусловно, помогло выявить проблему. Вопрос может быть обновлен с необходимой информацией, как предлагается в вопросе, если вы хотите посмотреть на него. В противном случае я оставлю это нерешенным до сих пор и, возможно, предоставил свой собственный ответ, когда узнаю больше о представлениях стека. – SuperDuperApps

0

, то ваш код будет работать: -

class RatingView: UIView { 

    // MARK: Initialisation 
    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 

     // Create a square button 
     let button = UIButton(frame: CGRect(x: 200, y: 100, width: 44, height: 44)) 

     // Set the background colour of the button 
     button.backgroundColor = UIColor.darkGray 

     button.addTarget(self, action: #selector(self.ratingButtonTapped(_:)), for: .touchDown) 

     // Add the button to the view 
     addSubview(button) 
    } 

    // MARK: Button Action 
    func ratingButtonTapped(_: UIButton) { 
     print("Button pressed") 
    } 
} 

Output

+0

Я пробовал это, но он жалуется на то, что «Значение типа« RatingControl »не имеет вида пользователя». Но в любом случае кнопка появляется, просто не работает в интерактивном режиме, поэтому кажется, что линия работает нормально, как есть. – SuperDuperApps

+0

ok Позвольте мне попробовать что-то обновит этот код как можно скорее. –

+0

Спасибо. Но похоже, что в коде нет ничего плохого, это проблема (пока неопределенная) с представлением стека, используемым в качестве супервизора. См. Комментарии к вопросу и предоставленный ответ. – SuperDuperApps

1

Похоже, вы натыкаетесь на учебник «Начните разработку приложений для iOS (Swift)» перед его обновлением для iOS 10 и Swift 3. Удивительно, что вы сделали это так далеко! Во всяком случае, имеет @ Matt большое техническое объяснение ниже, но не включает в себя фактический код, чтобы получить учебник рабочих:

Добавьте следующие строки в определение класса (за пределами функции инициализации):

override var intrinsicContentSize: CGSize { 
    return CGSize(width: 240, height: 44) 
} 
+0

Спасибо, это полезно. Что касается учебника ... спасибо, да, хорошо, я прочитал все руководство по языку Swift 3 от Apple, прежде чем делать это, и Xcode очень хорошо указал на изменения. Проблемы помогли мне многому научиться. Но на самом деле это плохо, что Apple еще не обновила это, тем более, что они делают так много, что легко научиться создавать приложения для iOS. – SuperDuperApps