execute put item request - AWS DynamoDB ios SDK - ios

Looked all over SO and through Amazon's docs as well, but couldn't find any solid documentation on how to make a put request using iOS SDK, specifically using Swift.
I gather that I need to instantiate an AWSDynamoDBClient first (https://aws.amazon.com/articles/7439603059327617) but don't see that appear as a type when I'm working in xcode.
I've honestly only got two lines of code after all this struggle:
var myDynamoDBPutRequest:AWSDynamoDBPutRequest = AWSDynamoDBPutRequest()
myDynamoDBPutRequest.item = ["fbid": "test"]
I can't figure out how to run it, and doubt that request is set up properly anyway. I've also looked at PutItemInputs, but not sure how that differs from putRequest.item. If anyone can just point me in the right direction I'll be happy to investigate on my own - I'm just running out of places to look for good documentation :/
EDIT:
I've made a bit of progress, but still can't figure out how to properly create a put item input . Here is the code I have now:
var myPutItemInput:AWSDynamoDBPutItemInput = AWSDynamoDBPutItemInput()
myPutItemInput.tableName = "mytable"
var myDynamoDB = AWSDynamoDB.defaultDynamoDB()
myDynamoDB.putItem(myPutItemInput).continueWithBlock { (task:BFTask!) -> AnyObject! in
if(task.result != nil){
let myPutOutput = task.result as AWSDynamoDBPutItemOutput
println(task.result)
}else{
println("task.result was nil for put item request")
}
return nil
}//end put item task
right now I at least figured out how to execute the request, but the result is nil each time.

Here is an example of - putItem:
let dynamoDB = AWSDynamoDB.defaultDynamoDB()
let putItemInput = AWSDynamoDBPutItemInput()
putItemInput.tableName = "testTableName"
let hashValue = AWSDynamoDBAttributeValue()
hashValue.S = "testPutItem"
let stringValue = AWSDynamoDBAttributeValue()
stringValue.S = "stringValue";
putItemInput.item = [
"hashKey" : hashValue,
"stringKey" : stringValue
]
dynamoDB.putItem(putItemInput).continueWithBlock { (task:AWSTask?) -> AnyObject? in
if(task.error != nil) {
println(task.error)
}
if (task.result != nil) {
let putItemOutput = task.result as AWSDynamoDBPutItemOutput
println(putItemOutput)
}
return nil
}
Even though it's in Objective-C, looking at the integration tests may help understand how to use Amazon DynamoDB with the AWS Mobile SDK for iOS v2.

Related

Fetching list of things in things group or things from AWS IoT

I need list of things in group or list of things from AWS with that I tried to find solution from AWSIoT Reference So i have used below code to get it. Previously i used to get it using normal API call from our backend service but i need fully use with AWS.
func initializeAWS() {
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:AWS_REGION,
identityPoolId:IDENTITY_POOL_ID)
initializeControlPlane(credentialsProvider: credentialsProvider)
}
func initializeControlPlane(credentialsProvider: AWSCredentialsProvider) {
let controlPlaneServiceConfiguration = AWSServiceConfiguration(region:AWS_REGION, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = controlPlaneServiceConfiguration
iot = AWSIoT.default()
let request = AWSIoTListThingsInThingGroupRequest()
request?.thingGroupName = "XXXGroupName"
let output = iot.listThings(inThingGroup: request!)
print("output is \(output.result)")
print("error is \(output.error)")
}
I have used here AWSIoT & AWSIoTListThingsInThingGroupRequest object to get list of things may i know is this right way to fetch ? if it is I'm output and error both objects getting nil.
I tried to find solution for the AWS IOT example from Github, I didnt get anything relevant answer to this. Or is there anything in iotDataManager that will give list of things ? Please can you help me on this ? For more info I have raised question on AWS Github Fetching list of things in things group
I've checked log level output was getting, All configurations as well was right only thing i wasn't aware about is how to get response of things, the way to get things is as below.
let credentialsProvider = AWSCognitoCredentialsProvider(regionType:AWS_REGION,
identityPoolId:IDENTITY_POOL_ID)
let controlPlaneServiceConfiguration = AWSServiceConfiguration(region:AWS_REGION, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = controlPlaneServiceConfiguration
iot = AWSIoT.default()
let request = AWSIoTListThingsInThingGroupRequest()
request?.thingGroupName = "XXXGroupName"
let output = iot.listThings(inThingGroup: request!)
output.continueOnSuccessWith { (response) -> Any? in
if let result = response.result, let things = result.things {
self.awsDevices = things
completionHandler(true)
}
return self.awsDevices
}

aws dynamodb how to use object mapper with batch get in ios swift

Thanks in advance for any help. I am trying to get Batch items (Load multiple) items from one DynamoDb table using the AWS iOS SDK (Swift). I can load one item using the Block syntax, but I need to load 10 or more than that. I don't want to use 10 Block calls to load them individually. I tried to follow the attach stackoverflow Link (where the similar solution is given) but I am getting the following compiler error message. I come from Java background, hence could also be a syntax issue. Is it the right way to load multiple items? I don't want to use low level API. Any help, where I am going wrong. Thanks.
aws dynamodb how to use object mapper with batch get in ios
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
var tasksList = Array<AWSTask<AnyObject>>()
for i in 1...10 {
tasksList.append(dynamoDBObjectMapper.load(AWSCards.self, hashKey: "SH_"+String(i), rangeKey: nil))
}
AWSTask.init(forCompletionOfAllTasksWithResults: tasksList).continueWithBlock { (task) -> AnyObject? in
if let cards = task.result as? [AWSCards] {
print(cards.count)
}
else if let error = task.error {
print(error.localizedDescription)
}
return nil
}
Have a try with the following codes (Swift 4.1, Feb 9th, 2018):
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
var tasksList = Array<AWSTask<AnyObject>>()
for i in 1...10 {
tasksList.append(dynamoDBObjectMapper.load(AWSCards.self, hashKey: "SH_"+String(i), rangeKey: nil))
}
AWSTask<AnyObject>.init(forCompletionOfAllTasksWithResults: tasksList).continueWith { (task) -> Any? in
if let cards = task.result as? [AWSCards] {
print(cards.count)
}
else if let error = task.error {
print(error.localizedDescription)
}
return nil
}
Your question is "how to use the object mapper" but it might be more efficient for you to not use it.
However, there is a way to use it. See Niklas's answer here and here (he copy & pasted), but something about it strikes me as fishy. I want to make the assertion that it is not as fast as the built-in batch-get function, but I am unsure. I suspect that this does not complete the items in parallel, or at least not as efficiently as in BatchGetItem.
See the docs: "In order to minimize response latency, BatchGetItem retrieves items in parallel."
According to Yosuke, "Currently, AWSDynamoDBObjectMapper does not support the batch get item. You need to load one item at a time if you want to use the object mapper" as of 2016. This still seems to be the case. I am using a version a couple versions behind, but not too far behind. Someone check.
In conclusion, if you are loading one item at a time, you are likely missing out on the whole purpose of BatchGetItem (low latency).
Pulling from various sources, including John Davis's question here, I have tested and ran this BatchGetItem result. Here ya go.
import AWSDynamoDB
let primaryKeyToSortKeyDict : [String : String] = .... // Your stuff
var keys = [Any]()
for key in primaryKeyToSortKeyDict.keys {
let partitionKeyValue = AWSDynamoDBAttributeValue()
partitionKeyValue?.s = String(key)
let sortValue = AWSDynamoDBAttributeValue()
sortValue?.s = String(primaryKeyToSortKeyDict[key]!)
keys.append(["partitionKeyAttributeName": partitionKeyValue, "sortKeyAttributeName": sortValue])
}
let keysAndAttributesMap = AWSDynamoDBKeysAndAttributes()
keysAndAttributesMap?.keys = keys as? [[String : AWSDynamoDBAttributeValue]]
keysAndAttributesMap?.consistentRead = true
let tableMap = [table : keysAndAttributesMap]
let request = AWSDynamoDBBatchGetItemInput()
request?.requestItems = tableMap as? [String : AWSDynamoDBKeysAndAttributes]
request?.returnConsumedCapacity = AWSDynamoDBReturnConsumedCapacity.total
guard request != nil else {
print("Handle some error")
return
}
AWSDynamoDB.default().batchGetItem(request!) { (output, error) in
print("Here is the batchgetitem output")
if error == nil {
// do output stuff
} else {
// handle error
}
}

aws dynamodb how to use object mapper with batch get in ios

I need to get ~50 items with their primary keys from dynamodb using ios sdk. i am able to get the items by AWSDynamoDB.defaultDynamoDB().batchGetItem but couldn't figure out if it is possible to use object mapper with the response. Unfortunately objectmapper class in ios doesn't have batchGet function. As far as i know i cant use query in this situation.
Is it possible to use object mapper? If not which one makes more sense: parsing the response to get the desired class instance or calling objectMapper.load on each item?
Currently, AWSDynamoDBObjectMapper does not support the batch get item. You need to load one item at a time if you want to use the object mapper.
I solved it by doing this,
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
let task1 = dynamoDBObjectMapper.load(User.self, hashKey: "rtP1oQ5DJG", rangeKey: nil)
let task2 = dynamoDBObjectMapper.load(User.self, hashKey: "dbqb1zyUq1", rangeKey: nil)
AWSTask.init(forCompletionOfAllTasksWithResults: [task1, task2]).continueWithBlock { (task) -> AnyObject? in
if let users = task.result as? [User] {
print(users.count)
print(users[0].firstName)
print(users[1].firstName)
}
else if let error = task.error {
print(error.localizedDescription)
}
return nil
}

Checking metadata of Amazon S3 file using iOS AWS SDK in Swift

I am using the AWS iOS SDK v2, and Swift 1.2.
I am storing my app's app.json file on S3 and want to check it at launch to see if it's been updated since the last run. According to research, simply doing a HEAD request on the object should return the "Last-Modified" attribute which can then be compared to the previous.
The problem is that doing a HEAD request on an Object doesn't really seem to be well documented. I've got the following:
var metaDataRequest = AWSS3HeadObjectRequest()
metaDataRequest.bucket = S3BucketName
metaDataRequest.key = S3AppJSONKey
This seems like a decent start, however I cannot find a way to execute the request. The AWSS3TransferManager has a download() method, but the method requires an AWSS3TransferManagerDownloadRequest type, which an AWSS3HeadObjectRequest cannot be cast as.
Not sure where to go from here, short of just doing the request outside of the SDK. I did, however, want to leverage as much of the SDK as possible, so if this is possible I would love to know how.
You need to use AWSS3 (instead of AWSS3TransferManager) to call - headObject:.
You need to call headobject method of AWSS3
var request = AWSS3HeadObjectRequest()
request.bucket = "flkasdhflhad"
request.key = "hfsdahfjkhadjkshf"
request.ifModifiedSince = NSDate()
var s3 = AWSS3.defaultS3()
s3.headObject(request) { ( output1 : AWSS3HeadObjectOutput?, error : NSError?) -> Void in
print( output1?.description())
}
if your object is modified from specified date then it will return u the object otherwise it will return u the status code 304.
You can use following Swift 2.2 method to check if file exist or not
func checkIfFileExist() {
let s3 = AWSS3.defaultS3()
let headObjectsRequest = AWSS3HeadObjectRequest()
headObjectsRequest.bucket = "YourBucketName" //Don't add "/" at end of your bucket Name
headObjectsRequest.key = "YourFileNameYouWantToCheckFor" //Don't add "/" in start of file name
s3.headObject(headObjectsRequest).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Error to find file: \(error)")
} else {
print("fileExist")
}
}
}
Note: Example to set bucket and key
suppose you have bucket named "ABC" and than folder named "XYZ" and than inside "XYZ" you have file "abc123"
than write
headObjectsRequest.bucket = "ABC/XYZ"
and
headObjectsRequest.key = "abc123"
and if you want to check for the entire folder
than use
headObjectsRequest.bucket = "ABC/XYZ"
and
headObjectsRequest.key = ""
Thanks Mohsin

