In Xcode 12, use the LibraryContentProvider protocol to add custom Views and Modifier to the Library. Drag and drop during development.

OK, let’s see how it works!

Custom view

Start by creating an InnerShadow innershadow. swift SwiftUI file. Specific code:

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))}}}Copy the code

This effect is achieved through a combination of shadows and clipping:

Add to Xcode Library

Xcode toolbar select Editor -> Create Library Item

A structure is automatically generated at the bottom of the current file:

Check out LibraryContentProvider

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

As can be seen from the code, you can add view and Modifier to the Library, respectively.

Add the views

First to implement to views

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

Once compiled, open the Xcode Library with the shortcut keys Command + Shift + L

You can also define Library titles and categories.

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

Adding modifier

  • First,ViewAdd a classification to the implementationInnerShadowmethods
extension View {
    func innerShadow(color: Color = .gray, cornerRadius: CGFloat = 10) -> some View {
        InnerShadow(color: color, cornerRadius: cornerRadius) {
            self}}}Copy the code
  • giveInnerShadow_LibraryContentImplementation methodmodifiers(base:)

There is a generic ModifierBase, which means you can write to whoever you want to add modifier to. So if you want to add something to Text, you change it to Text, and to Image, you change it to Image. I’m going to add it to all the Views, so I’m going to use AnyView

@LibraryContentBuilder
    func modifiers(base: AnyView)- > [LibraryItem] {
        LibraryItem(base.innerShadow(color: .gray, cornerRadius: 10), title: "My Inner Shadow", category: .effect)
    }
Copy the code

@LibraryContentBuilder

The modifier and Views returns [LibraryItem]. Adding @LibraryContentBuilder to the modifier returns a single or multiple Library objects without the need to include them in an array

As for why the above views do not need to add also can, emmm….

summary

After a series of operations above, you have one more way to implement a custom View or Modifier. Of course, this is only implemented in the current project, the next project is gone. If you want to display it in other projects, you can do this:

  • Drag files into a new project (duh)
  • Use Swift Package Manager

You can customize common widgets and create custom libraries for them, package them into SMP, and upload them to Github, Gitee, and Gitlab. Or you can put it locally. Integrate as dependencies at the start of a new project. This is a good way to do it.

Code snippet