How can I save an array of images into a firebase database? - ios

I have an app where a user takes some pictures which are saved into an array, then when he presses a button i want the array of images to be saved to firebase. I have searched around and not found any good resources for this. Bellow is the code I have already written.
DataModel where I save the array of images:
import Foundation
import UIKit
class PhotoArray {
static let sharedInstance = PhotoArray()
var photosArray: [UIImage] = []
}
Taking picture code:
import UIKit
import RealmSwift
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
// var realm: Realm!
// var photoArray = [PhotoArray]()
#IBOutlet weak var imageView: UIImageView!
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
// realm = try! Realm()
imagePicker.delegate = self
imagePicker.sourceType = .camera
imagePicker.allowsEditing = false
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let userPickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
// let imageToUse = PhotoArray()
// let data = UIImagePNGRepresentation(userPickedImage) //here convert to data
PhotoArray.sharedInstance.photosArray.append(userPickedImage) //append converted data in array
// do {
// try realm.write {
// realm.add(imageToUse)
// }
// } catch {
// print(“error adding image to array\(error)“)
// }
imageView.image = userPickedImage
}
// print(PhotoArray().photosArray.count)
imagePicker.dismiss(animated: true, completion: nil)
}
#IBAction func cameraButtonPressed(_ sender: UIButton) {
present(imagePicker, animated: true, completion: nil)
}
#IBAction func cameraButtonPressed(_ sender: UIButton) {
present(imagePicker, animated: true, completion: nil)
}
#IBAction func SendDataPressed(_ sender: UIButton) {
//TODO: Send the Images to Firebase and save it in our database
let messagesDB = Database.database().reference().child("Images")
let messageDictionary = ["Images": PhotoArray.sharedInstance.photosArray as NSArray]
messagesDB.childByAutoId().setValue(messageDictionary) {
(error, refrence) in
if error != nil {
print(error!)
//somthing
}
else {
print("message saved succesfully")
//somthing
}
}
}
}

Firebase databases don't support adding images to the database. You can find the supported Firebase data types here.
You should instead upload your images to a storage provider such as Firebase Cloud Storage and then save the url to that file in your database to download from later.
Here's an example:
//Create a reference to the image
let imageRef = Storage.storage().reference().child("image.jpg")
// Get image data
if let uploadData = UIImagePNGRepresentation(userPickedImage) {
// Upload image to Firebase Cloud Storage
imageRef.putData(uploadData, metadata: nil) { (metadata, error) in
guard error == nil else {
// Handle error
return
}
// Get full image url
imageRef.downloadURL { (url, error) in
guard let downloadURL = url else {
// Handle error
return
}
// Save url to database
Firestore.firestore().collection("images").document("myImage").setData(["imageUrl" : downloadUrl.absoluteString])
}
}
}

Related

I get "boringssl" error when uploading image to Firebase for iOS

I'm simply trying to upload an image but I'm getting this error "[boringssl] boringssl_metrics_log_metric_block_invoke(153) Failed to log metrics
Optional("User does not have permission to access 'here was the link to the folder.' ")"
My goal is to upload a photo and access it later from another page, but now I'm getting this error.
edit: Later I realized that I am getting some of the same error while signing up "[boringssl] boringssl_metrics_log_metric_block_invoke(153)".
The entered user can register and appears in the Firebase interface, but the above error is displayed on the console.
import UIKit
import Firebase
class UploadViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var commentText: UITextField!
#IBOutlet weak var uploadVar: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
imageView.isUserInteractionEnabled = true
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(chooseImage))
imageView.addGestureRecognizer(gestureRecognizer)
}
#IBAction func UploadClicked(_ sender: Any) {
let storage = Storage.storage()
let storageReferance = storage.reference()
let mediaFolder = storageReferance.child("media")
if let data = imageView.image?.jpegData(compressionQuality: 0.5) {
let imageReferance = mediaFolder.child("image.jpg")
imageReferance.putData(data, metadata: nil) { metaData, error in
if error != nil {
print(error?.localizedDescription)
} else {
imageReferance.downloadURL { url, error in
if error == nil {
let imageURL = url?.absoluteString
print(imageURL)
}
}
}
}
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
imageView.image = info[.originalImage] as? UIImage
self.dismiss(animated: true, completion: nil)
}
#objc func chooseImage() {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = .photoLibrary
present(pickerController, animated: true, completion: nil)
}
}

User variable is nil when creating a user with Firebase

I am following a tutorial and cannot seem to register my user as the user variable in the Firebase .createUser method appears to be nil. Therefore, when I unwrap it, I get an error.
I have read through a lot of the documentation as well as checked many other questions similar to mine but nothing seems to work
import UIKit
import Firebase
import SwiftKeychainWrapper
class ViewController: UIViewController {
#IBOutlet weak var userImgView: UIImageView!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
var imagePicker: UIImagePickerController!
var selectedImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
imagePicker = UIImagePickerController()
imagePicker.allowsEditing = true
imagePicker.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
if let _ = KeychainWrapper.standard.string(forKey: "uid") {
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupUser(userUid: String) {
if let imageData = self.userImgView.image!.jpegData(compressionQuality: 0.2) {
let imgUid = NSUUID().uuidString
let metaData = StorageMetadata()
Storage.storage().reference().child(imgUid).putData(imageData, metadata: metaData) { (metadata, error) in
let downloadURL = metadata
let userData = [
"username": self.usernameField.text!,
"userImg": downloadURL!
] as [String : Any]
Database.database().reference().child("users").child(userUid).setValue(userData)
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
}
#IBAction func signInPressed(_ sender: Any) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().signIn(withEmail: email, password: password) { user, error in
if error != nil && !(self.usernameField.text?.isEmpty)! {
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
self.performSegue(withIdentifier: "toFeed", sender: nil)
let userID = (user?.user.uid)!
self.setupUser(userUid: userID)
KeychainWrapper.standard.set(userID, forKey: "uid")
}
} else {
if let userID = (user?.user.uid) {
KeychainWrapper.standard.set((userID), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
}
}
}
#IBAction func getPhoto (_ sender: AnyObject) {
present(imagePicker, animated: true, completion: nil)
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
internal func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.originalImage] as? UIImage {
userImgView.image = image
} else {
print("image wasnt selected")
}
imagePicker.dismiss(animated: true, completion: nil)
}
}
The error I am getting is one the "let userID = (user?.user.uid)!". It is
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
The completion block for createUser(withEmail:,password:) gets called with either a AuthResult.user or an error. That why, as Joshua commented, you should check if error is nil before accessing any of the user properties.
From the auth quickstart for Swift:
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
strongSelf.hideSpinner {
guard let user = authResult?.user, error == nil else {
strongSelf.showMessagePrompt(error!.localizedDescription)
return
}
print("\(user.email!) created")
strongSelf.navigationController?.popViewController(animated: true)
}
}

