Swift, iboutlet и пользовательские элементы управления

Я могу делать что-то действительно глупое, но, похоже, я не могу использовать Interface Builder для подключения переменных IBOutlet к пользовательским представлениям, но только в Swift.

Я создал класс MyView, который простирается от UIView. В моем контроллере у меня есть переменная MyView (объявленная как @IBOutlet var newView: MyView). Я перехожу в IB и перетаскиваю UIView в окно и даю ему класс MyView.

Всякий раз, когда я делал подобное в Objective C, я мог бы щелкнуть по кнопке View Controller в верхней части окна приложения, выбрать переменную и перетащить ее в элемент управления, чтобы связать их вместе. Когда я пробую его в Swift, он отказывается признать, что вид есть.

Если я изменю класс переменной в контроллере на UIView, он отлично работает. Но не с моим пользовательским представлением.

У кого-нибудь еще была эта проблема? И это особенность, или просто мой идиотизм?

Код для контроллера

import UIKit

class ViewController: UIViewController {

    @IBOutlet var newView:MyView

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Код для просмотра

import UIKit

class MyView: UIView {

    init(frame: CGRect) {
        super.init(frame: frame)
        // Initialization code
    }

    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect)
    {
        // Drawing code
    }
    */

}

Ответ 1

У меня была аналогичная проблема, и я думаю, что это частично проблема кеширования и частично просто проблема Xcode6/Swift. Первый шаг, который я нашел, был необходим, чтобы убедиться, что файл диспетчера view.swift будет загружен в Редакторе помощника при выборе "автоматический".

С помощью Xcode, обнаруживающего, что оба файла связаны, я иногда мог управлять перетаскиванием из представления/кнопки/и т.д. от IB до файла .swift, но часто приходилось перетаскивать из пустого круга в желобе строки @IBOutlet var newView:MyView в представление, которое я хотел, чтобы оно соответствовало.

Если вы не можете загрузить файл в Редактор помощников, я обнаружил, что часто выполняются следующие действия:

  • Удалить пользовательский класс из представления IB
  • Очистите проект (cmd + K)
  • Закрыть/повторно открыть Xcode
  • Возможно, снова очистится?
  • Добавить пользовательский класс обратно в представление
  • Надеюсь, что он работает:)

Если это похоже на то, что вы получаете половину пути/нигде не добавляете комментарий, и я увижу, запускает ли он что-нибудь еще, что я сделал

Ответ 2

В моем случае import UIKit отсутствовал, после добавления этой строки я мог снова создать IBOutlet из Storyboard.

Ответ 3

У меня была аналогичная проблема с тем, что описывается в этом потоке. Возможно, вы нашли решение, возможно, не тем, кто сталкивается с этим в будущем. Я нашел ключ, чтобы использовать функцию "требуемого init" следующим образом:

required init(coder aDecoder: NSCoder) {
    print("DrawerView: required init")
    super.init(coder: aDecoder)!
    screenSize = UIScreen.mainScreen().bounds
    screenWidth = screenSize.width
    screenHeight = screenSize.height
    self.userInteractionEnabled = true
    addCustomGestureRecognizer()
}

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

import UIKit import Foundation

класс DrawerView: UIView {

var screenSize: CGRect!
var screenWidth: CGFloat!
var screenHeight: CGFloat!

var drawerState: Int = 0

override init (frame : CGRect) {
    print("DrawerView: main init")
    super.init(frame : frame)
}

override func layoutSubviews() {
    print("DrawerView: layoutSubviews")
    super.layoutSubviews()
}

convenience init () {
    self.init(frame:CGRect.zero)
}

required init(coder aDecoder: NSCoder) {
    print("DrawerView: required init")
    super.init(coder: aDecoder)!
    screenSize = UIScreen.mainScreen().bounds
    screenWidth = screenSize.width
    screenHeight = screenSize.height
    self.userInteractionEnabled = true
    addCustomGestureRecognizer()
}

func addCustomGestureRecognizer (){
    print("DrawerView: addCustomGestureRecognizer")
    let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(self.handleDrawerSwipeGesture(_:)))
    swipeDown.direction = UISwipeGestureRecognizerDirection.Down
    self.addGestureRecognizer(swipeDown)
    let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(self.handleDrawerSwipeGesture(_:)))
    swipeUp.direction = UISwipeGestureRecognizerDirection.Up
    self.addGestureRecognizer(swipeUp)
    print("DrawerView self: \(self)")
}

func minimizeDrawer(){
    UIView.animateWithDuration(0.25, delay: 0.0, options: .CurveEaseOut, animations: {
        //            let height = self.bookButton.frame.size.height
        //            let newPosY = (self.screenHeight-64)*0.89
        //            print("newPosY: \(newPosY)")
        self.setY(self.screenHeight*0.86)
        }, completion: { finished in
            self.drawerState = 0
            for view in self.subviews {
                if let _ = view as? UIButton {
                    let currentButton = view as! UIButton
                    currentButton.highlighted = false
                } else if let _ = view as? UILabel {
                    let currentButton = view as! UILabel
                    if self.tag == 99 {
                        currentButton.text = "hisotry"
                    } else if self.tag == 999 {
                        currentButton.text = "results"
                    }
                }
            }
    })
}

func handleDrawerSwipeGesture(gesture: UIGestureRecognizer) {
    print("handleDrawerSwipeGesture: \(self.drawerState)")
    if let swipeGesture = gesture as? UISwipeGestureRecognizer {
        switch self.drawerState{
        case 0:
            if swipeGesture.direction == UISwipeGestureRecognizerDirection.Down {
                // nothing to be done, mini and swiping down
                print("mini: !")
            } else {
                // mini and swiping up, should go to underneath city box
                UIView.animateWithDuration(0.25, delay: 0.0, options: .CurveEaseOut, animations: {
                    let toYPos:CGFloat = 128 + 64 + 8
                    self.setY(toYPos)
                    }, completion: { finished in
                        self.drawerState = 1
                        for view in self.subviews {
                            if let _ = view as? UIButton {
                                let currentButton = view as! UIButton
                                currentButton.highlighted = true
                            } else if let _ = view as? UILabel {
                                let currentLabel = view as! UILabel
                                currentLabel.text = "close"
                            }
                        }

                })
            }
            break;
        case 1:
            if swipeGesture.direction == UISwipeGestureRecognizerDirection.Down {
                // open and swiping down
                self.minimizeDrawer()
            } else {
                // open and swiping up, nothing to be done
            }
            break;
        default:
            break;
        }
    }
}

}

Надеюсь, что это поможет...