SwiftUI 把自定义的 View 和 Modifier 添加到 Xcode Library 中

2,099 阅读2分钟

在 Xcode 12 中,使用 LibraryContentProvider 协议将自定义的 ViewModifier 添加到 Library 中。在开发过程中直接拖拽即可。

预览

OK, 我们来看下具体是如何实现的!

自定义视图

首先创建一个内阴影 InnerShadow.swiftSwiftUI 文件。 具体代码:

import SwiftUI

struct InnerShadow<Content: View>: View {
    
    let color: Color
    let cornerRadius: CGFloat
    let content: Content
    
    init(color: Color = .gray, cornerRadius: CGFloat = 10, @ViewBuilder content: @escaping () -> Content) {
        self.color = color
        self.cornerRadius = cornerRadius
        self.content = content()
    }
    
    var body: some View {
        content
            .overlay(
                RoundedRectangle(cornerRadius: cornerRadius)
                    .stroke(Color.clear, lineWidth: 4)
                    .shadow(color: color, radius: 4, x: 4, y: 4)
                    .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
                    .shadow(color: color, radius: 3, x: -3, y: -3)
                    .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
        )
    }
}

struct InnerShadow_Previews: PreviewProvider {
    static var previews: some View {
        InnerShadow {
            Text("Hello SwiftUI").padding()
            .previewLayout(.fixed(width: 300, height: 300))
        }
    }
}

通过阴影和裁剪的组合方式实现这种效果:

添加到 Xcode Library 中

Xcode 工具栏选择 Editor -> Create Library Item

此时,当前文件底部会自动生成一个结构体:

点击去 LibraryContentProvider 看看

public protocol LibraryContentProvider {
	/// description...
    associatedtype ModifierBase = Any
	/// description...
    @LibraryContentBuilder var views: [LibraryItem] { get }
	/// description...
    func modifiers(base: Self.ModifierBase) -> [LibraryItem]
}

由代码可以看得出来,分别可以添加 viewmodifier 到 Library 中。

添加 views

先来实现以 views

struct InnerShadow_LibraryContent: LibraryContentProvider {
    
    var views: [LibraryItem] {
        LibraryItem(InnerShadow(content: { }))
    }
    
}

编译成功后,用快捷键 Command + Shift + L 打开 Xcode Library

nice~ 添加成功了。

你也可以定义 Library 的标题和分类。

struct InnerShadow_LibraryContent: LibraryContentProvider {
    
    var views: [LibraryItem] {
        LibraryItem(InnerShadow(content: { }), title: "My Inner Shadow", category: .control)
    }
    
}

添加 modifier

  • 先给 View 添加一个分类,实现 InnerShadow 方法
extension View {
    func innerShadow(color: Color = .gray, cornerRadius: CGFloat = 10) -> some View {
        InnerShadow(color: color, cornerRadius: cornerRadius) {
            self
        }
    }
}
  • 再给 InnerShadow_LibraryContent 实现方法 modifiers(base:) 这里有个泛型 ModifierBase, 意思是想给谁添加 modifier, 就写谁。 比如你想给 Text 添加,你就改为 Text, 给 Image 就改为 Image。我打算给所有的 View 添加,所以就用了 AnyView
@LibraryContentBuilder
    func modifiers(base: AnyView) -> [LibraryItem] {
        LibraryItem(base.innerShadow(color: .gray, cornerRadius: 10), title: "My Inner Shadow", category: .effect)
    }

@LibraryContentBuilder

modifier 和 views 返回的都是 [LibraryItem],添加上 @LibraryContentBuilder 后,就相当于返回单个或者多个 Library 对象,不需要用数组包括起来了

至于为啥上面的 views 不用添加也可以,emmm....

小结

经过上面的一系列操作,你就多了一种方式来实现自定义的 ViewModifier 了。当然,这样也仅仅是在当前的项目中实现了,换一个项目就没了。想要在其他项目中也显示的话,你可以通过以下方式实现:

  • 把文件拖入到新的项目中(废话)
  • 使用 Swift Package Manager 你可以自定义一些常用的小组件并给他们创建自定义库,打包到 SMP,上传到 GithubGiteeGitlab。或者是放到你本地都可以。在新项目开始的时候,作为依赖集成进去。这样不失为一个很不错的方法。

代码片段