diff --git a/iAppStore.xcodeproj/project.pbxproj b/iAppStore.xcodeproj/project.pbxproj index 001e492..2e99591 100644 --- a/iAppStore.xcodeproj/project.pbxproj +++ b/iAppStore.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 6D738E2C2779736400A4A76E /* SubscriptionHome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D738E2B2779736400A4A76E /* SubscriptionHome.swift */; }; 6D738E2E2779736B00A4A76E /* SettingHome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D738E2D2779736B00A4A76E /* SettingHome.swift */; }; 6D738E322779743D00A4A76E /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D738E312779743D00A4A76E /* Color.swift */; }; + 6D7A39492A46968100CA7F6E /* QRCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D7A39482A46968100CA7F6E /* QRCodeView.swift */; }; 6D89AF85277879190075E66F /* iAppStoreApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D89AF84277879190075E66F /* iAppStoreApp.swift */; }; 6D89AF89277879190075E66F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D89AF88277879190075E66F /* Assets.xcassets */; }; 6D89AF8C277879190075E66F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D89AF8B277879190075E66F /* Preview Assets.xcassets */; }; @@ -83,6 +84,7 @@ 6D738E2B2779736400A4A76E /* SubscriptionHome.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionHome.swift; sourceTree = ""; }; 6D738E2D2779736B00A4A76E /* SettingHome.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingHome.swift; sourceTree = ""; }; 6D738E312779743D00A4A76E /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; + 6D7A39482A46968100CA7F6E /* QRCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeView.swift; sourceTree = ""; }; 6D89AF81277879190075E66F /* iAppStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iAppStore.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6D89AF84277879190075E66F /* iAppStoreApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iAppStoreApp.swift; sourceTree = ""; }; 6D89AF88277879190075E66F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -218,6 +220,7 @@ 6D738E392779839C00A4A76E /* UI */ = { isa = PBXGroup; children = ( + 6D7A39482A46968100CA7F6E /* QRCodeView.swift */, 6DB3B796277EEC7100E8626F /* ImageLoader.swift */, 6C9A423D27A637E60074FD09 /* LoadingView.swift */, 6D0809DD29FB5FA500D12E21 /* SafariView.swift */, @@ -462,6 +465,7 @@ 6D95DC742781E76000EE8B54 /* SearchCellView.swift in Sources */, 6DB3B797277EEC7100E8626F /* ImageLoader.swift in Sources */, 6D738E2C2779736400A4A76E /* SubscriptionHome.swift in Sources */, + 6D7A39492A46968100CA7F6E /* QRCodeView.swift in Sources */, 6DB3B78A277D748400E8626F /* AppRankModel.swift in Sources */, 6D89AF85277879190075E66F /* iAppStoreApp.swift in Sources */, 6D605A17278B15950001C69F /* ShareSheet.swift in Sources */, diff --git a/iAppStore/Shared/UI/QRCodeView.swift b/iAppStore/Shared/UI/QRCodeView.swift new file mode 100644 index 0000000..ef6794a --- /dev/null +++ b/iAppStore/Shared/UI/QRCodeView.swift @@ -0,0 +1,99 @@ +// +// QRCodeView.swift +// iAppStore +// +// Created by iHTCboy on 2023/6/24. +// Copyright © 2023 37 Mobile Games. All rights reserved. +// + +import SwiftUI +import CoreImage.CIFilterBuiltins + +struct QRCodeView: View { + + let title: String + let subTitle: String + let qrCodeContent: String + @Binding var isShowingQRCode: Bool + @State var showShareSheet = false + + var body: some View { + VStack { + + HStack { + Button { + showShareSheet.toggle() + } label: { + Image(systemName: "square.and.arrow.up").imageScale(.large) + } + .frame(width: 60, height: 60, alignment: .center) + .padding([.top, .leading], 8) + .sheet(isPresented: $showShareSheet) { + ShareSheet(items: [generateQRCode(from: qrCodeContent)]) + } + + Spacer() + + Text(title) + .font(.title3) + .multilineTextAlignment(.center) + .padding() + + Spacer() + + Button { + isShowingQRCode = false + } label: { + Image(systemName: "xmark.circle").imageScale(.large) + } + .frame(width: 60, height: 60, alignment: .center) + .padding([.top, .trailing], 8) + } + + Spacer() + + // 在这里生成和显示二维码 + Image(uiImage: generateQRCode(from: qrCodeContent)) + .resizable() + .scaledToFit() + .padding([.leading, .trailing], 50) + .frame(maxWidth: 500) + + Text(subTitle) + .multilineTextAlignment(.center) + .foregroundColor(.accentColor) + + Spacer() + } + } + + private func generateQRCode(from string: String) -> UIImage { + let data = string.data(using: .utf8) + + if let filter = CIFilter(name: "CIQRCodeGenerator") { + filter.setValue(data, forKey: "inputMessage") + filter.setValue("H", forKey: "inputCorrectionLevel") // 设置纠错级别为高 + + if let outputImage = filter.outputImage { + let context = CIContext() + let scale = UIScreen.main.scale // 获取屏幕的缩放比例 + + // 将输出图像的尺寸放大一定倍数,例如放大为原来的10倍 + let transformedImage = outputImage.transformed(by: CGAffineTransform(scaleX: 10, y: 10)) + + if let cgImage = context.createCGImage(transformedImage, from: transformedImage.extent) { + return UIImage(cgImage: cgImage, scale: scale, orientation: .up) + } + } + } + + return UIImage(systemName: "qrcode") ?? UIImage() + } +} + + +struct QRCodeView_Previews: PreviewProvider { + static var previews: some View { + QRCodeView(title: "扫一扫下载", subTitle: "‎App Store 上的“凡人修仙传:人界篇-正版授权”", qrCodeContent: "https://apps.apple.com/cn/app/69437212", isShowingQRCode: .constant(false)) + } +} diff --git a/iAppStore/components/rankLists/AppDetailView.swift b/iAppStore/components/rankLists/AppDetailView.swift index 066918d..afa9730 100644 --- a/iAppStore/components/rankLists/AppDetailView.swift +++ b/iAppStore/components/rankLists/AppDetailView.swift @@ -15,6 +15,7 @@ struct AppDetailView: View { var item: AppRank? @StateObject private var appModel = AppDetailModel() + @State private var isShowingQRCode = false var body: some View { @@ -25,8 +26,17 @@ struct AppDetailView: View { .navigationBarBackButtonHidden(false) .navigationBarItems(trailing: Link(destination: URL(string: appModel.app?.trackViewUrl ?? item?.id.label ?? "https://apple.com")!) { - Image(systemName: "paperplane").font(.subheadline) + Image(systemName: "icloud.and.arrow.down").font(.subheadline) + Button(action: { + isShowingQRCode = true + }) { + Image(systemName: "qrcode") + .font(.subheadline) + } }) + .sheet(isPresented: $isShowingQRCode) { + QRCodeView(title: "扫一扫下载", subTitle: "App Store 上的“\(item?.imName.label ?? "")”", qrCodeContent: item?.id.label ?? "error", isShowingQRCode: $isShowingQRCode) + } .onAppear { if appModel.app == nil { appModel.searchAppData(appId, nil, regionName)