Fetch all fitness data at once - ios

From the official Facebook docs you can get simple statement that you can fetch 3 types of fitness activities:
fitness.bikes
fitness.walks
fitness.runs
That's great but they all share the same fields and there's no possibility to distiguish which one was fetched besides the graphPath.
I need all of this data and ideally I want to fetch it all at once but if I create a method like this:
let walkRequest = FBSDKGraphRequest(graphPath: "me/fitness.walks", parameters: nil)
let runRequest = FBSDKGraphRequest(graphPath: "me/fitness.runs", parameters: nil)
let bikeRequest = FBSDKGraphRequest(graphPath: "me/fitness.bikes", parameters: nil)
var connection = FBSDKGraphRequestConnection()
connection.addRequest(walkRequest) { (connection, result, error) -> Void
//
}
connection.addRequest(runRequest) { (connection, result, error) -> Void
//
}
connection.addRequest(bikeRequest) { (connection, result, error) -> Void
//
}
connection.start()
I get three different callbacs, returning same data and somehow I have to merge this into one structure so I can send it to the backend.
I'd like to get a Dictionary with structure similiar to this:
[
"walks": [ JSON ],
"runs": [JSON],
"bikes": [ JSON ]
]
Is it possible to create a batched request like this? Or do I have to do it manually with 3 different FBSDKGraphRequests and just wait for them to finish?

You should be able to do this via the so-called field expansion:
GET /me?fields=fitness.bikes,fitness.walks,fitness.runs
As I unfortunately have no such data in my account, I can't test the result, but the query runs smoothly.

Related

Nested syntax to use on Facebook Graph API request

I want to receive a larger profile picture than the standard 50px one that returns.
I can receive email etc no problem, but how do I pass fields to indicate that I want a larger profile picture. I am clear that you can pass nested parameters to picture to return a larger one, but I cannot find information on how to write this when dealing with the Facebook iOS SDK.
extension LoginManagerLoginResult {
func graphData() {
let params = ["fields": "first_name, last_name, email, picture{height: 1000}"]
let graphRequest = GraphRequest(
graphPath: "me",
parameters: params,
tokenString: self.token!.tokenString,
version: nil,
httpMethod: .get
)
graphRequest.start { graph, any, error in
debugPrint(any)
debugPrint(error)
debugPrint(graph)
}
}
}
I had the syntax wrong. To get pictures off different sizes you can pass fields like below:
let params = ["fields": "first_name, last_name, email, picture.width(1000)"]
You can also pass:
picture.type(large)
or:
picture.height(300)
Or other height values as required.

Get insights/page_fans for a Facebook page from Facebook's open graph

