Can't load image with UIImage or NSData - ios

I am programming a Swift application, and I can't load image saved in the application by using UIImage(contentsOfFile: imgPath) or NSData(contentsOfFile: imgPath)
private func loadData() {
println("load DATA DANGEROUS")
let (dangerous, err) = SD.executeQuery("SELECT * FROM Dangerous")
if err == nil && !dangerous.isEmpty {
var tabPhoto : [DangerousImage] = []
for d in dangerous {
let desc = d["description"]!.asString()!
let idDangerous = d["id"]!.asInt()!
println("iddangerous : \(idDangerous)")
let (photos, error) = SD.executeQuery("SELECT * FROM Photo WHERE idDangerous = ?", withArgs: [idDangerous])
if error == nil {
for photo in photos {
let imgPath = photo["photoPath"]!.asString()!
println(imgPath)
let uimage = UIImage(contentsOfFile: imgPath) // fatal error: unexpectedly found nil while unwrapping an Optional value
tabPhoto.append(DangerousImage(img: uimage!, path: imgPath))
}
}
println("add ENTRY")
self.tabEntry.append(Entry(descript: desc, tab: tabPhoto))
}
}
println("TAB ENTRY : \(tabEntry)")
}
My picture exists with this path : /var/mobile/Containers/Data/Application/...ID-APP.../Documents/images/JPEG_201506162_101128_IOS_99804574.jpg
Thank for your help.
Ysee

From I can see in your code, you are storing the full path to the image in your database, eg. "/var/mobile/Containers/Data/Application/...ID-APP.../Documents/images/JPEG_201506162_101128_IOS_99804574.jpg". Since iOS8, the folder structure has changed - the UDID in the path is changing every time the app is updated or a new build is installed during development. That's why should store a relative path to your image, eg. "/images/JPEG_201506162_101128_IOS_99804574.jpg" and then get the Documents directory with NSSearchPathForDirectoriesInDomains method.

Related

Why does my MLKit model always returns an error when processing an image?

I have a Google MLKit model for labeling an Image after capturing the image, but everytime I tried to process the Image, it always give me this error:
label process error:: Pipeline failed to fully start: Calculator::Open() for node "ClassifierClientCalculator" failed: #vk The TFLite Model Metadata must not contain label maps when text_label_map_file is used.
Here's my MLKit image labeler configuration code (this code is based on MLKit's documentation):
private func configureModelSource() { // Called in viewDidLoad()
guard let manifestPath = Bundle.main.path(forResource: "filename", ofType: "json") else { return }
guard let localModel = LocalModel(manifestPath: manifestPath) else { return }
let options = CustomImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0)
imageLabeler = ImageLabeler.imageLabeler(options: options)
}
private func processImage(with image: UIImage) { // Called after capturing an Image
guard imageLabeler != nil else { return }
let visionImage = VisionImage(image: image)
visionImage.orientation = image.imageOrientation
imageLabeler?.process(visionImage) { labels, error in
guard error == nil, let labels = labels, !labels.isEmpty else {
print("label process error:: \(error?.localizedDescription ?? "nil")")
return
}
for label in labels {
// Do something...
}
}
}
Is there anyway to solve this? For context, the model.tflite file was updated. The file before the one that gives me this error works as expected. But the new model.tflite file always gives me this error everytime I run my app. Is this a file-related error or did I do something wrong with my code that I have to also update it?
Here's my understanding based on the error message:
Given you are using the LocalModel(manifestPath: manifestPath) API, it is expecting a legacy TFLite model format where the label map is provided through a separate text file and the model.tflite itself does not contain the label map. That's why your file before your model update works.
To use your updated model.tflite (which seems to contain the lab map inside its metadata), I think you can try the following to use the model.tflite file directly with the custom models API without going through the filename.json manifest:
guard let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") else { return }
guard let localModel = LocalModel(path: modelPath) else { return }
You can check out the documentation about custom models here: https://developers.google.com/ml-kit/vision/image-labeling/custom-models/ios

Error 13010 "Object does not exist" while downloading jpeg image from Firebase storage using getData()

