Using Cloudkit Assets as a UIimage - swift

I have images saved in CloudKit as an asset. There are other attributes for each record as well. I can gather the record and use the other attributes, but I'm unable to use the asset in my ImageView. I'm new to Swift programming, therefore the error I receive does not make any sense.
let container = CKContainer.default()
let publicDB = container.publicCloudDatabase
let query1 = CKQuery(recordType: "movieArray", predicate: predicate2)
publicDB.perform(query1, inZoneWith: nil) {(results:[CKRecord]?, error:Error?) in
if error != nil {
DispatchQueue.main.async {
print("Cloud Query Error - Fetch Establishments: \(String(describing: error))")
}
return
}
for record in results! {
DispatchQueue.main.async {
let asset = record["myImageKey"] as? CKAsset
let data = NSData(contentsOf: (asset?.fileURL)!)
let image = UIImage(data: data! as Data)
print("Test")
self.detailImage.image = image
}
self.movieCast.text = record.object(forKey: "Actors") as? String
self.detailDescriptionLabel.text = record.object(forKey: "Description") as? String
let youLink = record.object(forKey: "youtubeTag") as! String
self.loadYoutube(videoID: youLink)
}
}
The error I get is on this line:
let data = NSData(contentsOf: (asset?.fileURL)!)
it says:
Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1020527c4
I attempted to remove it from the main thread, but I receive the same error.

Maybe the problem is that the CKAsset record is nil, but you are forcing to have a fileURL value.
Try to obtain CloudKit image with this snippet
if let asset = record["myImageKey"] as? CKAsset,
let data = try? Data(contentsOf: (asset.fileURL)),
let image = UIImage(data: data)
{
self.detailImage.image = image
}

Related

Retrieve data from Firebase Realtime Database to display I UIImage

