17

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

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

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

谢谢你。

4

4 回答 4

13

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

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

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

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 应该构建项目并渲染视图

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

于 2016-10-12T13:28:58.693 回答
9

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

@IBDesignable
class MyCustomView: CustomView {

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

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

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

您可能会遇到此问题:从 IBDesignable 中的自定义控件框架加载代码 按照本指南解决此问题:http ://www.dribin.org/dave/blog/archives/2009/11/15/rpath/

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

如果你不能让它工作,请留下评论。

于 2016-06-04T15:21:25.277 回答
5

好吧,很明显,如果您想在其中包含@IBDesignable 和@IBInspectablea frameworkframework则必须是:

  • 包含在消费应用程序中,因此Framework不会在它自己的项目中。'file -> new.. -> target -> framework'(即通过从消费应用程序中执行某些操作来添加框架作为目标)。
  • external frameworkas 包含CocoaPod在您的消费应用程序中。这实际上添加了framework作为目标,而不仅仅是链接framework到应用程序。
    • 有一种方法可以将本地包含CocoaPods在项目中,因此不必担心您不必framework为了执行此操作而将其部署到公众。
于 2015-04-30T20:38:49.350 回答
5

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

显示 Headers 阶段的 Xcode Build Phases 选项卡的屏幕截图

于 2018-02-11T09:04:29.713 回答