Implemented generating EPC QR code on iOS

This commit is contained in:
dankito 2020-11-15 02:29:10 +01:00
parent 0ed6c52ead
commit e421cdb176
6 changed files with 215 additions and 2 deletions

View File

@ -3,10 +3,13 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
368A7CDD2560A48900252D96 /* LabelledTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 368A7CDC2560A48900252D96 /* LabelledTextField.swift */; };
368A7CEC2560A93500252D96 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 368A7CEE2560A93500252D96 /* Localizable.strings */; };
368A7CFA2560B2A000252D96 /* ZXingObjC in Frameworks */ = {isa = PBXBuildFile; productRef = 368A7CF92560B2A000252D96 /* ZXingObjC */; };
7555FF7F242A565900829871 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF7E242A565900829871 /* AppDelegate.swift */; };
7555FF81242A565900829871 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF80242A565900829871 /* SceneDelegate.swift */; };
7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; };
@ -51,6 +54,9 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
368A7CDC2560A48900252D96 /* LabelledTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelledTextField.swift; sourceTree = "<group>"; };
368A7CED2560A93500252D96 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
368A7CF12560A94C00252D96 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
7555FF7B242A565900829871 /* EpcQrCodeiOSApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EpcQrCodeiOSApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF7E242A565900829871 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7555FF80242A565900829871 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@ -74,6 +80,7 @@
buildActionMask = 2147483647;
files = (
7555FFB2242A642300829871 /* EpcQrCode.framework in Frameworks */,
368A7CFA2560B2A000252D96 /* ZXingObjC in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -125,6 +132,8 @@
7555FF89242A565B00829871 /* LaunchScreen.storyboard */,
7555FF8C242A565B00829871 /* Info.plist */,
7555FF86242A565B00829871 /* Preview Content */,
368A7CDC2560A48900252D96 /* LabelledTextField.swift */,
368A7CEE2560A93500252D96 /* Localizable.strings */,
);
path = EpcQrCodeiOSApp;
sourceTree = "<group>";
@ -181,6 +190,9 @@
dependencies = (
);
name = EpcQrCodeiOSApp;
packageProductDependencies = (
368A7CF92560B2A000252D96 /* ZXingObjC */,
);
productName = EpcQrCodeiOSApp;
productReference = 7555FF7B242A565900829871 /* EpcQrCodeiOSApp.app */;
productType = "com.apple.product-type.application";
@ -251,8 +263,12 @@
knownRegions = (
en,
Base,
de,
);
mainGroup = 7555FF72242A565900829871;
packageReferences = (
368A7CF82560B2A000252D96 /* XCRemoteSwiftPackageReference "zxingify-objc" */,
);
productRefGroup = 7555FF7C242A565900829871 /* Products */;
projectDirPath = "";
projectRoot = "";
@ -270,6 +286,7 @@
buildActionMask = 2147483647;
files = (
7555FF8B242A565B00829871 /* LaunchScreen.storyboard in Resources */,
368A7CEC2560A93500252D96 /* Localizable.strings in Resources */,
7555FF88242A565B00829871 /* Preview Assets.xcassets in Resources */,
7555FF85242A565B00829871 /* Assets.xcassets in Resources */,
);
@ -316,6 +333,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
368A7CDD2560A48900252D96 /* LabelledTextField.swift in Sources */,
7555FF7F242A565900829871 /* AppDelegate.swift in Sources */,
7555FF81242A565900829871 /* SceneDelegate.swift in Sources */,
7555FF83242A565900829871 /* ContentView.swift in Sources */,
@ -354,6 +372,15 @@
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
368A7CEE2560A93500252D96 /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
368A7CED2560A93500252D96 /* en */,
368A7CF12560A94C00252D96 /* de */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
7555FF89242A565B00829871 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
@ -369,6 +396,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -429,6 +457,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@ -643,6 +672,25 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
368A7CF82560B2A000252D96 /* XCRemoteSwiftPackageReference "zxingify-objc" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/zxingify/zxingify-objc";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 3.6.7;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
368A7CF92560B2A000252D96 /* ZXingObjC */ = {
isa = XCSwiftPackageProductDependency;
package = 368A7CF82560B2A000252D96 /* XCRemoteSwiftPackageReference "zxingify-objc" */;
productName = ZXingObjC;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 7555FF73242A565900829871 /* Project object */;
}

