What happens in Dropbox API for iOS (Swift) if I create a folder that already exists? - dropbox

The first time I do it, I want the folder created.
The next time, should I check if folder already exists, or just do the create folder and assume nothing happens?

You can do this either way:
Check if the folder exists before attempting to create it:
client.files.getMetadata(path: folderPath).response { response, error in
if let _ = response {
print("Something already exists at path.")
} else if let error = error {
switch error {
case .routeError(let boxed, _, _, _):
switch boxed.unboxed as Files.GetMetadataError {
case .path(let lookupError):
switch lookupError {
case .notFound:
print("Nothing was found at this path. Attempting to create folder...")
client.files.createFolderV2(path: folderPath).response { response, error in
if let response = response {
print("Created folder:")
print(response)
} else if let error = error {
print("Error creating folder: ")
print(error)
}
}
default:
print("Some other error occurred.")
// handle accordingly...
}
}
default:
print("Some other error occurred.")
// handle accordingly...
}
}
}
Always attempt to create the folder, and handle the error that occurs if it already exists:
client.files.createFolderV2(path: folderPath).response { response, error in
if let response = response {
print("Created folder:")
print(response)
} else if let error = error {
print("Error creating folder: ")
print(error)
// handle accordingly...
}
}

Related

How to display a locally saved PDF | SwiftUI

I receive a String from a WebApi representing a Base64 PDF.
I implement this method to convert that Base64 String into a PDF and save it on documents.
/**
Saves Base64 to PDF
taken from: https://stackoverflow.com/a/40164036/15860448
*/
func saveBase64StringToPDF(_ base64String: String, fileName: String) -> URL? {
Logger.log(.warning, "Saving PDF...")
guard
var documentsURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last,
let convertedData = Data(base64Encoded: base64String)
else {
//handle error when getting documents URL
Logger.log(.error, "Error creating URL of PDF")
return nil
}
//name your file however you prefer
documentsURL.appendPathComponent("\(fileName).pdf")
do {
try convertedData.write(to: documentsURL)
//if you want to get a quick output of where your
//file was saved from the simulator on your machine
//just print the documentsURL and go there in Finder
Logger.log(.success, "Saved \(fileName) in \(documentsURL)")
return documentsURL
} catch {
//handle write error here
Logger.log(.success, "Error saving")
return nil
}
}
Now my goal is to open that File using the URL returned by saveBase64StringToPDF()
I have this method:
/**
Opens file
*/
func openFile(path: URL) {
if UIApplication.shared.canOpenURL(path) {
UIApplication.shared.open(path, options: [:], completionHandler: nil)
}
else{
Logger.log(.error, "Error opening URL: \(path)")
}
}
But I keep getting this error:
2022-03-03 14:34:39.271338+0100 LotoUp[7021:2647489] -canOpenURL: failed for URL: "file:///var/mobile/Containers/Data/Application/7D2DC4E8-90A7-4741-A730-CE039894FC88/Documents/liquidacion_2022-7_148.pdf" - error: "This app is not allowed to query for scheme file"
Any help?

Alamofire Decodable serializer

