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

Как загрузить изображение в prepareForInterfaceBuilder с IBDesignable UIImageView

Я хотел бы загрузить образ образца в IB UIImageView, который будет отображаться в Interface Builder при редактировании интерфейса. Следующий код не работает, поскольку замещающий объект в IB остается пустым (область просмотра содержит только текст UIImageView):

@IBDesignable
class TestImageView : UIImageView
{
    override func prepareForInterfaceBuilder() {
        //let bundle = NSBundle.mainBundle()
        let bundle = NSBundle(forClass: nil)
        let imagePath = bundle.pathForResource("Test", ofType: "jpg")
        self.image = UIImage(contentsOfFile: imagePath)
    }
}

Обратите внимание, что:

  • в IB класс Custom Class для представления корректен (TestImageView)
  • Test.jpg присутствует в проекте (если я вручную установил свойство изображения UIImageView в IB, изображение появится).
  • Я попробовал два разных метода получения пакета в коде

Это было протестировано с помощью Xcode 6 beta 3.

Обновить: в обоих случаях путь пучка, который я получаю, равен "/Applications/Temporary/Xcode6-Beta3.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays". На этом пути изображение, очевидно, отсутствует.

4b9b3361

Ответ 1

Обновлено для Swift 4.2

Когда вы создаете экземпляр UIImage (с UIImage (с именем: "SomeName"), приложение будет искать ресурс в вашем основном комплекте, который обычно работает нормально. Но когда вы находитесь во время разработки, InterfaceBuilder содержит код проектируемых представлений ( для компиляции при проектировании) в отдельной связке.

Итак, решение таково: определите ваш пакет динамически, поэтому ваши файлы могут быть найдены во время разработки, компиляции и выполнения:

    // DYNAMIC BUNDLE DEFINITION FOR DESIGNABLE CLASS
    let dynamicBundle = Bundle(for: type(of: self))

    // OR ALTERNATIVELY BY PROVDING THE CONCRETE NAME OF YOUR DESIGNABLE VIEW CLASS
    let dynamicBundle = Bundle(for: YourDesignableView.self)

    // AND THEN SUCCESSFULLY YOU CAN LOAD THE RESSOURCE
    let image = UIImage(named: "Logo", in: dynamicBundle, compatibleWith: nil)

Ответ 2

Попробуйте получить пакет класса следующим образом:

let bundle = NSBundle(forClass: self.dynamicType)

или указав имя класса, подобное этому

let bundle = NSBundle(forClass: TestImageView.self)

Предполагая, что ваше изображение находится в комплекте, например Images.xcassets, вы можете загрузить его, используя:

self.image = UIImage("Test", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection)

Не забудьте проверить, нет ли вашего изображения, прежде чем пытаться его использовать. Я не смог получить путь к изображению с помощью метода bundle.pathForResource для правильной работы с обычными объектами изображения. Там также нет вызова UIImage, где вы указываете только имя и комплект, поэтому вам нужно использовать коллекцию признаков.

Этот вопрос связан с:

xcode 6 IB_DESIGNABLE - не загружать ресурсы из пакета в конструкторе интерфейса

Ответ от Apple...

Engineering определила, что эта проблема ведет себя как предполагаемая на следующем:

Мы не можем сделать это проще, чем указывать пакет. Вы может сказать: "О, пусть swizzle - [NSBundle mainBundle]", но много сайты звонков, которые ссылаются на пакет, не проходят там (или идут через CF API). Тогда можно сказать "хорошо, ну тогда как насчет наименее swizzle - [UIImage imageNamed:]". Проблема здесь в том, что там не является единственной заменой основного пучка. У вас может быть несколько в реальном времени (или фреймворки или приложения) загружаются сразу, поэтому мы не может просто выбрать один из них в качестве основного пучка.

Разработчики должны знать о связках и как получать изображения с расслоение. Разработчики должны использовать UIImage (имя: inBundle: compatibleWithTraitCollection:) для всех поисков изображений.

Ответ 3

Позволяет выбрать быстрый ответ

let bundle = Bundle(for: self.classForCoder)
... UIImage(named: "AnImageInYourAssetsFolderPerhaps", in: bundle, compatibleWith: self.traitCollection)!

Ответ 4

Мне удалось исправить проблему с получением пути проекта Interface Builder от текущего объекта NSProcessInfo. Затем вы можете собрать правильный путь из клавиши IB_PROJECT_SOURCE_DIRECTORIES.

override func prepareForInterfaceBuilder() {
    let processInfo = NSProcessInfo.processInfo()
    let environment = processInfo.environment
    let projectSourceDirectories : AnyObject = environment["IB_PROJECT_SOURCE_DIRECTORIES"]!
    let directories = projectSourceDirectories.componentsSeparatedByString(":")

    if directories.count != 0 {
        let firstPath = directories[0] as String
        let imagePath = firstPath.stringByAppendingPathComponent("PrepareForIBTest/Test.jpg")

        let image = UIImage(contentsOfFile: imagePath)
        self.image = image
    }
}

Эта методика описана в сессии WWDC 2014 411 "Что нового в построителе интерфейса", как предложено bjhomer в этом

Ответ 5

Для Swift 4 (и 3) используйте это:

let image = UIImage(named: "foo", in: Bundle(for: type(of: self)), compatibleWith: traitCollection)

Этот подход получает универсальный пакет

Ответ 6

Для Swift 2 и Xcode 7 интерфейс был изменен. Должен использовать

let bundle = NSBundle(forClass: self.dynamicType)
let image = UIImage(named: "imageName", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection)
let imageView = UIImageView(image: image)

Я использую его в мой проект, он отлично работает как для IB, так и для устройства.

Ответ 7

Это загрузит ваш IB_Designable, или если у вас его нет - изображение по умолчанию.

- (void)prepareForInterfaceBuilder
{
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    imagePic = imagePic ? [imagePic imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] : [UIImage imageNamed:@"goodIcon" inBundle:bundle compatibleWithTraitCollection:self.traitCollection];

}