I'm trying to put AnyObject value to NSString and print it but unfortunatlly it is always crashing without showing the reason just EXC. After debugging I found it is crashing after currStr. So please where would be my issue?
var lastRefresh: AnyObject = self.currDic["Response"]!.objectForKey("Datasource")!
self.currStr = lastRefresh as NSString
println("Data: \(self.curreStr)")
My lastRefresh output:
{
Cookie = 0nss1w45xzuocyqgvrjcmr31;
Message = "\U0130\U015flem Ba\U015farl\U0131";
Response = {
Datasource = (
{
Content = "";
Date = "20.01.2015";
Time = "08:32:22";
Title = "Example1";
},
{
Content = "";
Date = "20.01.2015";
Time = "08:32:22";
Title = "Example2";
},
From your comments It's clear that, you need to convert the lastRefresh object to NSData for using it in NSXMLParser.
From your NSLog it looks like a Dictionary or Array. You can convert it to data using:
var yourData : NSData = NSJSONSerialization.dataWithJSONObject(lastRefresh, options: NSJSONWritingOptions.PrettyPrinted, error: nil)!
Related
In my apple watch interface controller "reply" object contains Json response in NSDictionary. Here is my response i need the "accountName" from this below response. How to parse it in Swift programming.
[Accounts: (
{
accountName = "ABCD";
idNumber = 114000093;
email = "xyz#gmail.com";
index = 0;
nickName = "Suites";
},
{
accountName = "EFGH";
idNumber = 114000094;
email = "abc#gmail.com";
index = 1;
nickName = "Sultan";
}
)]
I have tried like below:
WKInterfaceController.openParentApplication(["request" : "GetData"], reply: { (reply, error) -> Void in
println(reply)
self.accountNames = reply["Accounts"] as? NSMutableArray
println(self.accountNames)
This is very easy, you can try out by your own, and can google also, there are lots and lots of example available, you just need to brush up little bit.
Btw, You can try like this,
let accountArray : NSArray = reply.objectForKey("Accounts") as! NSArray
let accountDic : NSDictionary = accountArray.objectAtIndex(0) as! NSDictionary
let accountName : NSString = accountDic.valueForKey("accountName") as! NSString
Hope, this helps you.
Try this :
let accountInfos = (reply.valueForKey("Accounts") as [NSDictionary]).map {
YourModelClass(accountName: $0["accountName"] as String, idNumber: $0["idNumber"] as String ..... same for all other)
}
self.yourMutableArray.addObjectsFromArray(accountInfos)
let accountName = (yourMutableArray.objectAtIndex(0)as YourModelClass).accountName
println(accountName)
And your model class :
class YourModelClass : NSObject {
var accountName : String?
.
.
init(accountName:String, ......) {
self.accountName = accountName
}
I can perform a simple Get request on a singular table within AWS dynamoDB however when I expand it to a Batch Request across multiple tables I continue to get a error
validation error detected: Value null at 'requestItems.rip.member.keys' failed to satisfy constraint
I understand this as the values not being passed correctly but I can't see what the issue is with my code
//Create Request Values
AWSDynamoDBGetItemInput *getItem = [AWSDynamoDBGetItemInput new];
AWSDynamoDBAttributeValue *hashValue = [AWSDynamoDBAttributeValue new];
hashValue.S = #"User Test";
getItem.key = #{#"ripId": hashValue};
//Create Request Values 2
AWSDynamoDBGetItemInput *getItem2 = [AWSDynamoDBGetItemInput new];
AWSDynamoDBAttributeValue *hashValue2 = [AWSDynamoDBAttributeValue new];
hashValue2.S = #"User Test";
getItem2.key = #{#"chat": hashValue2};
//Combine to Batch Request
AWSDynamoDBBatchGetItemInput * batchFetch = [AWSDynamoDBBatchGetItemInput new];
batchFetch.requestItems = #{ #"rip": getItem,
#"chat": getItem,};
[[dynamoDB batchGetItem:batchFetch] continueWithBlock:^id(BFTask *task) {
if (!task.error) {
NSLog(#"BOY SUCCES");
} else {
NSLog(#" NO BOY SUCCESS %#",task.error);
}
return nil;
}];
Searched the internet high and low but cannot see a working example of a batch request using iOS Objective C (or swift for that matter).
I have tested both variables on a single Get request and they both work.
You forgot to wrap around AWSDynamoDBAttributeValue in AWSDynamoDBKeysAndAttributes. Here is a simple example from AWSDynamoDBTests.m:
AWSDynamoDBKeysAndAttributes *keysAndAttributes = [AWSDynamoDBKeysAndAttributes new];
keysAndAttributes.keys = #[#{#"hashKey" : attributeValue1},
#{#"hashKey" : attributeValue2}];
keysAndAttributes.consistentRead = #YES;
AWSDynamoDBBatchGetItemInput *batchGetItemInput = [AWSDynamoDBBatchGetItemInput new];
batchGetItemInput.requestItems = #{table1Name: keysAndAttributes};
Since the batch get doesn't map to a class I solved it by doing this instead.
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
}
Swift 3
I was able to get the BatchGet request work with the following code. Hope this helps someone else who's struggling with the lack of Swift Docs.
This code assumes that you've configured your AWSServiceConfiguration in the AppDelegate application didFinishLaunchingWithOptions method.
let DynamoDB = AWSDynamoDB.default()
// define your primary hash keys
let hashAttribute1 = AWSDynamoDBAttributeValue()
hashAttribute1?.s = "NDlFRTdDODEtQzNCOC00QUI5LUFFMzUtRkIyNTJFNERFOTBF"
let hashAttribute2 = AWSDynamoDBAttributeValue()
hashAttribute2?.s = "MjVCNzU3MUQtMEM0NC00NEJELTk5M0YtRTM0QjVDQ0Q1NjlF"
let keys: Array = [["userID": hashAttribute1], ["userID": hashAttribute2]]
let keysAndAttributesMap = AWSDynamoDBKeysAndAttributes()
keysAndAttributesMap?.keys = keys as? [[String : AWSDynamoDBAttributeValue]]
keysAndAttributesMap?.consistentRead = true
let tableMap = ["Your-Table-Name" : keysAndAttributesMap]
let request = AWSDynamoDBBatchGetItemInput()
request?.requestItems = tableMap as? [String : AWSDynamoDBKeysAndAttributes]
request?.returnConsumedCapacity = AWSDynamoDBReturnConsumedCapacity.total
DynamoDB.batchGetItem(request!) { (output, error) in
if output != nil {
print("Batch Query output?.responses?.count:", output!.responses!)
}
if error != nil {
print("Batch Query error:", error!)
}
}
I am trying to access the 'address' object (String) in a dictionary:
Chain.sharedInstance().getAddress("19b7ZG3KVXSmAJDX2WXzXhWejs5WS412EZ"){ dictionary, error in
NSLog("%#", dictionary)
let value = dictionary["address"] as? String //returns nil
}
this is the data I receive:
results = (
{
address = 19b7ZG3KVXSmAJDX2WXzXhWejs5WS412EZ;
confirmed = {
balance = 0;
received = 20000000;
sent = 20000000;
};
total = {
balance = 0;
received = 20000000;
sent = 20000000;
};
}
); }
How do I access the values in this dictionary when I keep getting nil?
To clarify, the data you are posting is not JSON, but rather looks like JSONP. You aren't showing any code deserializing the the object, so I assume Chain.sharedInstance().getAddress is handling that aspect. If this is an instance of the Bitcoin API, you might look at their documentation. If it is their API, the documentation says the return is
A dictionary with a single "results" key, whose value is a array
containing a single Address Object as a dictionary.
If that is the case if would be
if let resultsArray = dictionary["results"] as NSArray {
if let dict = results[0] as NSDictionary {
//dict["address"] should have your address
}
}
Try:
if let dict = dictionary["results"] as NSDictionary
{
let value = dict["address"] as NSString
}
or:
if let dict = dictionary["results"] as NSArray
{
if let di = dict[0] as NSDictionary
{
let value = di["address"] as NSString
}
}
Both the hash and range are specified, yet it thinks one is empty? Or is it talking about some other attribute?
The task.result() that is returned is nil, and task.error() says:
"Error Domain=com.amazonaws.AWSDynamoDBErrorDomain Code=0 "Supplied
AttributeValue is empty, must contain exactly one of the supported
datatypes" UserInfo=0x7ff3c0e21d40 {NSLocalizedDescription=Supplied
AttributeValue is empty, must contain exactly one of the supported
datatypes}"
I am sure that the hash and range names are correct, and so is the table name.
Writing in Swift, here is my code:
var venueIdAttribute = AWSDynamoDBAttributeValue()
venueIdAttribute.N = "2164156"
var venueIdCondition = AWSDynamoDBCondition()
venueIdCondition.comparisonOperator = .EQ // Hash Key must always be Equals
venueIdCondition.attributeValueList = [venueIdAttribute]
var startDateAttribute = AWSDynamoDBAttributeValue()
var startString = String(format:"%1.0f", lastSyncDate.timeIntervalSince1970 * 1000)
startDateAttribute.N = String(format:"%1.0f", lastSyncDate.timeIntervalSince1970 * 1000)
var dateCondition = AWSDynamoDBCondition()
dateCondition.comparisonOperator = .GT
dateCondition.attributeValueList = [startDateAttribute];
var keysArray : NSArray = [["venueId" : venueIdCondition, "dateInterval" : dateCondition]]
var keysAndAttributes : AWSDynamoDBKeysAndAttributes = AWSDynamoDBKeysAndAttributes()
keysAndAttributes.keys = keysArray;
var requestMap : NSDictionary = ["myTableName":keysAndAttributes]
var request : AWSDynamoDBBatchGetItemInput = AWSDynamoDBBatchGetItemInput()
request.requestItems = requestMap
var response : BFTask = dynamoDB.batchGetItem(request) // This is synchronous
keysArray is not formatted correctly in the code snippet. You are creating a NSString : AWSDynamoDBCondition dictionary, but it needs to be NSString : AWSDynamoDBAttributeValue dictionary. The following reference may help understand how to format the BatchGetItem request.
BatchGetItem
KeysAndAttributes
AWSDynamoDBKeysAndAttributes
I have this json result.
I would take the field "alert".
I try this:
var alert: NSString = jsonResult["features"]["properties"]["alert"]
but this is the error: does not have a member named 'subscript'.
I can not how to access a field in a nested dictionary
{
features = (
{
geometry = {
coordinates = (
"-97.95359999999999",
"37.2382",
5
);
type = Point;
};
id = usb000si7g;
properties = {
alert = green;
cdi = "5.8";
code = b000si7g;
detail = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/usb000si7g.geojson";
dmin = "0.017";
felt = 1258;
gap = 38;
ids = ",usb000si7g,";
mag = "4.3";
magType = mwr;
mmi = "4.94";
net = us;
nst = "<null>";
place = "8km SE of Harper, Kansas";
rms = "0.51";
sig = 864;
sources = ",us,";
status = reviewed;
time = 1412272884590;
title = "M 4.3 - 8km SE of Harper, Kansas";
tsunami = "<null>";
type = earthquake;
types = ",cap,dyfi,general-link,geoserve,losspager,moment-tensor,nearby-cities,origin,phase-data,shakemap,tectonic-summary,";
tz = "-300";
updated = 1412614943519;
url = "http://earthquake.usgs.gov/earthquakes/eventpage/usb000si7g";
};
type = Feature;
}
);
metadata = {
api = "1.0.13";
count = 1;
generated = 1412617232000;
status = 200;
title = "USGS Significant Earthquakes, Past Week";
url = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_week.geojson";
};
type = FeatureCollection;
}
I don't know what to do. swift is changed every beta.
As #Kirsteins said is his answer, you have to do a lot of unwrapping, and it's recommended to use a JSON library.
If you still want to stick with hand made extraction, then I suggest you to made it programmatically, such as adding an extension to NSDictionary as follows:
extension NSDictionary {
func objectForTreeKeys<T>(keys:[String]) -> T? {
var dict: NSDictionary? = self
var retValue: T?
for key in keys {
var value: AnyObject? = dict?.objectForKey(key)
if let unwrapped = value as? NSDictionary {
dict = unwrapped
} else if let unwrapped = value as? T {
retValue = unwrapped
break
} else {
retValue = nil
break
}
}
return retValue
}
}
You pass an array of keys to the function, and it traverses all nested dictionaries until:
a value of type T is encountered
a value having type different than NSDictionary and T is found
a nil value is found
In the first case, it returns the value of T type - in the other cases it returns nil.
You can use it as follows:
let ret: String? = jsonResult.objectForTreeKeys(["features", "properties", "alert"])
As you can see, it's a generic method, and the return type is inferred from the type of the variable the result is assigned to - so it's necessary to explicitly define its type, which must be optional (String? in this specific case).