Parsing GraphQL failure() result in Swift - ios

I am relatively new to Swift and am having trouble parsing the result of a GraphQL API call.
I see the result within the 'failure()' declaration is of the type NSError and I'm basically trying to access it if it is a 'failure' and then access the NSError keys. The result is:
failure(Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSUnderlyingError=0x282232700 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x280e54b40 [0x1faa4fcf0]>{length = 16, capacity = 16, bytes = 0x1002005036d7fb9f0000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=http://staging.mysite.com/api/, NSErrorFailingURLKey=http://staging.mysite.com/api/v2/, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-4, NSLocalizedDescription=The network connection was lost.})
I get the below information by using:
print("\(result)")
Result is an object of type Result<GraphQLResult<Data>, Error>. There are methods to get errors but this result apparently isn't thrown as a GraphQL Error. The error catch I'm using is:
if let firstError = try? result.get().errors?.first {
completion([], [], firstError)
return
}
It passes this check so it is just interpreting it as a normal data result. My question is how do I parse this information?
My thinking is that I need to check if it is a failure, then unwrap it from the 'failure' type and then can treat the enclosed info as an NSError object. I can't use 'contains' since it's not a String. There is a get() method on result that allows you to result.get().data or result.get().error but neither return anything in this case.
Any help on how I can parse this information would be greatly appreciated. Thanks!

Result is a generic swift enumeration, which has two states: success or failure.
To get the error from the failure one must use a switch statement, for eg:
switch result {
case .failure(let error):
//Handle error here
default:
break
}
More on the Result enumeration here: https://developer.apple.com/documentation/swift/result.

Related

Error trapping Swift Google upload to Firebase code

We are writing an iOS app that uploads data to Google Firebase storage. We use the code below to upload text data to the location we specify. It works fine, except when we are not connected to the internet.
For the case of not being connected to the internet, we are having trouble trapping and handling the error. As far as we can tell, the delegate is never called (MyFirebaseProtocol_UploadTextComplete doesn't fire until much later, perhaps after a timeout) , and it just tries to upload repeatedly. If we are connected to the Mac and watching the debug window, it continuously generates errors in a loop, indefinitely. These certainly look like they are intended to be trappable (class names like NSErrorFailingURLStringKey, and helpful error messages and codes), but so far we are unable to trap them as they occur.
We are relatively new at swift, but is there some syntax, something like exception handling, that will allow us to trap and handle these errors, rather than just loop indefinitely?
Thanks!
func UploadTextFile(filepath : String, text: String, delegate : MyFirebaseProtocol)
{
let storage = Storage.storage()
let storageRef = storage.reference()
let textfileref = storageRef.child(filepath)
let data: Data? = text.data(using: .utf8)
textfileref.putData(data!, metadata: nil)
{
(metadata, error) in
delegate.MyFirebaseProtocol_UploadTextComplete(error: error)
}
}
Error messages in Xcode debug window:
2022-01-20 15:15:38.553528-0500 GarmentTest[431:60410] Connection 1: received failure notification
2022-01-20 15:15:38.553552-0500 GarmentTest[431:60410] Connection 1: failed to connect 1:50, reason -1
2022-01-20 15:15:38.553564-0500 GarmentTest[431:60410] Connection 1: encountered error(1:50)
2022-01-20 15:15:38.555426-0500 GarmentTest[431:60410] Connection 2: received failure notification
2022-01-20 15:15:38.555442-0500 GarmentTest[431:60410] Connection 2: failed to connect 1:50, reason -1
2022-01-20 15:15:38.555452-0500 GarmentTest[431:60410] Connection 2: encountered error(1:50)
2022-01-20 15:15:38.557057-0500 GarmentTest[431:60410] Task .<1> HTTP load failed, 0/0 bytes (error code: -1009 [1:50])
2022-01-20 15:15:38.557104-0500 GarmentTest[431:60410] Task <1D0E3033-5A15-4435-AF3D-99A06EAB4C3C>.<2> HTTP load failed, 0/0 bytes (error code: -1009 [1:50])
2022-01-20 15:15:38.557485-0500 GarmentTest[431:60410] Connection 3: received failure notification
2022-01-20 15:15:38.557544-0500 GarmentTest[431:60410] Connection 3: failed to connect 1:50, reason -1
2022-01-20 15:15:38.557664-0500 GarmentTest[431:60410] Connection 3: encountered error(1:50)
2022-01-20 15:15:38.558844-0500 GarmentTest[431:60268] Task .<1> finished with error [-1009] Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_kCFStreamErrorCodeKey=50, NSUnderlyingError=0x280374a80 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<1>"
), NSLocalizedDescription=The Internet connection appears to be offline., NSErrorFailingURLStringKey=https://firebasestorage.googleapis.com/v0/b/garmenttest-8897e.appspot.com/o/Snapshots%2FAn%2FAn_20220120_151528_Relaxed_Center_Image_1B.png?uploadType=resumable&name=Snapshots%2FAn%2FAn_20220120_151528_Relaxed_Center_Image_1B.png, NSErrorFailingURLKey=https://firebasestorage.googleapis.com/v0/b/garmenttest-8897e.appspot.com/o/Snapshots%2FAn%2FAn_20220120_151528_Relaxed_Center_Image_1B.png?uploadType=resumable&name=Snapshots%2FAn%2FAn_20220120_151528_Relaxed_Center_Image_1B.png, _kCFStreamErrorDomainKey=1}

URLSession dataTask returns with no error and no data, causing SwiftyStoreKit.ReceiptError error 1

Why would the following code cause URLSession to return nil for both data and error?
let task = URLSession.shared.dataTask(with: storeRequest as URLRequest) { data, _, error -> Void in
// there is an error
if let networkError = error {
print("There was a network error")
return
}
// there is no data
guard let safeData = data else {
print("No network error, but no data either")
return
}
...
On running this code, one user hits the No network error, but no data either line.
According to Apple's docs on URLSession.dataTask:
If the request completes successfully, the data parameter of the
completion handler block contains the resource data, and the error
parameter is nil. If the request fails, the data parameter is nil and
the error parameter contain information about the failure.
I read that as: either data or error should always be non-nil. But that doesn't seem to be happening here. In what situation would both be nil?
(It if helps - the URL in question is the iTunes receipt validation API at https://buy.itunes.apple.com/verifyReceipt and the affected users are the reviewers at Apple, who are generally unwilling to assist in debug. This code is actually part of SwiftyStoreKit and it causes the error SwiftyStoreKit.ReceiptError error 1 for the reviewer - but never for anyone else.)
This could possibly depend on the HTTPURLResponse that you are ignoring in the completion handler of the dataTask (documentation for URLSession.dataTask indicates that the response, while of type URLResponse, is actually of type HTTPURLResponse - so it would have a statusCode property that would be helpful to understand the result of your request..
The request may very well have been successful, but with no data returned (ie a 204 No Content response or a 300 Redirect response). These would not have a data response, but would also not have an error response, as the request did not fail.

Alamofire downloading multiple images using swift 3

I currently have a an array of strings that contain about three thousand urls to download images. I have set up the following function to the pass the array of urls into:
func downloadAllImages(urlArray:[String])->Void{
var urlArray = urlArray
let destination = DownloadRequest.suggestedDownloadDestination(for: .documentDirectory)
var TotalProducts = urlArray.count
for i in 0 ..< urlArray.count {
Alamofire.download(
urlArray[i],
method: .get,
to: destination).downloadProgress(closure: { (progress) in
self.IndividualImage.text="\(progress.fractionCompleted*100)%"
}).response(completionHandler: { (DefaultDownloadResponse) in
TotalProducts-=1
self.DownloadLabel.text="Images left to download: \(TotalProducts)"
print("\(DefaultDownloadResponse.error)")
print("\(DefaultDownloadResponse.response)")
})
}
}
This works fine except it tends to cut out after downloading between 800-900 images and just stops. It outputs no errors. As I'm looping through every url and creating a task I imagine there are only so many concurrent tasks I can have at once. Any ideas?
UPDATE
I have gone through the output responses and found many are timing out:
Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x60800145b840 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=www.MYURL.com/image1.jpg, NSErrorFailingURLKey=www.MYURL.com/image1.jpg, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.})
So this is obvious as the for loop is sending everything to a task at once virtually and then it can only process so many at once. So the answer is to send them in batches. But how would I send a batch of 50 and then wait till every task has completed and then send another wave?

iOS Office365 send message 400 error

Using the Office365 iOS library I want to implement the send message functionality.
The code below, by running the sample code returns an error:
NSURLSessionDataTask* task = [[[client getMe] getOperations] sendMail:message :true :^(int returnValue, MSODataException *error) {
NSLog(#"Error: %#", error);
[task resume]; }];
Error Domain=Error in the Request Code=400 "The operation couldn’t be completed. (Error in the Request error 400.)" UserInfo=0x7cb3eee0 {error={
code = ErrorInvalidRequest;
message = "Cannot read the request body.";}}
Does anyone know a fix for this? It could be caused by a wrong sent payload message?
That error does indicate a problem with the request payload. The common case is a missing Content-Type header. Can you capture a network trace and confirm? Also make sure you're using the latest release of that library.

iOS GCDAsyncSocket Error: Domain=NSPOSIXErrorDomain Code=57

This is a weird one. I'm using GCDAsyncSocket and when I'm using the iOS simulator sometimes I can connect and send, no problem but sometimes when I try to connect and send something (writeData) I get the following error:
didDisconnect Error Domain=NSPOSIXErrorDomain Code=57 "The operation couldn’t be completed. Socket is not connected"
What is odd, I cannot predict when this will happen. Also when I check to see isConnected, that returns true.
Here is the code (SWIFT):
var sendBytes:[Byte] = [0x0, 0x1, 0x2, 0x3]
var msgData = NSData(bytes: sendBytes, length: sendBytes.count)
socket.writeData(msgData, withTimeout: -1.0, tag: 0)
socket.readDataWithTimeout(-1.0, tag: 0)
The socket(didConnectToHost) callback fired with no issues and correct address and port returned, but when I try the above code to writeData to socket, I get the above error.
Any ideas why this would be happening randomly.

Resources