I would like to know how to retrieve an image from a link in the Firebase Realtime.. I have set up my UIImageView in my app and linked it to my ViewController, how ever the code that I added doesn't give me error but it doesn't display anything.
My viewcontroller
let userID = Auth.auth().currentUser?.uid
Database.database().reference().child("Users").child(userID!).child("Total Progress").observeSingleEvent(of: .value, with: { snapshot in
if let url = snapshot.value as? String {
URLSession.shared.dataTask(with: URL(string: url)!) { [self] data, response, error in
if error == nil {
let image = UIImage(data: data!)
financialLiteracy.image = image
}
}.resume()
}
})
My Firebase Realtime Database
Realtime Database
let userID = Auth.auth().currentUser?.uid
Database.database().reference().child("Users").child(userID!).child("Total Progress").observeSingleEvent(of: .value, with: { snapshot in
if let url = snapshot.value as? String {
URLSession.shared.dataTask(with: URL(string: url)!) { [self] data, response, error in
if let data = data {
DispatchQueue.main.async {
let image = UIImage(data: data)
self.financialLiteracy.image = image
}
}
if let error = error {
print(error.localizedDescription)
}
}.resume()
}
})
use main thread for ui updates
the second way to get it
let userID = Auth.auth().currentUser?.uid
Database.database().reference().child("Users").child(userID!).child("Total Progress").observeSingleEvent(of: .value, with: { snapshot in
DispatchQueue.global(qos: .background).async {
if let urlstring = snapshot.value as? String,
let url = URL(string: urlstring) {
if let data = try? Data(contentsOf: url) {
DispatchQueue.main.async {
let image = UIImage(data: data)
self.financialLiteracy.image = image
}
}
}
}
}

Swift UIImageView Firebase DispatchQueue

I am using firebase to save and load my images. I have created a new view in Xcode and am using the same code I have been using to load profile images. Yet, this is now throwing an error saying that the url string is nil. The image url data disappears after "DispatchQueue.global().async". What could be causing this and how could I track this? Very strange how this code works for other views yet for this new view it is throwing an error.
let businessProfilePicture = dictionary["profPicString"] as! String
if businessProfilePicture.count > 0 {
let url = URL(string: businessProfilePicture)
print(url)
print("printing the url here to check")
DispatchQueue.global().async {
let dataURL = try? Data(contentsOf: url!)
print(dataURL)
print("printing the data url here")
DispatchQueue.main.async {
print(dataURL)
print("Printing Data to check")
let image = UIImage(data: dataURL!)?.potter_circleo
self.businessProfilePicture.contentMode = UIView.ContentMode.scaleAspectFill
self.businessProfilePicture.image = image
}
}
Full Code
func getWorkLocation() {
let uid = Auth.auth().currentUser?.uid
var profPicURL: String = ""
Database.database().reference().child("employees").child(uid!).child("Business").observe(.value, with: { snapshot in
if snapshot.exists() {
let dictionary = snapshot.value as? NSDictionary
self.businessName.text = dictionary?["businessName"] as? String
self.businessStreet.text = dictionary?["businessStreet"] as? String
self.businessCity.text = dictionary?["businessCity"] as? String
profPicURL = dictionary?["profPicString"] as! String
// set image
if profPicURL.count > 0 {
let url = URL(string: profPicURL)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
let image = UIImage(data: data!)?.potter_circle
self.businessProfilePicture.contentMode = UIView.ContentMode.scaleAspectFill
self.businessProfilePicture.image = image
}
}
} else {
let image = UIImage(named: "profile picture")?.potter_circle
self.businessProfilePicture.contentMode = UIView.ContentMode.scaleAspectFill
self.businessProfilePicture.image = image
}
} else {
self.businessName.text = ""
self.businessStreet.text = "Go to Add Work Location to send request"
self.businessCity.text = ""
self.deleteButton.isEnabled = false
}
})
}
Are you certain that the URL you create from profPicURL is being created properly?
URL(string:) can fail and return nil. If you then go on to implicitly unwrap it in Data(contentsOf: url!) you will crash.
Similarly, try? Data(contentsOf: url) can return nil. If it does, then when you implicitly unwrap it in UIImage(data: data!) you will crash.
As Jacob said in comments, you need to learn more about implicitly unwrapped optionals. To get you started, you might structure your code something like this:
if let url = URL(string: profPicURL) {
DispatchQueue.global().async {
if let data = try? Data(contentsOf: url),
let image = UIImage(data: data)?.potter_circle
{
DispatchQueue.main.async {
self.businessProfilePicture.contentMode = UIView.ContentMode.scaleAspectFill
self.businessProfilePicture.image = image
}
} else {
// raise an an error or set self.businessProfilePicture.image to a generic image or something
}
}
} else {
// raise an an error or set self.businessProfilePicture.image to a generic image or something
}

swift firebase get Image from Storage and show in JSQMessage Controller