I am trying to update some code for a Alamofire custom response serializer I found this bit of code on "bits of cocoa".
extension Alamofire.Request {
public func responseCollection<T: Decodable>(completionHandler: Response<[T], NSError> -> Void) -> Self {
let responseSerializer = ResponseSerializer<[T], NSError> { request, response, data, error in
guard error == nil else { return .Failure(error!) }
let result = Alamofire
.Request
.JSONResponseSerializer(options: .AllowFragments)
.serializeResponse(request, response, data, error)
switch result {
case .Success(let value):
do {
return .Success(try [T].decode(value))
} catch {
return .Failure(Error.errorWithCode(.JSONSerializationFailed,
failureReason: "JSON parsing error, JSON: \(value)"))
}
case .Failure(let error): return.Failure(error)
}
}
return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
}
}
This is pre swift 3, and Response<[T], NSError> is now a single value specialization Response<[T]> because of this I am not sure how this extension would translate for the changes to Alamofire on the swift 3
I started to update this code this is as far as I got
extension Alamofire.Request {
public func responseCollection<T: Decodable>(completionHandler: (Response<[T]>) -> Void) -> Self {
let responseSerializer = ResponseSerializer<[T]> { request, response, data, error in
guard error == nil else { return .failure(error!) }
let result = Alamofire
.Request
.JSONResponseSerializer(options: .allowFragments)
.serializeResponse(request, response, data, error)
switch result {
case .success(let value):
do {
return .success(try [T].decode(value))
} catch {
return .failure(Error(.errorWithCode(.JSONSerializationFailed, failureReason: "JSON parsing error, JSON: \(value)")))
}
case .failure(let error): return.failure(error)
}
}
return response(responseSerializer: responseSerializer, com
pletionHandler: completionHandler)
}
}
this get me 2 errors that at the moment I have not found any way to fix them:
1) for "return .failure(Error(.errorWithCode(.JSONSerializationFailed, failureReason: "JSON parsing error, JSON: \(value)")))", I am getting this error ('Error' cannot be constructed because it as no accessible initializers)
2) for "return response(responseSerializer: responseSerializer, completionHandler: completionHandler)", I am getting this error (Cannot call value of non-function type 'HTTPURLResponse')
Hopefully if any one can point me to a better solution then this bit of code or the correct fix for this. Thanks I will be working on this still, if I do fix it I will update this ticket.
Edit - update
So This is the code as of now
extension Alamofire.Request {
public func responseDecodable<T: Decodable>(completionHandler: #escaping (Response<T>) -> Void) -> Self {
let responseSerializer = ResponseSerializer<T> { request, response, data, error in
guard error == nil else {
print("error Network request: \(error)")
return .failure(error!)
}
let result = Alamofire
.Request
.JSONResponseSerializer(options: .allowFragments)
.serializeResponse(request, response, data, error)
switch result {
case .success(let value):
do {
let decodableObject = try T.decode(value)
return .success(decodableObject)
} catch let decodeErr {
print(decodeErr)
let failureReason = "JSON parsing error, JSON: \(value)"
let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason]
let error = NSError(domain: "com.prospects.error", code: BackendError.JSONSerializationFailed.rawValue, userInfo: userInfo)
return .failure(error)
}
case .failure(let error): return.failure(error)
}
}
return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
}
}
public protocol ResponseObjectSerializable {
init?(response: HTTPURLResponse, representation: AnyObject)
}
as per last comment : Response and ResponseSerializer are now unresolved, this used to work with no error yesterday. but updating xcode and alamofire this morning as made this to get errors now.

Best practice to safely load image from url

I have the following code snippet to load an image from an url:
let url = NSURL(string: imageUrl)
let data = NSData(contentsOfURL: url!)
let image = UIImage(data: data!)
In case that my variable imageUrl has a valid string value, what is the most secure way to protect this code against possible edge cases?
Following code seems not to be very handy:
if let url = NSURL(string: imageUrl) {
if let data = NSData(contentsOfURL: url) {
if let image = UIImage(data: data) {
// success -> do something with the image...
}
else {
// print error message
}
}
else {
// print error message
}
}
else {
// print error message
}
The best practice is not to use a synchronous method like contentsOfURL to load data from over the network.
The recommended way is NSURLSession which works asynchronously.
This is a simple example with a completion block and an enum with associated types,
it catches all possible errors
enum Result {
case Success(UIImage), Failure(NSString)
}
func loadImage(string : String, completion: (Result) -> ()) {
guard let url = NSURL(string: string) else {
completion(.Failure("Bad URL"))
return
}
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
if error != nil {
completion(.Failure(error!.localizedDescription))
} else {
guard let image = UIImage(data: data!) else {
completion(.Failure("Could not load image data"))
return
}
completion(.Success(image))
}
}.resume()
}
Call it with:
loadImage("http://myserver.com/path/to/image.png") { result in
switch result {
case .Success(let image) :
// do something with the image
case .Failure(let error) :
print(error)
}
}

