Подтвердить что ты не робот

Не удалось загрузить IBDesignable xib в построителе интерфейса

У меня есть xib (childXib), связанный с его пользовательским UIView swift через его владельца.

Вот как я инициализирую свой пользовательский UIView:

// init for IBDesignable
override init(frame: CGRect) {
    super.init(frame: frame)

    let view = loadViewFromNib()
    view.frame = bounds

    addSubview(view)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    addSubview(loadViewFromNib())
}

func loadViewFromNib() -> UIView {

    let bundle = NSBundle(forClass: self.dynamicType)
    let nib = UINib(nibName: "CommentCellView", bundle: bundle)
    let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

    return view
}

Когда я хочу добавить этот xib (childXib) в другой xib (parentXib), я получаю следующие ошибки:

ошибка: IB Designables: не удалось отобразить экземпляр MyRootView: агент выдал исключение.

Где MyRootView - это файл, связанный с parentXib

ошибка: IB Designables: не удалось обновить состояние автоматического макета: агент вызвал исключение "NSInternalInconsistencyException": не удалось загрузить NIB в комплекте: "NSBundle (загружен)" с именем "MyIBDesignableCustomViewFilename"

Где MyIBDesignableCustomViewFilename - это файл, связанный с childXib.

Когда я отлаживаю его, нажимая " Debug в Custom class из Identity inspector, он не работает из этой строки:

let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

Все файлы xib находятся в Copy Bundle Resources на xib Build Phases.

Есть идеи, что не так?

4b9b3361

Ответ 1

Первый шаг:

Я дам вам введение в IBDesignable и IBInspectable и покажу вам, как использовать новую функцию. Нет лучшего способа разработать функцию, кроме создания демонстрации. Поэтому мы создадим собственный интерфейс под названием "Радуга" вместе.

IBDesignable и IBInspectable

С IBDesignable и IBInspectable разработчикам разрешено создавать интерфейс (или просмотр), который отображается в интерфейсе Builder в режиме реального времени. В общем, для применения этой новой функции все, что вам нужно сделать, это создать визуальный класс путем подкласса UIView или UIControl, а затем префикс имени класса с помощью ключевого слова @IBDesignable в Swift. Если вы используете Objective-C, вместо этого вы используете макрос IB_DESIGNABLE. Вот пример кода в Swift:

@IBDesignable 
class Rainbow: UIView {
}

В старых версиях Xcode вы можете редактировать пользовательские атрибуты времени выполнения для изменения свойств объекта (например, layer.cornerRadius) в Interface Builder. Проблема в том, что вам нужно указать точное имя свойств. IBInspectable делает шаг вперед. Когда вы префикс свойства визуального класса с IBInspectable, свойство будет отображаться в Interface Builder, так что вы можете изменить его значение очень простым способом:

введите описание изображения здесь

Опять же, если вы разрабатываете свое приложение в Swift, вам нужно просто прикрепить выбранное вами свойство к ключевому слову @IBInspectable. Вот пример фрагмента кода:

@IBInspectable var firstColor: UIColor = UIColor.blackColor()
 {
     // Update your UI when value changes
 }



@IBInspectable var firstColor: UIColor = UIColor.blackColor()
{
     // Update your UI when value changes
 }

Создание проекта Xcode

Давайте начнем с создания нового проекта в Xcode и выберите Single View Application в качестве шаблона и назовите его RainbowDemo. Мы будем использовать Swift в этом проекте в качестве языка программирования, поэтому не забудьте выбрать его при создании проекта.

После завершения выберите Main.storyboard в Навигаторе проектов и перетащите объект View из библиотеки объектов в контроллер просмотра. Измените цвет на # 38334C (или любой цвет, который вы хотите), а также установите его размер 600 на 434. Затем поместите его в центр основного вида. Не забудьте изменить цвет основного вида на тот же цвет объекта вида. Совет. Если вы хотите изменить значения цвета RGB для своего кода, просто откройте свою палитру цветов и перейдите на вкладку "Слайдеры", чтобы изменить значения RGB.

Смущение? Не беспокойся. Вы поймете, что я имею в виду, пройдя демонстрацию проекта.

С помощью Xcode 6 вам нужно настроить ограничения автоматического макета для представления, чтобы поддерживать все типы устройств iOS. Автоматическая компоновка довольно мощная в последней версии Xcode. Для простых ограничений вы можете просто нажать кнопку "Проблемы" в меню "Автомакет" и выбрать "Добавить отсутствующие ограничения", а Xcode автоматически настроит ограничения макета для представления.

введите описание изображения здесь

Создание класса пользовательского вида

Теперь, когда вы создали представление в раскадровке, пришло время создать наш пользовательский класс представления. Хорошо используйте шаблон класса Swift для создания класса. Назовите его "Радуга" .

введите описание изображения здесь

Then insert the following code in the class:

import UIKit

class Rainbow: UIView {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }
}

Как уже упоминалось ранее, визуальный класс является подклассом UIView. Чтобы использовать наш собственный класс в режиме реального рендеринга, нам нужно переопределить оба инициализатора, как показано выше. Затем разделите вид, выбрав помощник редактора:

введите описание изображения здесь

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

Реализация IBDesignable Controls

Первым шагом, чтобы включить элемент управления для рендеринга в реальном времени, является установка настраиваемого представления как Designable путем префикса имени класса с помощью @IBDesignable:

@IBDesignable 
class Rainbow: UIView {
    ...
}

Его просто, как вы можете видеть. Но это простое ключевое слово значительно упростит вашу разработку. Затем добавим несколько свойств для установки цветов кругов. Вставьте эти строки кода в класс Rainbow:

@IBInspectable var firstColor: UIColor = UIColor(red: (37.0/255.0), green: (252.0/255), blue: (244.0/255.0), alpha: 1.0)
@IBInspectable var secondColor: UIColor = UIColor(red: (171.0/255.0), green: (250.0/255), blue: (81.0/255.0), alpha: 1.0)
@IBInspectable var thirdColor: UIColor = UIColor(red: (238.0/255.0), green: (32.0/255)

Здесь мы предопределяем каждое свойство цветом по умолчанию и сообщаем ему перерисовывать представление каждый раз, когда пользователь меняет свое значение. Самое главное, мы префикс каждого свойства с ключевым словом @IBInspectable. Если вы перейдете к атрибутам, доступным для просмотра, вы должны визуально найти эти свойства:

Прохладно, да? Указывая свойства как IBInspectable, вы можете редактировать их визуально с помощью выбора цвета.

Окно позволяет перейти к реализации основных методов класса Rainbow, который используется для рисования круга на экране. Вставьте следующий класс в класс:

func addOval(lineWidth: CGFloat, path: CGPathRef, strokeStart: CGFloat, strokeEnd: CGFloat, strokeColor: UIColor, fillColor: UIColor, shadowRadius: CGFloat, shadowOpacity: Float, shadowOffsset: CGSize) {

    let arc = CAShapeLayer()
    arc.lineWidth = lineWidth
    arc.path = path
    arc.strokeStart = strokeStart
    arc.strokeEnd = strokeEnd
    arc.strokeColor = strokeColor.CGColor
    arc.fillColor = fillColor.CGColor
    arc.shadowColor = UIColor.blackColor().CGColor
    arc.shadowRadius = shadowRadius
    arc.shadowOpacity = shadowOpacity
    arc.shadowOffset = shadowOffsset
    layer.addSublayer(arc)
}

введите здесь описание изображения

Чтобы сделать код чистым и читаемым, мы создаем общий метод для рисования полного или полукруга в соответствии с параметрами, предоставленными вызывающим. Его довольно просто нарисовать круг или дугу, используя класс CAShapeLayer. Вы можете управлять началом и концом стока, используя свойства strokeStart и strokeEnd. Изменяя значение stokeEnd между 0.0 и 1.0, вы можете нарисовать полный или частичный круг. Остальные свойства используются только для установки цвета штриха, теневого цвета и т.д. Вы можете проверить официальную документацию для получения информации о всех свойствах, доступных в CAShapeLayer.

Затем добавьте следующие методы в класс Rainbow:

override func drawRect(rect: CGRect) {
    // Add ARCs
    self.addCirle(80, capRadius: 20, color: self.firstColor)
    self.addCirle(150, capRadius: 20, color: self.secondColor)
    self.addCirle(215, capRadius: 20, color: self.thirdColor)
}

func addCirle(arcRadius: CGFloat, capRadius: CGFloat, color: UIColor) {
    let X = CGRectGetMidX(self.bounds)
    let Y = CGRectGetMidY(self.bounds)

    // Bottom Oval
    let pathBottom = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath
    self.addOval(20.0, path: pathBottom, strokeStart: 0, strokeEnd: 0.5, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero)

    // Middle Cap
    let pathMiddle = UIBezierPath(ovalInRect: CGRectMake((X - (capRadius/2)) - (arcRadius/2), (Y - (capRadius/2)), capRadius, capRadius)).CGPath
    self.addOval(0.0, path: pathMiddle, strokeStart: 0, strokeEnd: 1.0, strokeColor: color, fillColor: color, shadowRadius: 5.0, shadowOpacity: 0.5, shadowOffsset: CGSizeZero)

    // Top Oval
    let pathTop = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath
    self.addOval(20.0, path: pathTop, strokeStart: 0.5, strokeEnd: 1.0, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero)

}

По умолчанию реализация метода drawRect ничего не делает. Чтобы рисовать круги в представлении, мы переопределяем метод для реализации нашего собственного кода рисования. Метод addCircle имеет три параметра: arcRadius, capRadius и цвет. arcRadius - радиус круга, а capRadius - радиус закругленной крышки.

Метод addCircle использует UIBezierPath для рисования дуг, и он работает следующим образом:

First it draws a half circle at the bottom
Next it draws a full small circle at the edge of the arc.
Finally, it draws the other half of the circle

В методе drawRect мы вызываем метод addCircle три раза с разным радиусом и цветом. Этот рисунок иллюстрирует, как рисуются круги: введите описание изображения здесь

Совет. Если вам нужна дополнительная информация о UIBezierPath, вы можете проверить официальную документацию Apple.

С помощью свойств IBInspectable теперь вы можете изменять цвет каждого круга прямо в построителе интерфейса без погружения в код:

Очевидно, что вы можете дополнительно вывести arcRadius в качестве свойства IBInspectable. Я оставляю это как упражнение для вас.

введите описание изображения здесь

введите описание изображения здесь

для примера кода нажмите здесь: https://github.com/appcoda/Rainbow-IBDesignable-Demo

Ответ 2

У меня была такая же проблема, и мне удалось ее исправить.

Swift 3

let bundle = Bundle(for: MyView.self)
let view = UINib(nibName: "MyView", bundle: bundle).instantiate(withOwner: self) as! MyView

Важным битом является пакет

Ответ 3

Для обеих ошибок, как показано ниже:

error: IB Designables: Failed to render instance of ....
error: IB Designables: Failed to update auto layout status: The agent raised a "NSInternalInconsistencyException" exception: Could not load NIB in bundle ...

Я предлагаю, чтобы небольшая быстрая самоконтроль могла помочь выяснить, где должны быть устранены проблемы:

  • Проверьте, правильно ли добавлены файлы .xib в проект
  • Проверьте, правильно ли установлено nibName, иногда происходит опечатка
  • Проверьте, правильно ли подключены оба выхода и действия, включите кодов.