View File

@ -1,13 +1,119 @@
import SwiftUI
import EpcQrCode
import ZXingObjC
struct ContentView: View {
static private let ImageWidth: CGFloat = 350
static private let ImageHeight = Self.ImageWidth
@State private var receiver: String = ""
@State private var iban: String = ""
@State private var bic: String = ""
@State private var amount: String = ""
@State private var reference: String = ""
@State private var generatedQrCode: UIImage? = nil
var body: some View {
Text(MppTest().showMessage())
VStack {
Form {
Section {
LabelledTextField("Receiver", $receiver)
}
Section {
LabelledTextField("IBAN", $iban)
LabelledTextField("BIC", $bic)
}
Section {
HStack {
Text("Amount")
Spacer()
TextField("", text: $amount)
.multilineTextAlignment(.trailing)
.keyboardType(.numberPad)
}
VStack(alignment: .leading) {
Text("Reference")
TextField("", text: $reference)
}
}
Section {
Button(action: self.generateQRCode) {
HStack {
Spacer()
Text("Generate")
Spacer()
}
}
}
if let generatedQrCode = generatedQrCode {
Section {
VStack(alignment: .center) {
Image(uiImage: generatedQrCode)
.resizable()
}
}
}
}
}
}
private func generateQRCode() {
let creator = EpcQrCodeCreator()
let param = CreatorParam(receiverName: receiver, iban: iban, bic: bic, amount: map(amount), reference: reference, noteToUser: nil, encoding: .utf8)
let qrCodeContent = creator.generateAsString(param: param)
self.generatedQrCode = generateQRCode(qrCodeContent)
}
private func map(_ amount: String) -> KotlinDouble? {
if let double = Double(amount.replacingOccurrences(of: ",", with: ".")) {
return KotlinDouble(double: double)
}
return nil
}
private func generateQRCode(_ informationToEncode: String) -> UIImage? {
let writer = ZXQRCodeWriter()
let hints = ZXEncodeHints()
hints.errorCorrectionLevel = ZXQRCodeErrorCorrectionLevel.errorCorrectionLevelM()
if let result = try? writer.encode(informationToEncode, format: kBarcodeFormatQRCode, width: Int32(Self.ImageWidth), height: Int32(Self.ImageHeight), hints: hints) {
if let cgImage = ZXImage(matrix: result)?.cgimage {
return UIImage(cgImage: cgImage)
}
}
return nil
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()

View File

@ -0,0 +1,42 @@
import SwiftUI
struct LabelledTextField: View {
private let label: LocalizedStringKey
private var value: Binding<String>
private let placeholder: LocalizedStringKey
init(_ label: LocalizedStringKey, _ value: Binding<String>, _ placeholder: LocalizedStringKey = "") {
self.label = label
self.value = value
self.placeholder = placeholder
}
var body: some View {
HStack {
Text(label)
Spacer()
TextField(placeholder, text: value)
.multilineTextAlignment(.trailing)
}
}
}
struct LabelledTextField_Previews: PreviewProvider {
static var previews: some View {
LabelledTextField("Label", .constant("Value"))
}
}

View File

@ -0,0 +1,8 @@
"Receiver" = "Empfänger";
"IBAN" = "IBAN";
"BIC" = "BIC";
"Amount" = "Betrag";
"Reference" = "Verwendungszweck";
"Generate" = "Erzeugen";

View File

@ -0,0 +1,8 @@
"Receiver" = "Receiver";
"IBAN" = "IBAN";
"BIC" = "BIC";
"Amount" = "Amount";
"Reference" = "Reference";
"Generate" = "Generate";