Parse Cloud Code query not getting executed

I have the below cloud code function and when I call this function from my OS X app, I get the success response as well. But none of the console log output messages inside the success and failure blocks of the query operation gets executed. Any ideas on where to look would be much appreciated.
Parse.Cloud.define("markAlertAsExpired", function(request, response) {
Parse.Cloud.useMasterKey();
var Alert = Parse.Object.extend("Alert");
var query = new Parse.Query(Alert);
query.get("vC6ppoxuqd", {
success: function(alertObj) {
// The object was retrieved successfully.
var status = alertObj.get("status");
console.log("RECEIVED OBJECT WITH STATUS:");
console.log(status);
if (status == "active") {
console.log("active");
markActiveAlertAsExpired(alertObj);
} else if (status == "inactive") {
console.log("inactive");
markInactiveAlertAsExpired(alertObj);
} else {
console.error("unknown_status");
}
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
console.error("alert_not_found");
response.error("alert_not_found");
}
});
response.success("available");
});
You need to wait for your queries to complete before calling response.success, the updated code below should work.
Parse.Cloud.define("markAlertAsExpired", function(request, response) {
Parse.Cloud.useMasterKey();
var Alert = Parse.Object.extend("Alert");
var query = new Parse.Query(Alert);
query.get("vC6ppoxuqd", {
success: function(alertObj) {
// The object was retrieved successfully.
var status = alertObj.get("status");
console.log("RECEIVED OBJECT WITH STATUS:");
console.log(status);
if (status == "active") {
console.log("active");
markActiveAlertAsExpired(alertObj);
} else if (status == "inactive") {
console.log("inactive");
markInactiveAlertAsExpired(alertObj);
} else {
console.error("unknown_status");
}
response.success("available");
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
console.error("alert_not_found");
response.error("alert_not_found");
}
});
});

Location Manager Crashing when No Internet

The program runs fine when the user is connected to the internet. However, when the user is not connected, the app crashes with:
Error:The operation couldn’t be completed. (kCLErrorDomain error 8.)
fatal error: unexpectedly found nil while unwrapping an Optional value
I'd like the catch the error before it crashes and display an alertcontroller
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: { (placemarks, error) -> Void in
if (error != nil) {
println("Error:" + error.localizedDescription)
}
if placemarks.count > 0 {
let pm = placemarks[0] as CLPlacemark
self.displayLocationInfo(pm)
currentLoc = manager.location
currentLocGeoPoint = PFGeoPoint(location:currentLoc)
var query = PFQuery(className:"Restaurant") //default: Restaurant
query.whereKey("RestaurantLoc", nearGeoPoint:currentLocGeoPoint, withinMiles:setDistanceMiles) //filter by miles
query.limit = 1000 //limit number of results
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if objects.isEmpty {
//NO RESULTS
let alertController = UIAlertController(title: "Unavailable Area", message:
"This app is not available in your area yet. We'll try our best to have it up and running as soon as possible.", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
self.navigationController!.popViewControllerAnimated(true)
} else {
newArray = objects
}
self.hideActivityIndicator(self.view)
}
} else {
println("error: \(error)")
}
})
}
The problem is your if statement. You are saying this:
if (error != nil) {
println("Error:" + error.localizedDescription)
}
if placemarks.count > 0 { // ...
Well, there was an error. And you were told that there was an error. But you didn't listen! You didn't stop! You just go right on as if nothing had happened, and try to access the placemarks variable - which wasn't returned. You need to use logic here so that you exit if there's an error:
if (error != nil) {
println("Error:" + error.localizedDescription)
return // go no further!
}
if placemarks.count > 0 { // ...
Note, however, that it would be better to check placemarks for nil first:
if placemarks == nil {
// check error
// return
}
if placemarks.count > 0 { // ...
I believe you need to implement locationManager:didFailWithError which tells the delegate when it is unable to retrieve the location. Then, you just need to handle the error with appropriate response.
For references: CLLocationManagerDelegate apple docs