CoreImage를 통해 qrcode를 uiImage로 생성할 수 있다.
import CoreImage.CIFilterBuiltins
아래처럼 내용을 데이터화해서 이미지로 변환하여 나타낼 수 있다.
func generateQRCode(from string: String) -> UIImage {
filter.message = Data(string.utf8)
if let outputImage = filter.outputImage {
if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
return UIImage(cgImage: cgImage)
}
}
return UIImage(systemName: "xmark.circle") ?? UIImage()
}
💡 qr code 사진이 확장되면서 보간법이 적용되는데, .interpolation()으로 보간법 해제하면 뚜렷하게 보인다.
https://github.com/twostraws/CodeScanner 이 사이트의 package를 활용한다.
우선 qr code scan 버튼을 누르면 CodeScannerView가 활성화되게 설정한다. simulatedData는 qr code를 스캔할 수 없는 경우에 창을 클릭하는 것만으로도 생성될 수 있게 만든 임의 데이터다.
.sheet(isPresented: $isShowingScanner) {
CodeScannerView(codeTypes: [.qr], simulatedData: "Paul Hudson\npaul@hackingwithswift.com", completion: handleScan)
}
그리고 qr code를 스캔하면 scanner를 닫고, 데이터 읽기에 성공했다면 읽은 값을 swiftData에 Prospect
로 저장한다.
func handleScan(result: Result<ScanResult, ScanError>) {
isShowingScanner = false
switch result {
case .success(let result):
let details = result.string.components(separatedBy: "\n")
guard details.count == 2 else { return }
let person = Prospect(name: details[0], emailAddress: details[1], isContacted: false)
modelContext.insert(person)
case .failure(let error):
print("Scanning failed: \(error.localizedDescription)")
}
}
이젠 각 열의 액션을 설정한다. 만약 contacted 혹은 unContancted이더라도 다른 영역으로 변경할 수 있는 액션을 설정했다.
.swipeActions {
if prospect.isContacted {
Button("Mark Uncontacted", systemImage: "person.crop.circle.badge.xmark") {
prospect.isContacted.toggle()
}
.tint(.blue)
} else {
Button("Mark Contacted", systemImage: "person.crop.circle.fill.badge.checkmark") {
prospect.isContacted.toggle()
}
.tint(.green)
}
}
그리고 삭제 옵션을 추가하rh, EditButton()을 추가하고, 여러 열이 선택되었을 때 한꺼번에 삭제할 수 있도록 설정했다.
.swipeActions {
// ...
Button("Delete", systemImage: "trash", role: .destructive) {
modelContext.delete(prospect)
}
}
.tag(prospect)
}
.navigationTitle(title)
.toolbar {
// ...
if selectedProspects.isEmpty == false {
ToolbarItem(placement: .bottomBar) {
Button("Delete Selected", action: deleteProspects)
}
}
}
func deleteProspects() {
for prospect in selectedProspects {
modelContext.delete(prospect)
}
}
최종 결과물