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

View File

@ -1,13 +1,119 @@
import SwiftUI import SwiftUI
import EpcQrCode import EpcQrCode
import ZXingObjC
struct ContentView: View { 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 { 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 { struct ContentView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
ContentView() 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";