Reputation: 481
I am generating barcode from a string and then try to save this image to iPhone photos library. Here is my code:
@IBOutlet weak var uuidLabel: UILabel!
@IBOutlet weak var barcodeDisplay: UIImageView!
@IBAction func generateBarcode(_ sender: Any) {
barcodeDisplay.image = generateBarcodeFromString(string: uuidLabel.text!)
UIImageWriteToSavedPhotosAlbum(barcodeDisplay.image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}
@objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if let error = error {
let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Saved!", message: "Your image has been saved to your photos.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}
func generateBarcodeFromString(string:String)->UIImage? {
let data = string.data(using: String.Encoding.ascii)
if let filter = CIFilter(name: "CICode128BarcodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 1, y: 1)
if let output = filter.outputImage?.transformed(by: transform) {
return UIImage(ciImage: output)
}
}
return nil
}
When i run this app, it's generate the barcode and it's displayed on the view controller. When i try to save this image to iPhone photos library, the selector says,"Your image has been saved to your photos." but image is not saved into iPhone photos library.
After that, when i try to convert this image into NSData by following:
let data = UIImagePNGRepresentation(barcodeDisplay.image!) as NSData?
It's return nil. What's the problem behind this ?
Upvotes: 4
Views: 3969
Reputation: 3288
Swift version: 5.2
The problem is QRCode is CIImage so we need to convert it to UIImage in-order to save to Photos Album
QRCodeGenerator.swift
import UIKit
final class QrCodeGenerator {
func generateQRCode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
if let filter = CIFilter(name: "CIQRCodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
let transform = CGAffineTransform(scaleX: 5, y: 5) // Scale according to imgView
if let output = filter.outputImage?.transformed(by: transform) {
return convert(output)
}
}
return nil
}
private func convert(_ cmage:CIImage) -> UIImage? {
let context:CIContext = CIContext(options: nil)
guard let cgImage:CGImage = context.createCGImage(cmage, from: cmage.extent) else { return nil }
let image:UIImage = UIImage(cgImage: cgImage)
return image
}
}
ImageSaver.swift
import UIKit
final class ImageSaver: NSObject {
func writeToPhotoAlbum(image: UIImage) {
UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveError), nil)
}
@objc func saveError(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
print("error: \(error.localizedDescription)")
} else {
print("Save completed!")
}
}
}
QrCodeViewController
import UIKit
class QrCodeViewController: UIViewController {
@IBOutlet weak var qrCodeImageView: UIImageView!
private let qrCodeGenerator = QrCodeGenerator()
private let imageSaver = ImageSaver()
init() {
super.init(nibName: "QrCodeViewController", bundle: nil)
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save Photo", style: .plain, target: self, action: #selector(addTapped))
guard let image = qrCodeGenerator.generateQRCode(from: "mock") else { return }
qrCodeImageView.image = image
}
@objc func addTapped() {
guard let inputImage = QrCodeGenerator().generateQRCode(from: "mock") else { assertionFailure("null image"); return }
imageSaver.writeToPhotoAlbum(image: inputImage)
}
}
For letting the app to be able to write (add) photos into the device photos library we have to add the NSPhotoLibraryAddUsageDescription
into the application's plist file:
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Our application needs permission to write photos...</string>
Upvotes: 13