I want to get a saved Image in Firebase Storage.
I have the url saved in an string value in the Firebase database:
mediaUrl = url!.absoluteString
Now I want to get this image.
I observe the messages.
func observeMessages() {
let query = Constants.refs.databaseChats.child(chatId).queryLimited(toLast: 50)
_ = query.observe(.childAdded, with: { [weak self] snapshot in
if let data = snapshot.value as? [String: String],
let id = data["sender_id"],
let name = data["name"],
let timestamp = data["timestamp"],
let media = data["media"],
let text = data["text"]?.encode(),
!text.isEmpty
{
if media == "text" {
if let message = JSQMessage(senderId: id, senderDisplayName: name, date: self!.dateFormatter.date(from: timestamp), text: text) {
self?.messages.append(message)
self?.finishReceivingMessage()
}
}
else if media == "image" {
let storageRef = Storage.storage().reference(withPath: text)
storageRef.getData(maxSize: 1 * 1024 * 1024) { (data, error) -> Void in
if data != nil {
let image = UIImage(data: data!)
if let imageMessage = JSQMessage(senderId: id, senderDisplayName: name, date: self!.dateFormatter.date(from: timestamp), media: image as! JSQMessageMediaData) {
self?.messages.append(imageMessage)
print("image message")
self?.finishReceivingMessage()
}
}
}
}
}
})
}
If the media is an image, I want to create an image bubble, and when text a normal text bubble.
But I get no Image in the JSQMEssageViewController.
What went wrong? Can someone help me there?
I get the url in console:
https://firebasestorage.googleapis.com/v0/b/emmessenger-22.appspot.com/o/media%2FJzl0EUmjSvZZcpCd8Mdi8X9q87G2%2F03.06.2019%2021:26:39?alt=media&token=1c45feaf-0ed8-4f88-9c1f-13f4c6a8f3d4
And after that I get the following at console:
2019-06-03 21:28:21.092580+0200 EMMessenger[38502:554129] [] nw_proxy_resolver_create_parsed_array PAC evaluation error: NSURLErrorDomain: -1003
Thanks
Actually you don't need to call getData function for this case. As you're using tableView so I would recommend to use SDWebImage library to load the images on cells asynchronously. Once you have the imageURL just call below method
yourImageView.sd_setImage(with: URL(string: "https://firebasestorage.googleapis.com/v0/b/emmessenger-22.appspot.com/o/media%2FJzl0EUmjSvZZcpCd8Mdi8X9q87G2%2F03.06.2019%2021:26:39?alt=media&token=1c45feaf-0ed8-4f88-9c1f-13f4c6a8f3d4"), placeholderImage: UIImage(named: "placeholder.png"))
Rest the library will do for you.

How to decode Base64Encoded Bytes to Image in Swift 4

I want to convert a bas64 string to an image. Here's the code I currently have.
let sData = success as! String
let str = String(utf8String: sData.cString(using: String.Encoding.utf8)!)
let decodedData = NSData(base64Encoded: str!, options: NSData.Base64DecodingOptions(rawValue: 0) )
let image = UIImage(data: decodedData! as Data)
if let decodedData = Data(base64Encoded: (yourBase64Dasta as? String)! , options: .ignoreUnknownCharacters) {
imgThumb = UIImage(data: decodedData)
}
this is currently working code in my swift 4 project so you can use it :)
Here's an extension you can use to easily initialize an image from a base43 string:
extension UIImage {
convenience init?(base64 str: String) {
guard let url = URL(string: str),
let data = try? Foundation.Data(contentsOf: url),
UIImage(data: data) != nil else { return nil }
self.init(data: data)!
}
}
Then you can do:
let image = UIImage(base64: "string from your server goes here")

Swift loading images from firebase

Does someone know why this is not working? The tableView is empty and not showing anything even though there are items in the database and storage. This worked fine before I implemented the loading of the images from storage which you will see at the bottom of this code that I have pasted in. The food.append() statement used to be outside the storageRef.getData() closure (since it didn't exist) however if I take it out now it won't be able to access recipeImage since it's declared within the closure. Is it not working because it's in the closure? If so how do I fix it?
let parentRef = Database.database().reference().child("Recipes")
let storage = Storage.storage()
parentRef.observe(.value, with: { snapshot in
//Processes values received from server
if ( snapshot.value is NSNull ) {
// DATA WAS NOT FOUND
print("– – – Data was not found – – –")
} else {
//Clears array so that it does not load duplicates
food = []
// DATA WAS FOUND
for user_child in (snapshot.children) {
let user_snap = user_child as! DataSnapshot
let dict = user_snap.value as! [String: String?]
//Defines variables for labels
let recipeName = dict["Name"] as? String
let recipeDescription = dict["Description"] as? String
let downloadURL = dict["Image"] as? String
let storageRef = storage.reference(forURL: downloadURL!)
storageRef.getData(maxSize: 1 * 1024 * 1024) { (data, error) -> Void in
let recipeImage = UIImage(data: data!)
food.append(Element(name: recipeName!, description: recipeDescription!, image: recipeImage!))
}
}
self.tableView.reloadData()
}
})
Move
self.tableView.reloadData()
after
food.append(Element(name: recipeName!, description: recipeDescription!, image: recipeImage!))