How to make qr code generator with multiple info in swiftui - swiftui

I Have created a qr code generator with swiftui. i used uiimage to create qr code with datepicker, i want to create with multipile info with qr code generator, I want to add a integer as a picker to combine with the datepicker, what do i need to add for the function to make multiple info.
Here is my orginial code.
import Foundation
import SwiftUI
import CoreImage.CIFilterBuiltins
struct ContentView: View {
#State var start = Date()
var body: some View {
VStack {
DatePicker("", selection: $start, displayedComponents: [.hourAndMinute])
.datePickerStyle(.wheel)
Generate(start: $start)
}
}
}
struct GenerateQRCode: View {
#Binding var start: Date
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
var dateFormatter: DateFormatter {
let df = DateFormatter()
df.dateFormat = "HH:mm"
return df
}
var body: some View {
NavigationView{
Image(uiImage: imageGenerate(start))
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}.navigationBarBackButtonHidden(true)
}
func imageGenerate(_ start: Date)-> UIImage {
let str = dateFormatter.string(from: start)
let data = str.data(using: .utf8)
filter.setValue(data, forKey: "inputMessage")
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent){
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: "xmark") ?? UIImage()
}
}

Related

How to use picker as Int in qr code generator with swiftui

I am new to swift and i am using swiftui to create a qr code generator. I want to use a picker to select number and it shows in the qr code, when i finished the picker and i was trying to add function as qr code generator and the integer needs to be convert to string, so it can be used in the function. How can i make the function work with Integer?
Here is my code which i tried:
I used age as Integer with picker
import Foundation
import SwiftUI
import CoreImage.CIFilterBuiltins
struct QRCode: View {
#State private var selectedAge = 1
let age = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
#State var navigated = false
var body: some View {
NavigationView{
VStack{
Picker(“Select Age”, selection: $selectedAge) {
ForEach(age,id:\.self) {
ages in Text(“\(ages)”) }
}
}
}
}
}
//Below is the other view with the function
import Foundation
import SwiftUI
import CoreImage.CIFilterBuiltins
struct Generate: View {
#Binding var Ages: Int
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
var body: some View {
NavigationView{
Image(uiImage: GenerateQRCode(old: old))
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}
}
func GenerateQRCode(old: Int)-> UIImage {
let com = Ages
let con = com.data(using: .uft8)
filter.setValue(con, forKey: “inputMessage”)
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent) {
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: “xmark”) ?? UIImage()
}
}
Try this simple approach to "...make the function work with Integer".
Note the name change ages/age for clarity.
struct ContentView: View {
var body: some View {
QRCode()
}
}
struct QRCode: View {
#State private var selectedAge = 1
let ages = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100] // <-- ages
#State var navigated = false
var body: some View {
NavigationView {
VStack {
Picker("Select Age", selection: $selectedAge) {
ForEach(ages, id: \.self) { age in
Text("\(age)")
}
}.pickerStyle(.wheel) // <-- for testing
Generate(age: $selectedAge)
}
}
}
}
struct Generate: View {
#Binding var age: Int
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
var body: some View {
Image(uiImage: GenerateQRCode(old: age))
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}
func GenerateQRCode(old: Int)-> UIImage {
let data = String(old).data(using: .utf8) // <-- here
filter.setValue(data, forKey: "inputMessage") // <-- here
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent) {
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: "xmark") ?? UIImage()
}
}

how to convert muliple int number to string in qr code generator with swiftui

