Closed motivus closed 5 years ago
Hello @motivus
Sorry about the confusion you are having when using AWSTask
. Here is a stackoverflow post which gives an example of how to use it for asynchronous jobs:
https://stackoverflow.com/questions/44688027/what-is-the-proper-way-to-work-with-awstask-objects-in-swift
As a summary-
the task
object has two properties: result
and error
and they are mutually exclusive. When a task completes successfully, the task.result
will have the response of the API. If its an error, task.error
will be set. You have to use these properties in the completion handler.
Please let us know if you have more questions.
Thanks, Rohan
Regarding your summary of AWSTask
and the task
object... I do understand that. I'm trying to print result
(because a result IS returned after my call to calcGet
), but I don't know how to. So, I'm afraid this might be a dumb Swift question from yours truly.
The stackoverflow post is helpful in terms of showing how result
and error
are what's returned in calls to various AWS services. But in my case, I'm calling API Gateway, and Cloudwatch tells me my REST API call was a success. I can see that the Lambda function is returning the proper values as JSON. My REST API is passthrough on the response. So, I presume printing result
should show me the response from Lambda.
Basically, I'm expecting result
to have the properties sent back from the Lambda call; namely, the operands, the operator, and the result. How do I access them?
Note: I added my own question on this topic at stackoverflow: https://stackoverflow.com/questions/55542718/what-is-the-proper-way-to-work-with-api-gateway-awstask-objects-in-swift
I am seriously (and embarrassedly) at a standstill here... in fact, I've been stuck for 2 months now since trying to make the switch from using AWS for javascript-based web apps to attempting the same for iOS / mobile apps.
@motivus - What happens when you do this?
if let JSONDictionary = task.result as? NSDictionary {
print("Result: \(JSONDictionary)")
print("resultKey: \(JSONDictionary["resultKey"])")
}
Thanks @muellerfr - I'm afraid nothing prints out. But here's what happens:
Firstly, Xcode gives me the following error if I don't put a question mark after task
in the first line:
Value of optional type 'AWSTask<Empty>?' must be unwrapped to refer to
member 'result' of wrapped base type 'AWSTask<Empty>'
Chain the optional using '?' to access member 'result' only for non-'nil' base values... |Fix|
Choosing 'Fix' results in this change:
if let JSONDictionary = task?.result as? NSDictionary {
Having made that correction, I then get the following warning:
Cast from 'Empty?' to unrelated type 'NSDictionary' always fails
I get the following warning for the print("resultKey...")
line with two options to Fix:
String interpolation produces a debug description for an optional value; did you
mean to make this explicit?
Use 'String(describing:)' to silence this warning... |Fix|
Provide a default value to avoid this warning... |Fix|
I left the two warnings and built the project anyway. Clicking my 'Invoke API' button in the Simulator, I'm afraid nothing prints out.
Here is a screenshot from Xcode:
And here is a screenshot of my Simulator window.. just so you can see how I'm invoking.
Please try removing the ?
after AWSTask
in line 83, and then comment out line 84 - 93. Now remove the ?
after task
in line 95.
What do you see?
I get the same (fatal) warning message as before, unfortunately.
Here's a screenshot showing the same messages with the altered code:
This isn't really a Swift/ObjC interoperability issue, it's that the task's result type is an Empty
, rather than whatever result type your API is defining. Your API Gateway-generated code for client.calcGet
should have a response type based on the model you've assigned in your API Gateway setup. If you've not set up a response type in the resource, then the response would be Empty
, as you see here.
In the calc tutorial you reference, there is the following note:
By default, the method response body is assigned an empty model. This will cause the integration response body to be passed through without mapping. However, when you generate an SDK for one of the strongly-type languages, such as Java or Objective-C, your SDK users will receive an empty object as the result. To ensure that both the REST client and SDK clients receive the desired result, you must model the response data using a predefined schema. Here you'll define a model for the method response body and to construct a mapping template to translate the integration response body into the method response body.
I think that may be what's causing your issue. Can you ensure you've followed these steps, re-generate and re-integrate the SDK, and see if that solves your issue?
Thanks @palpatim. Interesting. It was my expectation that the task's result property would be an Empty
because that is what the API is defined to return. And I remember reading that section you highlighted several times to make sure "I was doing it right." I was thinking Swift at the time, not Obj-C. But now I see that I likely need to specifically model the response back to the Client so that an Empty
is not what's returned.
I will look into doing this and report back. I very much appreciate your calling that to my attention!!
State your question I'm having trouble figuring out how to access
result
when using the sample code provided in the SDK README.md.result
is derived fromtask
, which is of typeAWSTask
. Presumably AWSTask comes from the AWSCore library, but I'm afraid I'm new enough to Swift and the iOS SDK that I'm a bit lost. Would you kindly help me understand which AWSTask and how to access my Lambda response?Which AWS Services are you utilizing? API Gateway, Lambda
Provide code snippets (if applicable) Here's my code that invokes my REST API, which is based on the "calc" REST API featured in the API Gateway documentation. This is pretty much what is in the README.md:
Now, I've verified that the REST API is being successfully called and it is returning the correct result to the Client. Obviously, all I'm doing here is to print the address of
result
. I'm struggling to understand how to access the "properties" ofresult
, which I would expect to bea
,b
(for the operands),op
(for the operator), andc
for the result.This is what I see when I set a breakpoint on the print statement:
I've actually posted a full treatment of my problem to the Swift subreddit if you'd like to see more detail.
Environment(please complete the following information):
Device Information (please complete the following information):
If you need help with understanding how to implement something in particular then we suggest that you first look into our developer guide. You can also simplify your process of creating an application, as well as the associated backend setup by using the Amplify CLI.