You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI签名预览无法显示最后一笔绘制内容的问题求助

签名预览无法实时显示最后一笔绘制内容的解决方案

我在将signatureView.signature存入变量并直接作为图片输出时,遇到了无法显示最后一笔绘制内容的问题——绘制2笔仅显示第1笔,绘制3笔仅显示前2笔,始终无法显示最后一笔。


相关代码

主视图核心代码

@State private var signatureImage: UIImage? 
@Binding var signature: String


SignatureCaptureView(signatureImage: $signatureImage) 
    .frame(height: 200) 
    .border(Color.gray, width: 1)


if let img = signatureImage {
        Image(uiImage: img)
        .resizable()
        .scaledToFit()
        .frame(width: 300, height: 200)
        .background(Color.gray.opacity(0.2))
        .id(UUID())
} else {
    Text("Noch keine Unterschrift")
        .background(Color.gray.opacity(0.2))
        .frame(width: 300, height: 200)
}

SignatureCaptureView.swift代码

import SwiftUI
import SwiftSignatureView


struct SignatureCaptureView: UIViewRepresentable {
    @Binding var signatureImage: UIImage?
    private var signatureView: SwiftSignatureView // 未使用的冗余属性
    var coordinator: Coordinator? // 未使用的冗余属性

    func getCroppedSignature(from view: SwiftSignatureView) -> UIImage? {
        return view.getCroppedSignature()
    }

    init(signatureImage: Binding<UIImage?>) {
        self._signatureImage = signatureImage
        self.signatureView = SwiftSignatureView()
    }
    func makeUIView(context: Context) -> SwiftSignatureView {
        let signatureView = SwiftSignatureView()
        signatureView.delegate = context.coordinator
        return signatureView
    }

    func updateUIView(_ uiView: SwiftSignatureView, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, SwiftSignatureViewDelegate {
        var parent: SignatureCaptureView
        var signatureView: PencilKitSignatureView? // 未正确使用的属性


        init(_ parent: SignatureCaptureView) {
            self.parent = parent
        }

        
        func updateUIView(_ view: ISignatureView) {
            if let signatureView = view as? PencilKitSignatureView {
                parent.signatureImage = signatureView.signature
                view.signature = signatureView.signature
            }
            
        }

        func swiftSignatureViewDidDrawGesture(_ view: ISignatureView, _ tap: UIGestureRecognizer) {
            if let signatureView = view as? PencilKitSignatureView {
                // 未启用的更新逻辑
            }
        }

        func swiftSignatureViewDidDraw(_ view: ISignatureView) {
            print("triggered: DidDraw")
            if let signatureView = view as? PencilKitSignatureView {
                print("saving...")
               parent.signatureImage = signatureView.signature
            } else {
                print("View konnte nicht zu PencilKitSignatureView gecastet werden")
            }
        }
    }
}

完整SignatureView代码

import SwiftUI
import SwiftSignatureView

struct SignatureView: View {
    @State private var signatureImage: UIImage?
    @Binding var signature: String


    var body: some View {
        VStack(spacing: 20) {
            Text("Bitte unterschreiben:")
                .font(.headline)
            
            SignatureCaptureView(signatureImage: $signatureImage)
                .frame(height: 200)
                .border(Color.gray, width: 1)
        }
        VStack {
            HStack(spacing: 20) {
                Button("Speichern") {
                    if let img = signatureImage {
                        if let data = img.pngData() {
                            signature = data.base64EncodedString()
                        } else {
                            print("Fehler bei der Datenkonvertierung")
                        }
                    } else {
                        print("Kein Bild vorhanden")
                    }
                }


                Button("Zurücksetzen") {
                    signatureImage = nil
                    // 未重置签名绘制视图
                }
            }

            // 签名预览区域
            ZStack {
                if let img = signatureImage {
                    Image(uiImage: img)
                        .resizable()
                        .scaledToFit()
                        .frame(width: 300, height: 200)
                        .background(Color.gray.opacity(0.2))
                        .id(UUID())
                } else {
                    Text("Noch keine Unterschrift")
                        .background(Color.gray.opacity(0.2))
                        .frame(width: 300, height: 200)
                }
            }
        }
        .padding()
    }
}

问题表现截图