I'm trying to get the number of fans that a music artist has on their Facebook page, but it's not working. I've combed through the FBAPI docs as well as SO and still nothing. Here's my code:
func getHolychildInfo() {
//Make request
let newGraphRequest: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "/holychildmusic/insights/page_fans", parameters: ["period" : "lifetime", "show_description_from_api_doc" : "true", "fields": "read_insights"], httpMethod: "GET")
newGraphRequest.start(completionHandler: { (connection, result, error) in
if ((error) != nil) {
print("Holychild error getting insights: \(error.debugDescription)")
} else {
print("\nHolychild insights result:\n\n\(result)")
}
})
}
Here's my result:
data = (
);
paging = {
next = "https://graph.facebook.com/v2.8/holychildmusic/insights/page_fans?access_token=EAAIB5k3aWEEBAHBD9lZC5AAzZAVV8K8CGBfqaxcrLdZA7oZB2Gdar8cQphXj4VciloZAnZBKp5ZA59BmGloSNz847nFqZCTVsYZCl9rrOk88OnfCnDwwADKnkOO5EUhGumEbW96riHplgfBLdnZAEYmB2Qz4ZAH1sWbuftmGKDqPft4l5QAHSZAimIyI6sOHaKWiurRK201Af6NQCXGliZBsZAUYosUHttkUbo4CQZD&fields=read_insights&format=json&include_headers=false&period=lifetime&sdk=ios&show_description_from_api_doc=true&since=1487457711&until=1487716911";
previous = "https://graph.facebook.com/v2.8/holychildmusic/insights/page_fans?access_token=EAAIB5k3aWEEBAHBD9lZC5AAzZAVV8K8CGBfqaxcrLdZA7oZB2Gdar8cQphXj4VciloZAnZBKp5ZA59BmGloSNz847nFqZCTVsYZCl9rrOk88OnfCnDwwADKnkOO5EUhGumEbW96riHplgfBLdnZAEYmB2Qz4ZAH1sWbuftmGKDqPft4l5QAHSZAimIyI6sOHaKWiurRK201Af6NQCXGliZBsZAUYosUHttkUbo4CQZD&fields=read_insights&format=json&include_headers=false&period=lifetime&sdk=ios&show_description_from_api_doc=true&since=1486939311&until=1487198511";
};
As you can see, there is nothing in the "data" part of the response. The "page_fans" insights metric is supposed to return a number - among other things - but instead returns nothing.
All insights metrics besides the two public ones (page_fans_country and page_storytellers_by_country) require admin access to the page (admin user or page access token with read_insights permission.)
But the fan_count field of the page object is public, so just request that:
https://developers.facebook.com/tools/explorer/?method=GET&path=holychildmusic%3Ffields%3Dfan_count&version=v2.8

Facebook Graph API mutual friends images

I'm able to retrieve users' mutual friends using context.fields(mutual_friends)but I need to display images of the friends. However, I'm only getting back the friends id and name only. Is it possible to retrieve their images in the same call?
if((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "/\(userID)", parameters: ["fields": "context.fields(mutual_friends)"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
print("//////Mutual friends")
print(result!)
} else {
print(error!.localizedDescription)
}
})
}
You can get the image with using this API
https://graph.facebook.com/(friendFacebookId)/picture?type=large
For more info check this

Post on Facebook/ twitter in background in Swift

Can anyone recommend me any swift library to post on facebook and twiiter.
I am trying this for now
if FBSDKAccessToken.currentAccessToken().hasGranted("publish_actions")
{
print("publish actions already granted.")
}
else
{
FBSDKGraphRequest.init(graphPath: "me/feed", parameters: ["message" : "hello world"], HTTPMethod: "POST").startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error == nil))
{
print("Post id: \(result.valueForKey("id") as! String)")
}
})
}
There is a situation that when user creates an event then my app will automatically post/tweet on its wall about the event he just created.
I am fimiliar about swifter and Facebook SDK but i am not sure if it will help me post in background
How luschn said, you can't post automatically, but you can ask user if he want to post event.
For facebook post just use Facebook SDK(https://developers.facebook.com/docs/ios), you have there instruction for installation. You can use "Posting Data" from https://developers.facebook.com/docs/ios/graph, but you need first to check if user give you right to post it.
For Twitter post, apple give you a library(Social.framework) can help you for post on Twitter. You can learn how use it from http://code.tutsplus.com/tutorials/social-framework-fundamentals--mobile-14333. Also you can use this framework for facebook post.
guys i know i asked a silly question , but after upgrading my project to swift 2.0 and fb sdk 4.6 i did the posting
var params: NSDictionary = NSDictionary()
let userInfo: AnyObject = LocalStore.userDetails()!
let name = userInfo["name"] as? String
params = ["message": msgString]
let request: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "/me/feed", parameters: params as [NSObject: AnyObject], HTTPMethod: "POST")
request.startWithCompletionHandler({ (connection, result, error) -> Void in })
This way you can post any message in background... but do check for fb login and ask for publishPermission(loginWithPublishPermission).

How can I initialize an object with data from two separate Alamofire requests?