Creating an image format with an unknown type is an error...Swift3

I'm learning some swift 3 following courses on youtube. The code below I've written is for creating a user account and storing details in a Firebase database. When testing, I can progress up to the point of submitting the registration form. I then receive the following error:
[Generic] Creating an image format with an unknown type is an error.
Fatal Error: unexpectedly found nil whilst unwrapping an Optionional value.
I have also had the below on the line highlighted in the codeblock below:
exc_bad_instruction(code=exc_i386_invop subcode=0x0)
Below is my code. I have highlighted where the exception is thrown. Any assistance would be much appreciated.
import UIKit
import Firebase
class Signup_ViewController: UIViewController,
UIImagePickerControllerDelegate, UINavigationControllerDelegate {
// Input data fields for signup form
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var nameField: UITextField!
// Password data field for signup form
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var confirmPasswordField: UITextField!
// Next button for signup form (Hidden by default)
#IBOutlet weak var nextBtn: UIButton!
let picker = UIImagePickerController()
var userStorage: FIRStorageReference!
var ref: FIRDatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
let storage = FIRStorage.storage().reference(forURL: "XXXXXXXXXXXXXXXXXXXX") // Defines URL for Firebase storage container
ref = FIRDatabase.database().reference()
userStorage = storage.child("users") // Folder on Firebase storage
}
// Image for signup form - user profile image
#IBOutlet weak var imgView: UIImageView!
// Action for when user presses the "Select profile picture" button
#IBAction func selectProfileImagePress(_ sender: Any) {
picker.allowsEditing = true // Enables user to edit photo
picker.sourceType = .photoLibrary // Enables user to pick photo from photo library
present(picker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
self.imgView.image = image // Checks image selected exists
nextBtn.isHidden = false // Unhides "Next" button once image has been picked
}
self.dismiss(animated: true, completion: nil)
}
// Action for when the "Next" button is pressed
#IBAction func nextPressed(_ sender: Any) {
guard usernameField.text != "", nameField.text != "", emailField.text != "", passwordField.text != "", confirmPasswordField.text != "" else { return }
if passwordField.text == confirmPasswordField.text { // Checks password and confirm password match <---- Error highlights this line when the app crashes out.
FIRAuth.auth()?.createUser(withEmail: emailField.text!, password: passwordField.text!, completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
}
if let user = user {
let changeRequest = FIRAuth.auth()!.currentUser!.profileChangeRequest()
changeRequest.displayName = self.nameField.text!
changeRequest.commitChanges(completion: nil)
let imageRef = self.userStorage.child("\(user.uid).jpg") // Creates JPG file for user uploading (user.uid is variable for specific user)
let data = UIImageJPEGRepresentation(self.imgView.image!, 0.5) // Prepares user profile picture to be sent to Firebase. Applies 0.5 compression to image.
let uploadTask = imageRef.put(data!, metadata: nil, completion: { (metadata, err) in
if err != nil {
print(err!.localizedDescription)
}
imageRef.downloadURL(completion: { (url, er) in
if er != nil {
print(er!.localizedDescription)
}
if let url = url {
let userInfo: [String : Any] = ["uid" : user.uid,
"username" : self.usernameField.text!,
"name" : self.nameField.text!,
"urltoImage" : url.absoluteString]
self.ref.child("users").child(user.uid).setValue(userInfo)
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "userVC")
self.present(vc, animated: true, completion: nil)
}
})
})
uploadTask.resume()
}
})
} else {
print ("Password does not match")
}
}
}
Instead of your code :
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
self.imgView.image = image // Checks image selected exists
nextBtn.isHidden = false // Unhides "Next" button once image has been picked
}
self.dismiss(animated: true, completion: nil)
}
use this one ..
/// what app will do when user choose & complete the selection image :
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
/// chcek if you can return edited image that user choose it if user already edit it(crop it), return it as image
if let editedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
/// if user update it and already got it , just return it to 'self.imgView.image'
self.imgView.image = editedImage
/// else if you could't find the edited image that means user select original image same is it without editing .
} else if let orginalImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
/// if user update it and already got it , just return it to 'self.imgView.image'.
self.imgView.image = orginalImage
}
else { print ("error") }
/// if the request successfully done just dismiss
picker.dismiss(animated: true, completion: nil)
}
And for this error :
Creating an image format with an unknown type is an error…Swift3
It's a bug in xcode , if picker could select and return images properly that means everything is okay , just ignore it .

How do i save and recall a UIImage on the View Controller?

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.

UIImage not saving to Camera Roll

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)
}

Resources