Unsupported URL for image layer mapbox iOS - ios

I am trying to learn mapbox maps iOS but am struggling with inserting an image layer.
The image is however, failing to load, throwing the error:
Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL"
The docs for for this structure are here
Please help!!!
ViewController.swift:
mapView.mapboxMap.onNext(.mapLoaded) { _ in
self.addImageLayer()
}
internal func addImageLayer() {
var sourceId = "planet-source"
let style = mapView.mapboxMap.style
// Create an `ImageSource`. This will manage the image displayed in the `RasterLayer` as well
// as the location of that image on the map.
var imageSource = ImageSource()
// Set the `coordinates` property to an array of longitude, latitude pairs.
imageSource.coordinates = [
[-80.425, 46.437],
[-71.516, 46.437],
[-71.516, 37.936],
[-80.425, 37.936]
]
// Get the file path for the first radar image, then set the `url` for the `ImageSource` to that path.
let path = Bundle.main.path(forResource: "planet", ofType: "svg")!
imageSource.url = path
// Create a `RasterLayer` that will display the images from the `ImageSource`
var imageLayer = Layer(id: "planet-layer")
imageLayer.source = sourceId
do {
try style.addSource(imageSource, id: sourceId)
try style.addLayer(imageLayer)
} catch {
print("Failed to add the source or layer to style. Error: \(error)")
}
}

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

Retrieving a video from Documents Directory, but app cannot find location

I have implemented Core Data to save string formatted URLS in my application. These URLS are URLS of videos they have recorded.
I used core data because I want the video to still be available to them after they exit out of the app. I am able to save and retrieve the URLS. However, when i use them to get the video thumbnails it does not work.
Here is where I declare the video file location:
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let cropUniqueId = NSUUID().uuidString
let outputPath = "\(documentsPath)/\(cropUniqueId).mov"
Then i convert it to a string and save the data to core data:
arrayOfStringPaths.append(outputPath)
stringOfArrayPaths = stringOfArrayPaths + arrayOfStringPaths.joined(separator: ",")
saveData(arrayPath: stringOfArrayPaths)
func saveData(arrayPath: String) {
let savedVideo = VideoPath(context: context)
savedVideo.fileLocations = arrayPath
appDelegate.saveContext()
print("Saved")
}
Everything so far works fine. It saves the URLS just as they are, i checked them with various print statements.
Now I retrieve the information when the user opens the app.
var data = [VideoPath]()
func fetchSavedData() {
do {
data = try context.fetch(VideoPath.fetchRequest())
for each in data {
// I append each url to the array.
videosArray.append(URL(fileURLWithPath: each.fileLocations!))
// They all print out correctly
print(each.fileLocations!)
}
for video in videosArray {
print("This is in video array")
// This prints out correctly as the URL i recorded earlier
print(video)
// This is where everything messes up
let thumbnail = getThumbnail(video)
thumbnails.append(thumbnail)
}
} catch {
print("There was an error")
}
}
When i try to get the thumbnail of the video it gives me this error here:
"The requested URL was not found on this server." UserInfo={NSLocalizedDescription=The requested URL was not found on this server., NSUnderlyingError=0x17064c330 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-802.0.53/src/swift/stdlib/public/core/ErrorType.swift

Access the files/folders in the Assets folder for TVOS programmatically

I am working on a TVOS 10 project with Swift 3.0 and I am trying to access the files in the Assets folder from the controller.
I have this array:
var posters: [String] = ["image1", "image2", "image3","image4", "image5"]
But I want to populate this array programmatically. So if i change the files in the assets, the content of the array should change.
Because later I do this:
//currentImage is an ImageView in storyboard
currentImage.image = UIImage(named: posters[currentPoster])
This is the hierarchy of my files.
This is what I have tried but it does not give me what I want.
if let resourcePath = Bundle.main().resourcePath {
print(resourcePath)
do {
let temp = try FileManager.default().contentsOfDirectory(atPath: resourcePath)
print(temp)
let assetsPath = resourcePath + "/" + temp[6]
let temp2 = try FileManager.default().contentsOfDirectory(atPath: assetsPath)
print (temp2)
}
catch let error as NSError {
print(error)
}
}
Output:
/var/containers/Bundle/Application/9AECCDB0-DD5F-4377-9237-6E7DA1E14A39/PosterAppTV.app
["Assets.car", "Base.lproj", "Frameworks", "Info.plist", "META-INF", "PkgInfo", "PosterAppTV", "_CodeSignature", "embedded.mobileprovision", "libswiftRemoteMirror.dylib"]
Error Domain=NSCocoaErrorDomain Code=256 "The file “PosterAppTV” couldn’t be opened." UserInfo={NSFilePath=/var/containers/Bundle/Application/9AECCDB0-DD5F-4377-9237-6E7DA1E14A39/PosterAppTV.app/PosterAppTV, NSUserStringVariant=(
Folder
), NSUnderlyingError=0x1740524e0 {Error Domain=NSPOSIXErrorDomain Code=20 "Not a directory"}}
Any help how to get a list of names of the files in the Assets/Posters folder?
Also, if this may not be possible, are there other ways to store some pictures into a folder and then access the names of those files programmatically?
When you are placing your images in assets it means xcode have remembered your all image names, there is no need to call any folder name or directory path, now you can directly call your image name in code.
Here is what you are looking for:
var posters: [String] = ["image1", "image2", "image3","image4", "image5"]
if let myImage = UIImage(named: posters[2]) {
imageView.image = myImage //image3 is called at the index of 2 in posters array
}
else {
print("image not found")
}
Or you can retrieve your images in one line like this:
imageView.image = UIImage(named: posters[2])

Can't load image with UIImage or NSData

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.

Resources