  • 绘制2笔时的预览效果:
    绘制2笔的预览效果
  • 绘制第3笔(1和2之间的线条)时,预览仍不显示该笔:
    绘制3笔的预览效果

修复方案

问题根源

  1. swiftSignatureViewDidDraw回调触发时,signatureView.signature可能尚未完成最新绘制内容的渲染
  2. 代码中存在未使用的冗余属性,导致逻辑混乱
  3. 预览视图中.id(UUID())强制重建视图,干扰了状态驱动的更新逻辑

修复步骤

  1. 移除冗余属性:删除SignatureCaptureView中未使用的signatureView和coordinator属性
  2. 修正图像获取逻辑:使用getCroppedSignature()方法替代直接读取signature,确保获取完整渲染的签名图像
  3. 主线程更新状态:SwiftUI状态更新必须在主线程执行,添加DispatchQueue.main.async调度
  4. 优化预览视图:移除.id(UUID()),让状态变化自然驱动视图更新

修复后的SignatureCaptureView代码

import SwiftUI
import SwiftSignatureView

struct SignatureCaptureView: UIViewRepresentable {
    @Binding var signatureImage: UIImage?
    private var signatureView: SwiftSignatureView? // 保存视图引用用于重置

    func getCroppedSignature(from view: SwiftSignatureView) -> UIImage? {
        return view.getCroppedSignature()
    }

    init(signatureImage: Binding<UIImage?>) {
        self._signatureImage = signatureImage
    }

    func makeUIView(context: Context) -> SwiftSignatureView {
        let view = SwiftSignatureView()
        view.delegate = context.coordinator
        self.signatureView = view
        return view
    }

    func updateUIView(_ uiView: SwiftSignatureView, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    // 添加重置签名方法
    func resetSignature() {
        signatureView?.clear()
        signatureImage = nil
    }

    class Coordinator: NSObject, SwiftSignatureViewDelegate {
        var parent: SignatureCaptureView

        init(_ parent: SignatureCaptureView) {
            self.parent = parent
        }

        func swiftSignatureViewDidDraw(_ view: ISignatureView) {
            guard let signatureView = view as? SwiftSignatureView else {
                print("View konnte nicht zu SwiftSignatureView gecastet werden")
                return
            }
            DispatchQueue.main.async {
                self.parent.signatureImage = signatureView.getCroppedSignature()
            }
        }
    }
}

修复后的预览视图代码(SignatureView中ZStack部分)

ZStack {
    if let img = signatureImage {
        Image(uiImage: img)
            .resizable()
            .scaledToFit()
            .frame(width: 300, height: 200)
            .background(Color.gray.opacity(0.2))
    } else {
        Text("Noch keine Unterschrift")
            .background(Color.gray.opacity(0.2))
            .frame(width: 300, height: 200)
    }
}

完善重置功能

修改SignatureView中的"Zurücksetzen"按钮,添加签名视图重置逻辑:

// 先给SignatureCaptureView添加@StateObject或使用PreferenceKey获取引用,这里简化使用@Binding传递重置信号
// 例如在SignatureView中添加:
@State private var shouldReset = false

// 然后修改SignatureCaptureView调用reset方法
SignatureCaptureView(signatureImage: $signatureImage)
    .frame(height: 200)
    .border(Color.gray, width: 1)
    .onChange(of: shouldReset) { newValue in
        if newValue {
            // 获取视图引用并调用resetSignature(),可通过PreferenceKey实现
            shouldReset = false
        }
    }

// 按钮修改为:
Button("Zurücksetzen") {
    shouldReset = true
}

内容的提问来源于stack exchange,提问作者Arakel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:10:57