我在将WorkListView导出为PDF时遇到了问题。下面是我的代码的一个简单示例:
客户端数据
class Client: ObservableObject,
Identifiable {
let name = "Foo"
@Published var work: [Work]
init() {
self.work = []
}
func addWork(_ work: Work) {
self.work.append(work)
}
}
工作数据
struct Work: Identifiable {
var id = UUID()
let content = "Bar"
}
工作列表视图
struct WorkListView: View {
@State var client: Client
@ObservedObject var clientData = ClientData()
@State private var showSheet = false
var body: some View {
VStack {
Button {
exportPDF {
self
} completion: { status, url in
if let url = url, status {
self.PDFUrl = url
self.showShareSheet.toggle()
}
else {
print("Failed to produce PDF")
}
}
} label: {
Image(systemName: "square.and.arrow.up.fill")
.font(.title3)
}
}
List {
Section {
Text(client.name)
}
Section(header: Text("Performed Work")) {
ForEach(client.work.indices) { work in
VStack {
Text(client.work[work].content)
}
}
}
}
.onTapGesture {
showSheet.toggle()
}
.sheet(isPresented: $showSheet, content: {
AddWorkView(client: client, showSheet: $showSheet)
})
.padding()
}
}
导出为PDF的功能
extension View {
func convertToScrollView<Content: View>(@ViewBuilder content: @escaping ()->Content)->UIScrollView {
let scrollView = UIScrollView()
let hostingController = UIHostingController(rootView: content()).view!
hostingController.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
hostingController.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
hostingController.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
hostingController.topAnchor.constraint(equalTo: scrollView.topAnchor),
hostingController.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
hostingController.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width)
]
scrollView.addSubview(hostingController)
scrollView.addConstraints(constraints)
scrollView.layoutIfNeeded()
return scrollView
}
func exportPDF<Content: View>(@ViewBuilder content: @escaping ()->Content, completion: @escaping (Bool,URL?)->()){
let documentDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
let outputFileURL = documentDirectory.appendingPathComponent("YOURPDFNAME\(UUID().uuidString).pdf")
let pdfView = convertToScrollView {
content()
}
pdfView.tag = 1009
let size = pdfView.contentSize
pdfView.frame = CGRect(x: 0, y: getSafeArea().top, width: size.width, height: size.height)
getRootController().view.insertSubview(pdfView, at: 0)
let renderer = UIGraphicsPDFRenderer(bounds: CGRect(x: 0, y: 0, width: size.width, height: size.height))
do {
try renderer.writePDF(to: outputFileURL, withActions: { context in
context.beginPage()
pdfView.layer.render(in: context.cgContext)
})
completion(true,outputFileURL)
}
catch {
completion(false,nil)
print(error.localizedDescription)
}
getRootController().view.subviews.forEach { view in
if view.tag == 1009 {
print("Removed")
view.removeFromSuperview()
}
}
}
func screenBounds()->CGRect {
return UIScreen.main.bounds
}
func getRootController()->UIViewController {
guard let screen = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
return .init()
}
guard let root = screen.windows.first?.rootViewController else {
return .init()
}
return root
}
func getSafeArea()->UIEdgeInsets {
guard let screen = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
return .zero
}
guard let safeArea = screen.windows.first?.safeAreaInsets else {
return .zero
}
return safeArea
}
}
我还有一个用于切换shareSheet的结构体。
所以这是我的工作列表视图,我希望能够导出到PDF。我只能设法导出它只是按钮。有人可以帮助我吗?
1条答案
按热度按时间rt4zxlrg1#
以下是将SwiftUI视图渲染为PDF的方法:
这是我们要保存的视图:
PDF管理器
用法
希望这对你有帮助:)