I am using Swift 3 and have been following apples https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson4.html have created 20 different UIImage views on 20 different UIViewcontroller
They are called photoImageView1 photoImageView2 etc. currently you are able to click on each generic image and input your own image.
I would like the user to be able to input their image but also save it and when they re-open that same viewcontroller the image they inputed is there.
I have looked at many different methods however have been unsuccessful i have attempted following this question Save images in NSUserDefaults? and was once again unsuccessful. Any help would be much appreciated, Thanks.
i ended up using this method it may not be the best but its easy and it works.
import UIKit
class timetable: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
#IBOutlet var imageviewtimetable: UIImageView!
#IBAction func saveMyImage(_ sender: UIBarButtonItem) {
let myTimeTableImage = imageviewtimetable.image
let theImageData:NSData = UIImagePNGRepresentation(myTimeTableImage!)! as NSData
UserDefaults.standard.set(theImageData, forKey: "mySavedImage")
let data = UserDefaults.standard.object(forKey: "mySavedImage")
imageviewtimetable.image = UIImage(data: data as! Data)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let data = UserDefaults.standard.object(forKey: "mySavedImage")
imageviewtimetable.image = UIImage(data: data as! Data)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func selectImageFromPhotoLibrary(_ sender: Any) {
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
present(imagePickerController, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController){
dismiss(animated: true, completion:nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
imageviewtimetable.image = selectedImage
dismiss(animated: true,completion:nil)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
You can store the image name in a database, iCloud, a plist or even Userdefaults. To save an image to disk, but not the photo library, use:
import PlaygroundSupport
import UIKit
func save(image: UIImage, name: String) -> Bool {
guard var path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first,
let imageData = UIImagePNGRepresentation(image) else {
return false
}
path = path.appendingPathComponent(name)
do {
try imageData.write(to: path)
} catch {
return false
}
return true
}
func loadImage(name: String) -> UIImage? {
guard var path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return nil
}
path = path.appendingPathComponent(name)
return UIImage(contentsOfFile: path.relativePath)
}
let image = UIImage(named: "test.png")!
save(image: image, name: "test2.png")
let loadedImage = loadImage(name: "test2.png")
PlaygroundPage.current.liveView = UIImageView(image: loadedImage)
EDIT: I changed the source code to a full playground so you can copy and paste it into a playground and run it. The only thing you need to do is drag a file named test.png into the Resources folder.
Related
Bear with me as I’m a novice programmer. I'm building out a project where a user goes into their photo library, selects a photo and displays the image's name in a tableView. They can select that image in the tableView and it will then load a full size of that image.
Problem: When I click the row item in the tableView to load the image, the new view controller is just a white screen and not the image previously selected.
Here is the view controller that displays the image:
class DetailViewController: UIViewController {
var selectedImage: String?
#IBOutlet var image: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
if let imageToLoad = selectedImage {
image.image = UIImage(named: imageToLoad)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.hidesBarsOnTap = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
}
}
Here is where the new view is loaded:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let dvc = storyboard?.instantiateViewController(identifier: "Detail") as? DetailViewController {
dvc.selectedImage = imageArray[indexPath.row].image
navigationController?.pushViewController(dvc, animated: true)
}
}
The photos are picked using a navBar button item and loaded into the imageArray of type Photo here:
#objc func loadImage() {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
let imageName = UUID().uuidString
let imagePath = getDocumentsDirectory().appendingPathComponent(imageName)
// Convert to JPEG data
if let jpegData = image.jpegData(compressionQuality: 0.8) {
// We have a valid photo
try? jpegData.write(to: imagePath)
}
let photo = Photo(name: "Unkown", image: imageName)
imageArray.append(photo)
tableView.reloadData()
dismiss(animated: true)
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths[0]
}
And finally here is the Photo class that holds the photo data
import UIKit
class Photo: NSObject {
var name: String
var image: String
init(name: String, image: String) {
self.name = name
self.image = image
}
}
I can see the image name string populated in the debugger when the new view controller is loading, but for some reason it’s just a white screen displayed.
New Detail View Controller
#IBOutlet var image: UIImageView!
var url = URL(string: "")
override func viewDidLoad() {
super.viewDidLoad()
if let data = try? Data(contentsOf: url!) {
image.image = UIImage(data: data)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.hidesBarsOnTap = true
}
override func viewWillDisappear(_ animated: Bool) {
//super.viewWillAppear(animated)
}
New didSelectRowAt method
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let dvc = storyboard?.instantiateViewController(identifier: "Detail") as? DetailViewController {
let imageName = UUID().uuidString
let urlString = getDocumentsDirectory().appendingPathComponent(imageName)
dvc.url = urlString
navigationController?.pushViewController(dvc, animated: true)
}
}
The problem is this line:
image.image = UIImage(named: imageToLoad)
You won’t find the image that way. That method looks in the app bundle. That’s not where the image is.
You need to fetch the image from where you put it, in the Documents directory, using essentially the reverse of the way you saved it. Get the Documents directory url, form the image file url, and load the image data from that url using the Data struct and then create the UIImage from the data.
So once you have calculated the url for this image, exactly the way you calculated it to save it in the first place, you will say
if let data = try? Data(contentsOf: url) {
image.image = UIImage(data: data)
}
At main.storyboard I have UIImageView and button. I want to save my image witch I took via camera to file system. But when I loading my app again, this image disappeared. Tell me please what I done wrong?
This is my code:
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBAction func useCamera(_ sender: UIButton) {
let picker = UIImagePickerController()
picker.sourceType = .camera
self.present(picker, animated: true, completion: nil)
picker.delegate = self
}
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
picker.dismiss(animated: true, completion: nil)
if imageView.image == UIImage(named: "example.jpg") {
if let data = UIImageJPEGRepresentation(imageView.image!, 0.8) {
let filename = getDocumentsDirectory().appendingPathComponent("copy.png")
try? data.write(to: filename)
}
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
}
what exactly you are doing wrong, I don't know. I haven't tested your code. This is a saving routine that does work. It is tested on an app that is currently in the app store.
func save(image: UIImage, with fileName: String, and imageName: String?) {
let documentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first
let imageStore = documentsDirectory?.appendingPathComponent(fileName)
let imageData = UIImagePNGRepresentation(image)
do {
try imageData?.write(to: imageStore!)
} catch {
print("Couldn't write the image to disk.")
}
}
I am trying to create an iOS app using swift that will let the user either take a photo or choose an image from their gallery, and convert it to a pdf file that they are able to save to their phone. My code currently works to open either the camera or the gallery and choose an image, but I'm unable to convert it to pdf.
Any tips would be really appreciated, thanks!
CameraViewController class
import UIKit
class CameraViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate
{
#IBOutlet weak var myImg: UIImageView!
#IBAction func takePhoto(_ sender: AnyObject) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
imagePicker.allowsEditing = false
self.present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
myImg.contentMode = .scaleToFill
myImg.image = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
#IBAction func savePhoto(_ sender: AnyObject) {
let imageData = UIImagePNGRepresentation(myImg.image!)
let compressedImage = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(compressedImage!, nil, nil, nil)
let alert = UIAlertController(title: "Saved", message: "Your image has been saved", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil)
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
GalleryViewController class
import UIKit
class GalleryViewController: UIViewController {
#IBOutlet weak var myImg: UIImageView!
#IBAction func pickPhoto(_ sender: Any) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
imagePicker.sourceType = UIImagePickerControllerSourceType.photoLibrary
imagePicker.allowsEditing = true
self.present(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
myImg.contentMode = .scaleToFill
myImg.image = pickedImage
}
picker.dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Answers Updated:
Since Apple introduced PDFKit to iOS 11.0, you can use the code below to convert uiimage to pdf, I only tried the osx below, but it should work the same way on iOS.
// Create an empty PDF document
let pdfDocument = PDFDocument()
// Load or create your UIImage
let image = UIImage(....)
// Create a PDF page instance from your image
let pdfPage = PDFPage(image: image!)
// Insert the PDF page into your document
pdfDocument.insert(pdfPage!, at: 0)
// Get the raw data of your PDF document
let data = pdfDocument.dataRepresentation()
// The url to save the data to
let url = URL(fileURLWithPath: "/Path/To/Your/PDF")
// Save the data to the url
try! data!.write(to: url)
================================================
Actually there're a lot similar questions and good enough answers. Let me try to answer this again.
Basically generating PDF is similar to the drawing in iOS.
Create a PDF context and push it onto the graphics stack.
Create a page .
Use UIKit or Core Graphics routines to draw the content of the page.
Add links if needed .
Repeat steps 2, 3, and 4 as needed.
End the PDF context to pop the context from the graphics stack and, depending on how the context was created, either write the resulting data to the specified PDF file or store it into the specified NSMutableData object.
So the most simple way would be something like this:
func createPDF(image: UIImage) -> NSData? {
let pdfData = NSMutableData()
let pdfConsumer = CGDataConsumer(data: pdfData as CFMutableData)!
var mediaBox = CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height)
let pdfContext = CGContext(consumer: pdfConsumer, mediaBox: &mediaBox, nil)!
pdfContext.beginPage(mediaBox: &mediaBox)
pdfContext.draw(image.cgImage!, in: mediaBox)
pdfContext.endPage()
return pdfData
}
That created all the NSData for the PDF file, then we need to save the data to file:
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let docURL = documentDirectory.appendingPathComponent("myFileName.pdf")
try createPDF(image: someUIImageFile)?.write(to: docURL, atomically: true)
Read more here: Generating PDF Content
in swift 5 using PDFKit :
First Import PDFKit
Then use this array Extension :
import UIKit
import PDFKit
extension Array where Element: UIImage {
func makePDF()-> PDFDocument? {
let pdfDocument = PDFDocument()
for (index,image) in self.enumerated() {
let pdfPage = PDFPage(image: image)
pdfDocument.insert(pdfPage!, at: index)
}
return pdfDocument
}
}
and use this :
let imageArray = [UIImage(named: "1")!,UIImage(named: "2")!] let yourPDF = imageArray.makePDF()
Swift 5 We will use UIGraphicsPDFRenderer() class and it will work for iOS 10+
let image = results.croppedScan.image
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let docURL = documentDirectory.appendingPathComponent("Scanned-Docs.pdf")
let outputFileURL: URL = docURL
let imageBounds = CGRect(origin: .zero, size: image.size)
let pdfRenderer = UIGraphicsPDFRenderer(bounds: imageBounds)
do {
try pdfRenderer.writePDF(to: outputFileURL) { context in
context.beginPage()
results.croppedScan.image.draw(in: imageBounds)
}
} catch {
print("Could not create PDF file: \(error)")
}
print("save at ===\(outputFileURL)")
//Show PDF in Controller
let dc = UIDocumentInteractionController(url: outputFileURL)
dc.delegate = self
dc.presentPreview(animated: true)
PDF Generator written in swift.it will help to generate PDF with image path, image binary, image ref (CGImage)
https://github.com/sgr-ksmt/PDFGenerator
This question already has answers here:
how to load image from local path ios swift (by path)
(8 answers)
Closed 5 years ago.
I am attempting to create a application in xcode 8 swift 3 where the user adds an image using a imagePickerController then when the user clicks either save or exits the imagePickerController I want the image to be saved locally, so next time the app is loaded (for example after a device restart) the image is there. Just to be clear I Do Not want to save the image to the camera roll. Here is my code thus far without any save or load methods, (just the save button reference) any help would be very appreciated as I have been attempting to do this for a long while.
import UIKit
class timetable: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
#IBOutlet var imageviewtimetable: UIImageView!
#IBAction func save(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func selectImageFromPhotoLibrary(_ sender: Any) {
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
present(imagePickerController, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController){
dismiss(animated: true, completion:nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
imageviewtimetable.image = selectedImage
dismiss(animated: true,completion:nil)
}
}
For info : click here
Save image in Document Directory
func saveImageDocumentDirectory() {
let fileManager = NSFileManager.defaultManager()
let paths = (getDirectoryPath() as NSString).stringByAppendingPathComponent("apple.jpg")
let image = UIImage(named: "apple.jpg")
print(paths)
let imageData = UIImageJPEGRepresentation(image!, 0.5)
fileManager.createFileAtPath(paths as String, contents: imageData, attributes: nil)
}
Get Document Directory Path
func getDirectoryPath() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
get Image from document directory
func getImage(){
let fileManager = NSFileManager.defaultManager()
let imagePath = (self.getDirectoryPath() as NSString).stringByAppendingPathComponent("apple.jpg")
if fileManager.fileExistsAtPath(imagePath){
self.imageView.image = UIImage(contentsOfFile: imagePath)
} else {
print("No Image")
}
}
create Directory
func createDirectory(){
let fileManager = NSFileManager.defaultManager()
let paths = getDirectoryPath() as NSString).stringByAppendingPathComponent("customDirectory")
if !fileManager.fileExistsAtPath(paths){
try! fileManager.createDirectoryAtPath(paths, withIntermediateDirectories: true, attributes: nil)
} else {
print("Already dictionary created.")
}
}
I'm currently writing a photo app for iOS in Swift. I'm using the CoreImage Framework to generate a pixel effect on a UIImageView selected by the user. However, I'm having trouble saving the "pixeled" image to the iPhone's Camera Roll. Normally I use
UIImageWriteToSavedPhotosAlbum(pixeledImage,nil,nil,nil)
but it's not saving the UIImage. I have given the app full access to the photo library on the device. It will be helpful if someone could help me figure this out. My image picker:
class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var imagetobepassed: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func Cameratapped(sender: AnyObject) {
var camera = UIImagePickerController()
dispatch_async(dispatch_get_main_queue()) {
camera.delegate = self
camera.sourceType = UIImagePickerControllerSourceType.Camera
camera.allowsEditing = false
self.presentViewController(camera, animated: true, completion: nil)
}
}
#IBAction func photolib(sender: AnyObject) {
var photo = UIImagePickerController()
dispatch_async(dispatch_get_main_queue()) {
photo.delegate = self
photo.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
photo.allowsEditing = false
self.presentViewController(photo, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
imagetobepassed = image
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func editorPressed(sender: AnyObject) {
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "image" {
var editorview = segue.destinationViewController as! EditorViewController
editorview.imagerecived = imagetobepassed
}
}
}
And my editor:
import UIKit
class EditorViewController: UIViewController {
var imagerecived:UIImage!
var pixeledImage:UIImage!
var savedImage:UIImage!
#IBOutlet var imageview: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
pixel()
}
// this function will prduce the pixel effect
func pixel() {
var regularImage = CIImage(image: imagerecived)
var filter = CIFilter(name: "CIPixellate")
filter.setDefaults()
filter.setValue(regularImage, forKey: kCIInputImageKey)
var output = filter.outputImage
pixeledImage = UIImage(CIImage: output)
imageview.image = pixeledImage
}
#IBAction func SaveTapped(sender: AnyObject) {
println(pixeledImage)
UIImageWriteToSavedPhotosAlbum(pixeledImage,nil,nil,nil) // not saving image
}
How can I make this work? I do see this error:
2015-05-16 23:40:05.416 Pixelate2[21579:3341726] Connection to assetsd
was interrupted or assetsd died
First use this line to save image:-
UIImageWriteToSavedPhotosAlbum(pixeledImage, self, "image:didFinishSavingWithError:contextInfo:", nil)
Now implement this method,to catch the error you are getting:-
func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) {
if error == nil {
}
else
{
//log the error out here ,if any
}
}
There is another work around, if you are getting memory warning !
ALAssetsLibrary* lib = [[ALAssetsLibrary alloc] init];
[lib writeImageDataToSavedPhotosAlbum:imageData metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error)
{
// do whatever in the completion handler
}];
I was able to solve the issue using this code:
#IBAction func SaveTapped(sender: AnyObject) {
let softwareContext = CIContext(options: [kCIContextUseSoftwareRenderer:true])
let cgimg = softwareContext.createCGImage(savedImage,
fromRect: savedImage.extent())
let libary = ALAssetsLibrary()
libary.writeImageToSavedPhotosAlbum(cgimg, metadata: savedImage.properties(),
completionBlock: nil)
}