I have made a qr code generator with date and I want to add another picker for hours, and I have tried to conver Int to String, there isn't any problem, when I tried to convert multiple Int to string and it doesn't work and also i want to change the Int format to something like this 12 02:11, first is integer space and time. how could I do that?
My Code:
struct GenerateQRCode: View {
#Binding var time: Date
#Binding var hours: Int
let hour = ["3","6","9","12"]
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
var dateFormatter: DateFormatter {
let df = DateFormatter()
df.dateFormat = "HH:mm"
return df
}
var body: some View {
NavigationView{
Image(uiImage: imageGenerate(times:time, hours: hours))
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}.navigationBarBackButtonHidden(true)
}
func imageGenerate(hours: Int, times: Date)-> UIImage { //<--here how to add integer parameter?
let str = dateFormatter.string(from: start)
let ts = String(hours)
let com = ts + str
let data = com.data(using: .utf8)
filter.setValue(data, forKey: "inputMessage") //
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent){
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: "xmark") ?? UIImage()
}
}
Preview:
import Foundation
import SwiftUI
import CoreImage.CIFilterBuiltins
struct DatePicker: View {
#State var Time = Date()
#State var sHours = Int()
#State var navigated = false
let hour = ["3", "6", "9", "12"]
var body: some View {
NavigationView{
VStack{
Section{
Text("Please Select Time")
DatePicker("", selection: $startTime, displayedComponents: [.hourAndMinute])
.datePickerStyle(.wheel)
}
Section{
Text("Please Select Minutes")
Picker(selection: $sMinutes, label: Text("Please Select Minutes"))
{
ForEach(0 ..< minutes.count) {
index in Text(self.minutes[index]).tag(index)
}
}
}
Section
{
NavigationLink(destination: GenerateQRCode(start: $Time, minutes: $sHours), isActive: self.$navigated)
{
Text("Complete")
}
}.padding(100)
}.navigationBarTitle("Visitor")
}
}
}
struct DatePicker_Previews: PreviewProvider {
static var previews: some View {
DatePicker()
}
}
Output: "012:30"
what i expected output, should be like this: "3 12:30" first should be hours and then time. i don't know why it only shows 0 if my picker turns to 3. How can i solve it out?

How to set a date picker for QR Code to select in XCode SwiftUI

