【问题标题】:IBDesignable from External Framework?IBDesignable 来自外部框架?
【发布时间】:2015-07-08 03:30:32
【问题描述】:

我想创建一些使用@IBDesignable@IBInspectable 标签的自定义视图。我已将这些添加到我的框架中,然后将我的框架链接到我的测试应用程序。但Designables从未出现在故事​​板中。

如何使用@IBDesignable@IBInspectable 从外部框架创建自定义视图?

您可以在非嵌入式框架的应用程序中使用@IBDesignable@IBInspectable 吗?

谢谢。

【问题讨论】:

    标签: ios swift storyboard ios-frameworks ibdesignable


    【解决方案1】:

    我找到了一种将可设计对象和可检查对象与 Cocoa Touch 框架一起使用的方法。以下说明适用于 Objective-C 项目和 Xcode 8(我没有在旧版本上测试),如果涉及 Swift 代码,应该是相同的。

    由于 Interface Builder 在框架中没有发现可设计对象,因此在框架标头中将类标记为 IB_DESIGNABLE 是没有用的。 Interface Builder 只会在编译项目源文件时发现可设计的类。因此,我们的想法是将这些信息作为框架配套源文件提供,然后客户可以使用他们的项目对其进行编译。

    我发现您不必子类化即可将框架类标记为项目中的可设计类。您可以简单地注释每个必须通过伴随.msource 文件中声明的类别来指定的类,例如:

    IB_DESIGNABLE
    @interface MyCustomView (Designable)
    
    @end
    

    事实上,代码甚至不需要编译,你可以将它包装在一个封闭的#if 0 ... #endif 中,它仍然可以工作。所需要的只是该类以某种方式与IB_DESIGNABLE 属性相关联。

    考虑到这些信息,以下是如何使可设计对象与 Cocoa Touch 框架一起使用:


    如果您是框架供应商:

    1. 如果需要,有必须可设计的组件实现-prepareForInterfaceBuilder
    2. 将文件夹引用(蓝色文件夹)添加到您的框架目标,其中包含伴随的.m 文件。可能的命名约定是将文件夹命名为 Designables 和其中的文件 MyFrameworkNameDesignables.m,但你可以选择你最喜欢的。
    3. .m 文件中,为每个必须可设计的视图创建一个与上述类似的类别。文件本身必须可由客户端项目编译,这意味着您需要进行必要的导入(例如,您的框架全局公共标头 #import <MyFramework/MyFramework.h>)或使用上面的 #if 0 ... #endif 技巧

    通过将文件包含在蓝色文件夹中,我们确保该文件夹按原样复制到最终的.framework 产品中,而不会编译伴随的源文件。此外,由于该文件夹是框架包的一部分,它可供框架的所有客户端使用,无论是直接集成还是使用 Carthage。

    如果您有一个使用框架作为目标依赖项的演示项目,并且如果您的框架依赖于其他框架,则在尝试在演示项目中呈现可设计视图时会遇到dlopen 问题。这是因为在框架目标中发现了IB_DESIGNABLE 属性(因为已将Designables 文件夹添加到其中),Xcode 预构建在与您的项目对应的Build/Intermediates/IBDesignables 派生数据文件夹中。如果您查看此文件夹的内容,则缺少框架依赖项,从而导致dlopen 问题。

    要修复演示中的渲染,只需将 Copy Files 阶段添加到框架目标,将每个所需的框架依赖项添加到文件列表中,并将 Products 目录 设置为目的地。现在,当 Xcode 构建您的演示以进行渲染时,它也会包含依赖项。


    如果您是具有可设计支持的框架的用户:

    • 将框架(及其所有框架依赖项,如果有)作为嵌入式二进制文件添加到您的目标
    • 从框架包中检索配套源文件并将其复制到您的项目中,并将其添加到您的目标中。遗憾的是,添加位于框架内的文件或使用符号链接不起作用,因为 Xcode 似乎根本不在框架内查看
    • 将可设计视图类的实例(在我们上面的示例中为MyCustomView)添加到情节提要。 Interface Builder 应该构建项目并渲染视图

    此解决方案并不完美,因为您仍然必须手动复制提供的源文件,这可能会在框架版本之间发生变化。但它工作得很好,并且提供了框架包本身所需的一切。

    【讨论】:

    • 这太棒了。太糟糕了,Apple 不断添加这些“功能”,这些“功能”远不及“成品”产品 :(希望有一天他们会提出解决方案。我真的看不出让 IBDesignable 和 IBInspectable 工作的任何价值具有自己的框架目标。这些价值尤其体现在允许第 3 方在项目的情节提要中绘制他们的控件。
    【解决方案2】:

    我有一个解决方法。使用此解决方法,您无需将框架添加为目标。所以它适用于Carthage

    @IBDesignable
    class MyCustomView: CustomView {
    
        @IBInspectable override var bgColor: NSColor {
            get {
                return super.bgColor
            }
            set {
                super.bgColor = newValue
            }
        }
    }
    

    在目标项目(不在框架项目中)创建自定义类(CustomView)的子类(MyCustomView),并将子类标记为@IBDesignable。在您的应用程序中使用子类。这种方式使@IBDesignable 工作。

    在子类中,覆盖那些@IBInspectable 属性(bgColor),这样@IBInspectable 就可以工作了。

    您可能会遇到此问题:Loading code from a framework for a custom control in IBDesignable 按照本指南解决此问题:http://www.dribin.org/dave/blog/archives/2009/11/15/rpath/

    请同时公开自定义类及其可检查的属性,否则此方法无法编译。

    如果你不能让它工作,请离开 cmets。

    【讨论】:

      【解决方案3】:

      UICircularProgressRing 通过在框架Headers 文件夹中添加包含@IBDesignable 类的Swift 文件来解决这个问题。为此,选择框架的 Xcode 项目,选择框架的目标,然后转到 Build Phases 选项卡并展开 Headers 阶段,然后将 Swift 文件放入 公开:

      【讨论】:

      • 解决不了。我用 Carthage 尝试了 UICircularProgressRing,但它不起作用(但它适用于 CocoaPods)
      • 在 3.0.0 版之前是这样。该文件不再是最新版本。但是只用了一周的时间,我就可以让 3.0.0 版正常工作。您需要使用 carthage 的 checkout 文件夹中的 UICircularProgressRing.swift 文件,并使用上面相同的方法,它就像一个魅力。
      • 这行得通。将包含 @IBInpectable.swift 文件添加到公共标头,然后重建 Carthage 项目。
      【解决方案4】:

      好吧,如果你想在framework 中包含@IBDesignable 和@IBInspectable,那么framework 必须是:

      • 包含在消费应用程序中,因此Framework 不会出现在它自己的项目中。 (即,通过在消费应用程序中执行 'file -> new.. -> target -> framework' 之类的操作,将框架添加为目标)。
      • 在您的消费应用程序中包含external framework 作为CocoaPod。这实际上将framework 添加为目标,而不仅仅是将framework 链接到应用程序。
        • 有一种方法可以在项目中包含本地 CocoaPods,因此不必担心,您不必为了执行此操作而将 framework 部署到公众。

      【讨论】:

      • 真的是唯一的解决方案吗?
      • 当框架位于其自己的单独 Xcode 项目中时,这是我发现的唯一可行的解​​决方案。如上所述,如果您将框架创建为消费项目中的嵌入式框架,一切都会好起来的,您不需要将框架创建为 CocoaPod。
      • 我认为@defagos 目前在这里有最好的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 2016-08-20
      • 1970-01-01
      • 1970-01-01
      • 2021-06-22
      相关资源
      最近更新 更多