Im trying to make a GET request to Foursquare's Photos From a Venue and
Foursquare's Explore at the same time. Right now (correct me if I'm wrong) I have two methods to make the request via Alamofire and convert the response to a JSON object using SwiftyJSON.
I can successfully update the UITableViewCell's labels to reflect the data using makeRequest() below, but can't update the UIImage for the background photo of each respective cell.
My problem is A) getting a usable photo URL, and B) Initializing "pin" while providing data from two separate requests. In order to initialize pin, I need to set all of the values. Im geting 90% of the values from one request, and 10% (the photo URL that I need to get) from another request. How do I initialize "pin" with data from two separate requests?
makeImageRequest:
func makeImageRequest() {
let venueID = "43695300f964a5208c291fe3"
let firstURL = "https://api.foursquare.com/v2/venues/\(venueID)/photos"
Alamofire.request(.GET, firstURL, parameters: [
"client_id" : foursquareClientID,
"client_secret" : foursquareClientSecret,
"v" : "20140806",
"m" : "foursquare",
"limit" : "10"
])
.responseJSON { (request, response, data, error) in
println(request)
println(response)
println(error)
let jsonObj = JSON(data!)
self.pins = []
for obj in jsonObj["response"]["photos"]["items"].arrayValue {
let photoURL = obj["prefix"]["suffix"].stringValue
println("the photo url is\(photoURL)")
let pin = Pin(title: obj["venue"]["name"].stringValue, openUntil: obj["venue"]["hours"]["status"].stringValue, address: obj["venue"]["location"]["address"].stringValue, ratingSignals: obj["venue"]["ratingSignals"].stringValue, ratingImage: UIImage(named:"Score8-5")!, venueImage: UIImage(named: "FloraGrubTestImage.jpg")!)
self.pins.append(pin)
}
self.tableView.reloadData()
}
}
and makeRequest
func makeRequest(searchString: String) {
let secondURL = "https://api.foursquare.com/v2/venues/explore"
Alamofire.request(.GET, secondURL, parameters: [
"client_id" : foursquareClientID,
"client_secret" : foursquareClientSecret,
"ll" : "37.71987,-122.470089",
"query" : searchString,
"radius" : "1000",
"limit" : "10",
"v" : "20140806",
"m" : "foursquare"
])
.responseJSON { (request, response, data, error) in
println(request)
println(response)
println(error)
let jsonObj = JSON(data!)
self.pins = []
println(jsonObj)
for obj in jsonObj["response"]["groups"][0]["items"].arrayValue {
let pin = Pin(title: obj["venue"]["name"].stringValue, openUntil: obj["venue"]["hours"]["status"].stringValue, address: obj["venue"]["location"]["address"].stringValue, ratingSignals: obj["venue"]["ratingSignals"].stringValue, ratingImage: UIImage(named:"Score8-5")!, venueImage: UIImage(named: "FloraGrubTestImage.jpg")!)
self.pins.append(pin)
}
self.tableView.reloadData()
}
}
I have a separate bindData() method in my UITableViewCell class. Does this make sense? Can anyone help me?
UPDATE: An engineer I work with suggested that I make another request inside of the same method makeRequest and not bother with breaking it out into two separate methods. I also read a tutorial online that suggests a response router of some kind. Any suggestions on how I can refactor this code into one method?
UPDATE #2: I have renamed this question as I realize that the original question was not my real problem
The easiest way would be to execute these request serially. First retrieve all the pins, and then retrieve all the photos. This is essentially what the other engineer advised.
If you fire off these requests in parallel, it will require a extra work to merge the responses, since you don't know which request will return first.
Now to merge the pins you need a way to uniquely identify each pin. If they have some ID, you can use that. Otherwise you have to rely on the sort order and index. Assuming each request returns the same pins in the same order.
After the first request returns, you have an array of pins. Then in the second request callback you can retrieve the matching pin from this array and update it with the new data.

Resources