Swift Parse: can not retrieve the value of a bool in _User class

I am developing an app using swift and Parse. For some reasons I have implemented a Bool named "modified" in the _User class. I have been playing around with swift and Parse for a few months but this just does not make sense.
When I try to retrieve the value of the "modified" Bool I keep on getting "false" value even though it is set on "true" on Parse server. Here is the code:
var modified: Bool = PFUser.currentUser().objectForKey("modified") as! Bool
println("User Modified Bool is set to: \(modified)")
I have also tried with
self.modified = PFUser.currentUser().valueForKey("modified") as! Bool
println("User Modified Bool is set to: \(modified)")
and
self.modified = PFUser.currentUser()["modified"] as! Bool
println("User Modified Bool is set to: \(modified)")
Do I have to make a specific query or is there a way to access this value directly?
Edit
I have implemented a specific query. Still get a "false" value though
var queryMainUser: PFQuery = PFUser.query()
queryMainUser.whereKey("username", equalTo: PFUser.currentUser().username)
queryMainUser.findObjectsInBackgroundWithBlock { (mainUsersObjects, mainUsersError) -> Void in
if (mainUsersError == nil) {
var theRef = mainUsersObjects[0] as! PFObject
self.modified = theRef["modified"] as! Bool
println("Any improvement? \(self.modified)")
}
}
Edit 2
Following #danh advices, I tried updating the currentuser instance on the device by implementing this code:
var currentUser = PFUser.currentUser()
currentUser.fetchInBackgroundWithBlock { (object, error) -> Void in
println("Refreshed")
currentUser.fetchIfNeededInBackgroundWithBlock { (result, error) -> Void in
self.modified = currentUser.objectForKey("modified") as! Bool
var idOfUser: String = currentUser.objectId
println("User \(idOfUser) UPDATED")
println(self.modified)
if self.modified == true {
self.deleteData()
self.fetchAllObjects()
}
}
}
When running the console gives me this:
Refreshed
User xTbBw6cNzK UPDATED
false
Here is a screenshot I just took of the server side:
Thank you all for your attention
I am not sure what version of swift you are using. But if you are using Swift 2.0 and Xcode 7, this SHOULD do the job.
This will not work:
let modifiedStatus = PFUser.currentUser()?["modified"] // return value will be nil
This will work for sure:
let modifiedStatus = PFUser.currentUser()?.objectForKey("modified")
print(modifiedStatus) // true as per your table
I know this may sound strange, but some I struggle with something for hours later realising my silly mistake. So it is always good to move back of the current task and later recheck after few hours. So just make sure you cross check the following:
The key "modified" in the main user class of parse
You can retrieve other key values (just to see if nothing else is wrong other than your current retrieving of a key bool value(
Though I am on Swift 2.0, but for sure there is no major change from in this specific code when it comes to move from Swift 1.2 to Swift 2.0.
Just see and if it still doesn't work, we can discuss more on your setup.
I have initialised a "doneSetUp" var as a local variable, it is an int.
then I query the user which just logged in
checks if it exists...
check if the variable userDidSetUp exists in parse and if it does I am converting it to an int and assign it to the local variable doneSetUp I made
then I am using the "doneSetUp" variable which now has a value of 0(false) or 1(true) to decide if the user already setup his account or not and then segue the user to the correct view controller.
mention that all of this code is inside of my logininbackgroundwithblock function.
I hope that helped.
query?.getObjectInBackgroundWithId(user!.objectId!, block: {
(user, error) -> Void in
if let user = user{
if var userDidSetUp: AnyObject = user["doneSetUp"] {
self.doneSetUp = userDidSetUp as! Int
if self.doneSetUp == 0 {
self.performSegueWithIdentifier("procceedToSetup", sender: self)
}else{
self.performSegueWithIdentifier("procceedToApp", sender: self)
}
}
}
})
I know it's an old post, but here's what worked for me.
This is inside the viewDidLoad method.
PFUser.currentUser()?.fetchInBackgroundWithBlock({ (object, error) -> Void in
var modified = PFUser.currentUser()?.objectForKey("modified")?.boolValue
if modified == true {
print(modified) // Output console displays "true"
Hope this helps.

Resources