I'm using facebook-api to fetch user's friends. The code is as follows:
let params = ["fields": "id"]
let request = FBSDKGraphRequest(graphPath: "me/friends", parameters: params)
request.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error != nil {
let errorMessage = error.localizedDescription
print(errorMessage)
/* Handle error */
}
else if result.isKindOfClass(NSDictionary){
/* handle response */
let defaults = NSUserDefaults.standardUserDefaults()
let resultdict = result as! NSDictionary
let data : NSArray = resultdict.objectForKey("data") as! NSArray
for i in 0..<data.count {
let valueDict : NSDictionary = data[i] as! NSDictionary
let id = valueDict.objectForKey("id") as! String
print("the id value is \(id)")
}
let friends = resultdict.objectForKey("data") as! NSArray
print("Found \(friends.count) friends")
print(friends)
defaults.setObject(friends, forKey: "fb_friends")
defaults.synchronize()
}
}
The resultDict contains:
{
data = (
{
id = 1662200084096651;
}
);
paging = {
cursors = {
after = QVFIUmFsa0JGazI4amNEcFczT0NRQzdiNshusdsDSHFDHFDDSm02UzNudV9ZATS1ESk5iUEQ5T2syNGDSw4yegdxbdf4WGZA3;
before = QVFIUmFsa0JGazI4amNEcFczT0NRQzdiNURGQTgdsgdsHFDSHTRTNU9DSm02UzNudV9ZATS1ESk5iUEQ5T2syNkRjQW8xc1drGgdsGREHRTcXE4WGZA3;
};
};
summary = {
"total_count" = 762;
};
}
The print above prints (for 1 fb friend):
(
{
id = 1020XXXXXX305XXX;
}
)
I want to pass this to my server, so I thought about doing:
var emptyParams = ["":""]
emptyParams["friends"] = (defaults.objectForKey("fb_friends") as! NSArray).componentsJoinedByString(",")
but then instead of params:
friends: 1020XXXXXX305XXX
I have:
"friends": {
id = 10206503694305180;
}
I want to skip the id and send it as an array, because on my server I have:
var friends = req.body.friends;
for(var i=0; i<friends.length; i++) {
console.log(friends[i]);
query = query.or([{ 'fb_friend': friends[i] }]);
}
how should my modify my swift code so that it creates a correct request?
From what I understand of your code, fb_friends have type of [[String:String]] and you want convert it to [String]?
You can use .map to get "id" from the dictionary.
let friends = (defaults.objectForKey("fb_friends") as! NSArray)
.map{$0["id"]!}
.joinWithSeparator(",")
let params = [
"friends": friends
]
Related
I'm trying to parse the response object from an API call, but having some difficulty.
First, I parsed the returned JSON with following:
let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
if let result = responseObject["result"] {
print(result)
}
Then, when I log the result, following is what I get:
{
"_links" = {
next = "/api/3/action/datastore_search?limit=50&id=22f223e7-73f7-4842-935c-80a0ba5c3e5b&offset=50";
start = "/api/3/action/datastore_search?limit=50&id=22f223e7-73f7-4842-935c-80a0ba5c3e5b";
};
fields = (
{
id = "_id";
type = int;
},
{
id = package;
info = {
label = "";
notes = "Unique, normalized, name of dataset.
"type_override" = "";
};
type = text;
}
)
}
I tried parsing it again:
let finalResult = (try? JSONSerialization.jsonObject(with: result)) as? [String: Any]
But, I get the following error:
No exact matches in call to class method 'jsonObject'
Update
if let result = responseObject["result"] as? [String: Any] {
if let finalResult = result["records"] {
print(finalResult)
}
}
When I log this, I get the following:
(
{
"_id" = 186;
accessibility = 1;
completeness = "0.6899999999999999";
freshness = "0.5";
grade = Silver;
"grade_norm" = Silver;
metadata = "0.84";
package = "air-conditioned-and-cool-spaces-heat-relief-network";
"recorded_at" = "2019-12-17T20:24:09";
score = "0.78";
"score_norm" = "0.76";
usability = "0.86";
version = "v0.1.0";
},
{
"_id" = 187;
accessibility = 1;
completeness = 1;
freshness = 0;
grade = Bronze;
"grade_norm" = Bronze;
metadata = "0.25";
package = "air-conditioned-public-places-cooling-centres";
"recorded_at" = "2019-12-17T20:24:09";
score = "0.54";
"score_norm" = "0.31";
usability = "0.85";
version = "v0.1.0";
},
)
When I tried to iterate this:
for (key, value) in finalResult {
print("key", key)
print("value", value)
}
I get the following error:
Tuple pattern cannot match values of none-tuple type
Thanks to #OOPer, I was able to parse it as a dictionary:
if let result = responseObject["result"] as? [String: Any] {
if let finalResult = result["records"] as? [[String: Any]] {
finalResult.forEach { (catalogue) in
if let package = catalogue["package"] as? String {
}
}
}
}
I am trying to access items parsed in JSON from the iTunes API using Swift 3.0, but I am struggling to access the objects after they have been parsed. The objects are being parsed in this format:
{
resultCount = 50;
results = (
{
artistId = 70936;
artistName = "Johnny Cash";
artistViewUrl = "https://itunes.apple.com/us/artist/johnny-cash/id70936?uo=4";
artworkUrl100 = "http://is2.mzstatic.com/image/thumb/Music3/v4/13/ae/73/13ae735e-33d0-1480-f51b-4150d4a45696/source/100x100bb.jpg";
artworkUrl30 = "http://is2.mzstatic.com/image/thumb/Music3/v4/13/ae/73/13ae735e-33d0-1480-f51b-4150d4a45696/source/30x30bb.jpg";
artworkUrl60 = "http://is2.mzstatic.com/image/thumb/Music3/v4/13/ae/73/13ae735e-33d0-1480-f51b-4150d4a45696/source/60x60bb.jpg";
collectionCensoredName = "The Essential Johnny Cash";
collectionExplicitness = notExplicit;
collectionId = 251001680;
collectionName = "The Essential Johnny Cash";
collectionPrice = "14.99";
collectionViewUrl = "https://itunes.apple.com/us/album/ring-of-fire/id251001680?i=251002253&uo=4";
country = USA;
currency = USD;
discCount = 2;
discNumber = 1;
isStreamable = 1;
kind = song;
previewUrl = "http://a1144.phobos.apple.com/us/r1000/070/Music/b3/99/be/mzi.qvkhtgfg.aac.p.m4a";
primaryGenreName = Country;
releaseDate = "2002-02-12T08:00:00Z";
trackCensoredName = "Ring of Fire";
trackCount = 18;
trackExplicitness = notExplicit;
trackId = 251002253;
trackName = "Ring of Fire";
trackNumber = 15;
trackPrice = "1.29";
trackTimeMillis = 155707;
trackViewUrl = "https://itunes.apple.com/us/album/ring-of-fire/id251001680?i=251002253&uo=4";
wrapperType = track;
},
I want to be able to access the information from all 50 results, such as the artistName, for instance. This is my parsing function attempting to get the artistName and add it to my NSDictionary, but it keeps returning that it can't unwrap the dictionary.
func parser() {
let enteredText:String = (tbxSearch.text?.replacingOccurrences(of: " ", with: "+"))!
let url = "https://itunes.apple.com/search?term=\(enteredText)"
print(url)
guard let urlRequest = URL(string: url) else
{
print("Error creating endpoint")
return
}
let request = URLRequest(url: urlRequest)
URLSession.shared.dataTask(with: request) {(data,response,error) in
do
{
guard let data = data else
{
return
}
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary else
{
return
}
if let results = json["results"] as? NSDictionary
{
self.avObjects.avDict.setValue("Artist Name", forKey: results["artistName"] as! String)
print(self.avObjects.avDict)
}
else
{
print("Couldn't unwrap the dictionary.")
}
print(json)
}
catch let error as NSError
{
print(error.debugDescription)
}
}.resume()
}
It looks like results is an array of dictionaries, not just a dictionary.
Instead of this: if let results = json["results"] as? NSDictionary
try this: if let results = json["results"] as? NSArray
You could then map or iterate over each element in the array, extracting "artistName" from each one, for example.
results is an array of dictionaries, not a dictionary itself. Try changing this:
if let results = json["results"] as? NSDictionary
to:
if let results = json["results"] as? NSArray
and then iterating over results. Each element of results is a dictionary with attributes such as artistName.
I am trying to get all my taggable_friends profil picture in swift. With my code, I can obtain my taggable_friends' name, but I don't know how I can get their profil picture... Any idea how? Thanks!!!
var fbRequest = FBSDKGraphRequest(graphPath:"/me/taggable_friends", parameters: nil);
fbRequest.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
var resultdict = result as! NSDictionary
var data : NSArray = resultdict.objectForKey("data") as! NSArray
for i in 0..<data.count {
let valueDict : NSDictionary = data[i] as! NSDictionary
let id = valueDict.objectForKey("id") as! String
let name = valueDict.objectForKey("name") as! String
// let url = valueDict.objectForKey("url") as! String -- is not working
I already saw this topic: How can I retrieve friend's picture through FBRequest in swift but I still don't undersand how to do it...
Not sure if this is the most effective way to do this, but the code works:
func returnUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me/taggable_friends?", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
println("fetched user: \(result)")
var resultdict = result as! NSDictionary
var data : NSArray = resultdict.objectForKey("data") as! NSArray
for i in 0..<data.count {
let valueDict : NSDictionary = data[i] as! NSDictionary
let id = valueDict.objectForKey("id") as! String
let name = valueDict.objectForKey("name") as! String
let pictureDict = valueDict.objectForKey("picture") as! NSDictionary
let pictureData = pictureDict.objectForKey("data") as! NSDictionary
let pictureURL = pictureData.objectForKey("url") as! String
println("Name: \(name) URL: \(pictureURL)")
}
}
})
}
Have a look at
https://developers.facebook.com/docs/graph-api/reference/user-taggable-friend/
The request should be something like this
graphPath:"/me/taggable_friends?fields=id,name,picture"
I'm having a problem with passing data in an multidimensional array.
So this is the Array:
var dataHome:[[String]] = []
And I would like to pass data into it like this:
if let countries_list = json as? NSArray
{
for (var i = 0; i < countries_list.count ; i++ )
{
if let country_obj = countries_list[i] as? NSDictionary
{
println(country_obj)
let countryName = country_obj["country"] as! String
let countryCode = country_obj["code"] as! String
var tempArray:[String] = []
tempArray.append(countryName)
tempArray.append(countryCode)
println(tempArray)
dataHome.append(tempArray)
println(dataHome)
}
}
}
It crashes when I try to pass data into dataHome.append(tempArray)
The array from country_obj is {code = US;country = Amerika;}
Does anybody have an solution ?
Thank's !
EDIT:
the whole function is:
func extract_json(data:NSString){
var parseError: NSError?
let jsonData:NSData = data.dataUsingEncoding(NSASCIIStringEncoding)!
let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &parseError)
if (parseError == nil)
{
if let countries_list = json as? NSArray
{
for (var i = 0; i < countries_list.count ; i++ )
{
if let country_obj = countries_list[i] as? NSDictionary
{
println(country_obj)
var countryName = country_obj["country"] as! String
var countryCode = country_obj["code"] as! String
println(countryName)
println(countryCode)
var tempArray:[String] = []
tempArray.append(countryName)
tempArray.append(countryCode)
println(tempArray)
dataHome.append(tempArray)
println(dataHome)
}
}
}
}
do_table_refresh();
}
The error is: Thread 3: Breakpoint 2.1
tempArray.append(countryName)
In Swift how do you parse the result of a fbk graph request? I have a nested dictionary and casting to [String: String] does not work. I have casted to NSDictionary which works for level 1 but anything nested started complaining about optionals and casting. I see from the changeling that FBGraphObject has been deprecated, so what is the correct approach now in SDK 4?
My data looks like
{
data = {
"is_silhouette" = 0;
url = "...";
};
}
I can do
var data = photoRes["data"] as? NSDictionary
to get
Optional({
"is_silhouette" = 0;
url = "...;
})
I'm not sure how to parse that object...
EDIT For now I have it working with
var data = photoRes["data"] as? NSDictionary
var urlStr = data!["url"] as? String
if urlStr != nil {
let url = NSURL(fileURLWithPath: urlStr!)
//my code...
}
But this is a complicated approach especially if the result coming back is highly nested. Is there a better way to go about this?
Create a dictionary :
class ViewController: UIViewController {
var dict : NSDictionary!
}
Fetching the data :
if((FBSDKAccessToken.currentAccessToken()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler({ (connection, result, error) -> Void in
if (error == nil){
self.dict = result as NSDictionary
println(self.dict)
NSLog(self.dict.objectForKey("picture")?.objectForKey("data")?.objectForKey("url") as String)
}
})
}
Output should be :
{
email = "ashishkakkad8#gmail.com";
"first_name" = Ashish;
id = 910855688971343;
"last_name" = Kakkad;
name = "Ashish Kakkad";
picture = {
data = {
"is_silhouette" = 0;
url = "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfa1/v/t1.0-1/s200x200/22501_915701971820048_9046303472199214595_n.jpg?oh=f3b3564f1450c13332b3067a135cad5d&oe=55C71792&__gda__=1443571904_c4667dcb08d85682edfd77a90ee9c3ab";
};
};
}
2015-05-25 22:12:34.015 SwiftFB[2713:7830] https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfa1/v/t1.0-1/s200x200/22501_915701971820048_9046303472199214595_n.jpg?oh=f3b3564f1450c13332b3067a135cad5d&oe=55C71792&__gda__=1443571904_c4667dcb08d85682edfd77a90ee9c3ab
This mess worked for me. I am using SWIFT 3.01 and FB Swift SDK
if let responseDictionary = response.dictionaryValue {
print(responseDictionary["name"] ?? "")
let a = responseDictionary["picture"] as! NSDictionary
let b = a["data"] as! NSDictionary
let c = b["url"]
print(c ?? "")