I have created a qr code generator and i want to do time set in the qr code, so i used a date picker for time and it only shows hours and minutes. i want to use the date picker to show the result in qr code like this (12 34).
I have tried with the string but i don't know to do with the datetime
Code for string(Is working in XCode)
import Foundation
import SwiftUI
import CoreImage.CIFilterBuiltins
struct Generate: View {
#State var start = String
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
var body: some View {
Image(uiImage: imageGenerate(start))
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}
func imageGenerate(_ start: Int?)-> UIImage {
let data = Data(start)
filter.setValue(data, forKey: "inputMessage")
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent){
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: "xmark") ?? UIImage()
}
}
Code for datetime(not working)
import Foundation
import SwiftUI
import CoreImage.CIFilterBuiltins
struct Generate: View {
#State var start = Timer()
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
var body: some View {
Image(uiImage: imageGenerate(start))
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}
func imageGenerate(_ start: Timer)-> UIImage {
let data = Data(start.[not utf8, don't know what should it be?])
filter.setValue(data, forKey: "inputMessage")
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent){
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: "xmark") ?? UIImage()
}
}
Update Part
code for date picker
#State private var startTime = Date()
var body: some View {
Form{
Section {
VStack{
Text("Please Select Start Time")
.padding(.bottom, 10)
.font(.system(size:20))
.bold()
DatePicker("", selection: $startTime, displayedComponents: .hourAndMinute)
.labelsHidden()
.datePickerStyle(.wheel)
}
VStack{
Picker(selection: $sMinutes, label: Text("Please Select Minutes"))
{
ForEach(0 ..< minutes.count) {
index in Text(self.minutes[index]).tag(index)
}
}
}
}
Button("Complete"){
self.showflag.toggle()
}
.font(.system(size:20))
.bold()
.foregroundColor(Color.blue)
.frame(maxWidth: .infinity)
}
Try this example code to show a qr code using a date picker.
The code uses a DatePicker to select the hours and minutes.
Then a DateFormatter to convert those into a string for the qr code generator.
struct ContentView: View {
#State var start = Date()
var body: some View {
VStack {
DatePicker("", selection: $start, displayedComponents: [.hourAndMinute])
.datePickerStyle(.wheel)
Generate(start: $start)
}
}
}
struct Generate: View {
#Binding var start: Date // <-- here
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
var dateFormatter: DateFormatter { // <-- here
let df = DateFormatter()
df.dateFormat = "HH:mm"
return df
}
var body: some View {
Image(uiImage: imageGenerate(start))
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}
func imageGenerate(_ start: Date)-> UIImage {
let str = dateFormatter.string(from: start) // <-- here
let data = str.data(using: .utf8) // <-- here
filter.setValue(data, forKey: "inputMessage")
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent){
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: "xmark") ?? UIImage()
}
}
EDIT-1:
to put the qr code generation into a function, try this:
struct ContentView: View {
#State var start = Date()
#State var img: UIImage = UIImage() // <-- here
var body: some View {
VStack {
DatePicker("", selection: $start, displayedComponents: [.hourAndMinute])
.datePickerStyle(.wheel)
Button("Show QR code", action: {
img = imageGenerate(start) // <-- here
})
Image(uiImage: img)
.interpolation(.none)
.resizable()
.frame(width: 150, height: 150, alignment: .center)
}
}
func imageGenerate(_ start: Date) -> UIImage {
let filter = CIFilter.qrCodeGenerator()
let cont = CIContext()
let dateFormatter = DateFormatter() // <-- here
dateFormatter.dateFormat = "HH:mm" // <-- here
let str = dateFormatter.string(from: start) // <-- here
let data = str.data(using: .utf8) // <-- here
filter.setValue(data, forKey: "inputMessage")
if let qr = filter.outputImage {
if let qrImage = cont.createCGImage(qr, from: qr.extent){
return UIImage(cgImage: qrImage)
}
}
return UIImage(systemName: "xmark") ?? UIImage()
}
}

ImagePicker in array

I am trying to make a dynamic image selection with the help of an array, but the problem I have is that I select the first position and the photo loads in the first position, but if I select another position, the image always loads in the first position.
I am occupying a single .sheet within the foreach, it is worth mentioning that what I want to achieve is a number of images, not a fixed size
code:
import SwiftUI
struct Research {
var id: Int
var name: String
var date: String
var aux: Int
var imagen1: UIImage
var imagen2: UIImage
var imagen3: UIImage
var imagen4: UIImage
var imagen5: UIImage
var imagen6: UIImage
}
struct ContentView: View {
#State var dataResearch : [Research] = []
#State var aux: Int = 0
#State var showPicker: Bool = false // I imagine that this variable must be unique per element
#State var sourceType: UIImagePickerController.SourceType = .photoLibrary
var body: some View {
VStack{
ForEach($dataResearch, id: \.aux) { $i in
VStack{
Image(uiImage: i.imagen1)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.edgesIgnoringSafeArea(.all)
.onTapGesture(){
showPicker = true
}
Image(uiImage: i.imagen2)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.edgesIgnoringSafeArea(.all)
.onTapGesture(){
showPicker = true
}
}
.sheet(isPresented: $showPicker) {
ImagePicker(sourceType: sourceType, selectedImage: $i.imagen1)
.ignoresSafeArea()
}
}
}
.onAppear(){
getRequest()
}
}
func getRequest(){
let image1: UIImage = UIImage(named: "default_image")!
let image2: UIImage = UIImage(named: "default_image")!
let image3: UIImage = UIImage(named: "default_image")!
let image4: UIImage = UIImage(named: "default_image")!
let image5: UIImage = UIImage(named: "default_image")!
let image6: UIImage = UIImage(named: "default_image")!
let row = Research(id: 0, name: "", date: "", aux: aux, imagen1: image1, imagen2: image2, imagen3: image3, imagen4: image4, imagen5: image5, imagen6: image6)
dataResearch.append(row)
aux = aux + 1
}
}
IMAGE PICKER
import UIKit
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
var sourceType: UIImagePickerController.SourceType = .photoLibrary
#Binding var selectedImage: UIImage
//#Binding var selectedImage: SelectImage
#Environment(\.presentationMode) private var presentationMode
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let imagePicker = UIImagePickerController()
imagePicker.allowsEditing = false
imagePicker.sourceType = sourceType
imagePicker.delegate = context.coordinator
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
print("aqui vemos-- ", parent)
print("aqui vemos-- ", parent.selectedImage)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
parent.selectedImage = image
//var row1 = SelectImage(id: 0, uiImage: image ,name:"")
//parent.selectedImage.uiImage = image
}
parent.presentationMode.wrappedValue.dismiss()
}
}
}
This was a little bit complicated because of the structure of Research and the fact that it has so many image fields (that aren't in an array). I'd suggest that it's possible that your model could use a refactor, but since I don't have any information about what the end goal is, I don't know exactly what that would involve yet.
With your current code, you can set a selected item and then set an additional variable that determines which imagen(X) property it should be bound to:
struct ContentView: View {
#State private var dataResearch : [Research] = []
#State private var aux: Int = 0
#State private var pickerItem : Binding<Research>? // the item from ForEach
private enum SelectedImage {
case imagen1, imagen2
}
#State private var selectedImage : SelectedImage? //which image gets selected
var body: some View {
VStack{
ForEach($dataResearch, id: \.aux) { $i in
VStack{
Image(uiImage: i.imagen1)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.edgesIgnoringSafeArea(.all)
.onTapGesture(){
pickerItem = $i
selectedImage = .imagen1
}
Image(uiImage: i.imagen2)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.edgesIgnoringSafeArea(.all)
.onTapGesture(){
pickerItem = $i
selectedImage = .imagen2
}
}
}
.sheet(item: $pickerItem) { [selectedImage] item in
VStack {
if let selectedImage = selectedImage {
switch selectedImage {
case .imagen1:
ImagePicker(selectedImage: item.imagen1)
case .imagen2:
ImagePicker(selectedImage: item.imagen2)
}
}
}
.ignoresSafeArea()
}
}
.onAppear(){
getRequest()
}
}
func getRequest(){
let image1: UIImage = UIImage(systemName: "pencil")!
let image2: UIImage = UIImage(systemName: "pencil")!
let image3: UIImage = UIImage(systemName: "pencil")!
let image4: UIImage = UIImage(systemName: "pencil")!
let image5: UIImage = UIImage(systemName: "pencil")!
let image6: UIImage = UIImage(systemName: "pencil")!
let row = Research(id: 0, name: "", date: "", aux: aux, imagen1: image1, imagen2: image2, imagen3: image3, imagen4: image4, imagen5: image5, imagen6: image6)
dataResearch.append(row)
aux = aux + 1
}
}

State Change only Updates Some Views

The attached program doesn't change the QR code in the QRView when the user changes the url in the TextField, yet the Text view below the QR code does update. What am I missing?
I tried this without the text field and also added/substituted a MapView to see if a different representable view would fire. The MapView didn't fire either and removing the Text view didn't change anything.
import SwiftUI
import CoreImage.CIFilterBuiltins
struct ContentView: View
{
#State var url = "https://www.nytimes.com"
var body: some View
{
VStack
{
Spacer()
QRView(string: "URL:\(url))")
Text(url)
Spacer()
HStack
{
Text("URL")
TextField("URL",text: $url)
}
.padding()
}
}
}
struct QRView: View
{
#State var string:String
var body: some View
{
Image(uiImage: generateQRCode(from: string))
.interpolation(.none)
.resizable()
//.aspectRatio(contentMode: .fit)
.frame(width: 200, height: 200)
}
}
//MARK:- QRCode
func generateQRCode(from string: String) -> UIImage
{
let context = CIContext()
let filter = CIFilter.qrCodeGenerator()
let data = Data(string.utf8)
filter.setValue(data, forKey: "inputMessage")
if let outputImage = filter.outputImage {
if let cgimg = context.createCGImage(outputImage, from: outputImage.extent)
{
return UIImage(cgImage: cgimg)
}
}
return UIImage(systemName: "xmark.circle") ?? UIImage()
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
You don't need state wrapper in QRView, it preserves initial value and prevents external update of property, so here is a fix:
struct QRView: View
{
var string: String // << here !!
// .. other code
}