Language : Swift 5
iOS: 13.2
macOS: Catalina 10.15.4
Firebase Storage Rules:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth!=null;
}
}
}
The code to upload image and save download URL: (Which works fine, because I can see images uploaded to storage and their respective download URLs stored to real-time database.)
let storageRef = Storage.storage().reference()
//Let's upload all workout pictures
let uploadPicsRef =
storageRef.child("WORKOUTDATA/USERS/"+self.UID!).child("WHITEBOARDWORKOUTS")
let uploadNumberRef = uploadPicsRef.child("\(String(describing: workoutNum))")
let workoutPicturesRef = uploadNumberRef.child("WORKOUTPICTURES")
let workoutPicURLRef = workoutRef.child("WORKOUTPICTURESURL")
var count = 0
var picNumber = 0
//workoutPictures list/array contains images selected from iPhone Gallery, using
//UIImagePickerController
for workoutPic in self.workoutPictures
{
let workoutPicData = workoutPic.jpegData(compressionQuality: 1.0)!
count = count + 1
let pictureName = "Picture\(count).jpg"
// Upload the file to the path in pictureRef
let pictureRef = workoutPicturesRef.child("\(pictureName)")
let metaData = StorageMetadata()
metaData.contentType = "image/jpg"
pictureRef.putData(workoutPicData, metadata: metaData) { (metadata, error) in
if error != nil {
print("Error while uploading image")
}
else
{
pictureRef.downloadURL { (url, err) in
picNumber = picNumber + 1
workoutPicURLRef.child("Picture\(picNumber)").setValue(url?.absoluteString)
}
}
}
}
The code to download image:
let myGroup = DispatchGroup()
let workoutPicUrls = snapshot.childSnapshot(forPath: "WORKOUTPICTURESURL")
for url in workoutPicUrls.children
{
myGroup.enter()
let snap = url as! DataSnapshot
let link = snap.value as? String
let storageRef = Storage.storage().reference()
let pictureRef = storageRef.root().child(link!)
DispatchQueue.main.async {
pictureRef.getData(maxSize: 1*2000000*2000000) { (data, err) in
if (err != nil) {
print(err!)
print(err!.localizedDescription)
} else {
let pic = UIImage(data: data!)
workoutPicsArray.append(pic!)
myGroup.leave()
}
}
}
}
Error:
Error Domain=FIRStorageErrorDomain Code=-13010 "Object https:/firebasestorage.googleapis.com/v0/b/trainer-8cb52.appspot.com/o/WORKOUTDATA%2FUSERS%2F1K7WV1alYIeWPAsFC6YMoJKPFSj1%2FWHITEBOARDWORKOUTS%2F5%2FWORKOUTPICTURES%2FPicture1.jpg?alt=media&token=785ab8c7-1e08-4ad3-a542-c9e6313eb547 does not exist." UserInfo={object=https:/firebasestorage.googleapis.com/v0/b/trainer-8cb52.appspot.com/o/WORKOUTDATA%2FUSERS%2F1K7WV1alYIeWPAsFC6YMoJKPFSj1%2FWHITEBOARDWORKOUTS%2F5%2FWORKOUTPICTURES%2FPicture1.jpg?alt=media&token=785ab8c7-1e08-4ad3-a542-c9e6313eb547, ResponseBody={
"error": {
"code": 404,
"message": "Not Found. Could not get object",
"status": "GET_OBJECT"
}
}, bucket=trainer-8cb52.appspot.com, data={length = 115, bytes = 0x7b0a2020 22657272 6f72223a 207b0a20 ... 54220a20 207d0a7d }, data_content_type=application/json; charset=UTF-8, NSLocalizedDescription=Object https:/firebasestorage.googleapis.com/v0/b/trainer-8cb52.appspot.com/o/WORKOUTDATA%2FUSERS%2F1K7WV1alYIeWPAsFC6YMoJKPFSj1%2FWHITEBOARDWORKOUTS%2F5%2FWORKOUTPICTURES%2FPicture1.jpg?alt=media&token=785ab8c7-1e08-4ad3-a542-c9e6313eb547 does not exist., ResponseErrorDomain=com.google.HTTPStatus, ResponseErrorCode=404}
What I have tried so far:
Checked firebase storage rules.
When I paste the path https:/firebasestorage.googleapis.com/v0/b/trainer8cb52.appspot.com/o/WORKOUTDATA%2FUSERS%2F1K7WV1alYIeWPAsFC6YMoJKPFSj1%2FWHITEBOARDWORKOUTS%2F5%2FWORKOUTPICTURES%2FPicture1.jpg?alt=media&token=785ab8c7-1e08-4ad3-a542-c9e6313eb547 in chrome browser window, the expected image opens.
Set the maxSize to a ridiculously high number 1*2000000*2000000.
Thank you!
Is it possible that you are storing the full https URL in the database and are trying to create a reference by adding the full https url as a child to the storage reference?
I think you should try to either store just the path and name in your database or you change your download code to use the https URL.
// Create a reference from an HTTPS URL
// Note that in the URL, characters are URL escaped!
let httpsReference = storage.reference(forURL: "https://firebasestorage.googleapis.com/b/bucket/o/images%20stars.jpg")
httpsReference.getData(maxSize: ...
Also you're running your getData method inside DispatchQueue.main.async. getData has itself a completion handler and might take some time, when you run that inside of DispatchQueue.main.async it will block your code until the download is done. Only put code that update the UI inside DispatchQueue.main.async. In your case as soon as you do something with your workoutPicsArray or the UIImage to update your view.
Have a look here to see if you can figure out how you are actually trying to get the data. It might be helpful to put a print() after each line to see what you are creating and using at what point.
Download Files on iOS

Swift Get data from Firebase Storage

I'm trying to fetch image data from firebase storage with swift .
Code :
let ref = Storage.storage().reference().child("users").child("uid").child("savedimage");
let task = ref.getData(maxSize: 1024*1024*12) { (data, error) in
if let data = data , let image = UIImage(data: data) {
print("image exists");
self.imageView.image = image;
}else {
print(error);
}
}
task.resume();
But most of the time the app crash after a second of getting the image , and take me to this :
It's not showing any error in console output so i cannot figure out what's the issue but sometimes it's give me a warning before the crash :
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
What i'm doing wrong ?

Xcode - iOS - AWS S3 - Downloaded Image Doesn't Appear On First Download

Here is the code I use to download an image from an AWS S3 server and assign it to be the image displayed in an image view:
let s3BucketName = "bucketName"
let fileName = Globals.currAuthorName.filter { $0 != Character(" ") } + ".jpg"
let downloadFilePath = NSTemporaryDirectory().stringByAppendingPathComponent(fileName)
let downloadingFileURL = NSURL.fileURLWithPath(downloadFilePath)
// Create a credential provider for AWS requests
let credentialsProvider = AWSCognitoCredentialsProvider(
regionType: AWSRegionType.USEast1,
identityPoolId: "us-east-1:********-****-****-****-************")
// Create a service configuration for AWS requests
let defaultServiceConfiguration = AWSServiceConfiguration(
region: AWSRegionType.USEast1,
credentialsProvider: credentialsProvider)
// Create a new download request to S3, and set its properties
AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = defaultServiceConfiguration
let downloadRequest = AWSS3TransferManagerDownloadRequest()
downloadRequest.bucket = s3BucketName
downloadRequest.key = "folderName/" + fileName
downloadRequest.downloadingFileURL = downloadingFileURL
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
transferManager.download(downloadRequest)
// Set the UIImageView to show the file that was downloaded
let image = UIImage(contentsOfFile: downloadFilePath)
authorImage.contentMode = UIViewContentMode.ScaleAspectFit
authorImage.image = image
The problem is that when I run the iOS Simulator and navigate to the appropriate page, the image is never loaded the first time I visit the page. However, it is always loaded when I navigate away from the page and then return the page, and every subsequent time I visit the page. The image is still loaded when I stop running the app and then start it again and visit the page again. The image is only not loaded the very first time I visit the page for a certain iOS Simulator (i.e. it happens once in the iPhone 6 simulator, the iPhone 5 simulator, etc)
I tried to fix the problem by adding this bit of code:
while (image == nil) {
transferManager.download(downloadRequest)
let image = UIImage(contentsOfFile: downloadFilePath)
}
But that simply resulted in an infinite while loop the first time I visited the page. Also the console eventually output this error:
2015-07-06 23:26:28.529 CCBF[19839:92323] 19839: CFNetwork internal error (0xc01a:/SourceCache/CFNetwork_Sim/CFNetwork-711.3.18/Foundation/NSURLRequest.mm:798)
2015-07-06 23:26:28.564 AuthorProject[19839:92323] AWSiOSSDKv2 [Error] AWSURLSessionManager.m line:240 | __41-[AWSURLSessionManager taskWithDelegate:]_block_invoke222 | Invalid AWSURLSessionTaskType.
EDIT:
I tried to implement the following continuewithblock:
var image : UIImage!
let task = transferManager.download(downloadRequest)
task.continueWithBlock({
if task.error != nil {
println(task.error)
} else {
dispatch_async(dispatch_get_main_queue(), {
image = UIImage(contentsOfFile: downloadFilePath)
self.authorImage.contentMode = UIViewContentMode.ScaleAspectFit
self.authorImage.image = image
})
}
return nil
}())
However, when I ran it and tried to load the image, I got a runtime error that pointed me to the code for a "continueWithExecutor" method. Specifically, the line of code:
result = block(self);
With the message being:
EXC_BAD_ACCESS(code: 1, address=0x10)
EDIT2:
I seem to have found a solution that works:
var image : UIImage!
let taskTODO = transferManager.download(downloadRequest)
taskTODO.continueWithBlock{ (task: AWSTask!) -> AnyObject! in
if task.error != nil {
println(task.error)
} else {
dispatch_async(dispatch_get_main_queue(), {
image = UIImage(contentsOfFile: downloadFilePath)
self.authorImage.contentMode = UIViewContentMode.ScaleAspectFit
self.authorImage.image = image
})
}
return nil
}
Does this seem like the correct way to do it?
transferManager.download(downloadRequest) is asynchronous, meaning it takes about 20 miliseconds to download the image. However, the first time into the screen you are trying to assign the image immediately (which has not yet been downloaded). In subsequent screen loads - the image has already been downloaded and cached - so it's immediately ready to be displayed, . What you need is a completion block that indicates when the image is has finished downloading and is ready for display and in that block you shall assign the image. See example below:
let readRequest1 : AWSS3TransferManagerDownloadRequest = AWSS3TransferManagerDownloadRequest()
readRequest1.bucket = "shrikar-picbucket"
readRequest1.key = "bingo"
readRequest1.downloadingFileURL = downloadingFileURL1
let task = transferManager.download(readRequest1)
task.continueWithBlock { (task) ->; AnyObject! in
println(task.error)
if task.error != nil {
} else {
dispatch_async(dispatch_get_main_queue()
, { () ->; Void in
self.selectedImage.image = UIImage(contentsOfFile: downloadingFilePath1)
self.selectedImage.setNeedsDisplay()
self.selectedImage.reloadInputViews()
})
println("Fetched image")
}
return nil
}

SQLLite Error - Failed to open DB

I have the following sqllite code:
func createAndCheckDatabase()-> Bool
{
var success: Bool = true
var db:COpaquePointer = nil // Get path to DB in Documents directory
let docDir:AnyObject = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let path = docDir.stringByAppendingPathComponent("MyDatabase.db")
// Check if copy of DB is there in Documents directory
let fm = NSFileManager.defaultManager()
if !(fm.fileExistsAtPath(path)) {
// The database does not exist, so copy to Documents directory
let from = NSBundle.mainBundle().resourcePath!.stringByAppendingPathComponent(databaseName)
var error:NSError?
if !fm.copyItemAtPath(from, toPath: path, error: &error) {
//ALWAYS ERRORS HERE THE FIRST TIME
println("SQLiteDB - #1 failed to open DB.")
println("Error - \(error!.localizedDescription)")
}
}
databasePath = path
// Open the DB
let cpath = (path as NSString).UTF8String
let error = sqlite3_open(cpath, &db)
if error != SQLITE_OK {
// Open failed, close DB and fail
println("SQLiteDB - another error - couldn't open DB")
sqlite3_close(db)
}
return success
}
I call this function within my app delegate with the thought that it would successfully create my database once (and only once). Whenever I clear settings and run it, it always hits the area I've marked (error) once. After running it again I never get this error anymore.
Is there some logic flaw in this code (I mostly copied this code) or am I perhaps reporting an error that is actually not? I suspect that it might just be happening the first time it creates, but i'm actually OK and can start interacting with the database just fine.
Also does anyone sees something concerning in the code?
Thanks!
Well, after not really figuring out why the above code cobbled together from online tutorials did as I described, I found a very helpful article here:
http://metrozines.com
This ended up solving my problem (by following how they did things and introducing the code from the tutorial). Now when I clear settings, it doesn't crash and starting it up again works correctly without throwing an error.
The code that works now is this:
func createAndCheckDatabase() -> Bool {
let DATABASE_RESOURCE_NAME = "abc"
let DATABASE_RESOURCE_TYPE = "sqlite"
let DATABASE_FILE_NAME = "abc.sqlite"
let documentFolderPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let dbfile = "/" + DATABASE_FILE_NAME;
self.dbFilePath = documentFolderPath.stringByAppendingString(dbfile)
let filemanager = NSFileManager.defaultManager()
if (!filemanager.fileExistsAtPath(dbFilePath) ) {
let backupDbPath = NSBundle.mainBundle().pathForResource(DATABASE_RESOURCE_NAME, ofType: DATABASE_RESOURCE_TYPE)
if (backupDbPath == nil) {
return false
} else {
var error: NSError?
let copySuccessful = filemanager.copyItemAtPath(backupDbPath!, toPath:dbFilePath, error: &error)
if !copySuccessful {
println("copy failed: \(error?.localizedDescription)")
return false
}
}
}
return true
}

Resources