Facebook iOS SDK和Swift:如何获取用户的个人资料图片

28

我已经在 Xcode 6 中集成了 Facebook SDK(使用 Swift)。 在登录期间,我请求 public_profile 权限:

FBSession.openActiveSessionWithReadPermissions(["public_profile"], allowLoginUI: true, completionHandler: {
...
...

所以我请求用户的信息:

FBRequestConnection.startForMeWithCompletionHandler { (connection, user, error) -> Void in
...
...

为什么用户对象中不包含个人资料图片?如何获取用户个人资料图片?它不是public_profile的一部分吗?

我得到以下信息:

2015-01-25 01:25:18.858 Test[767:23804] {
"first_name" = xxx;
gender = xxx;
id = xxxxxxxxx;
"last_name" = xxxxxx;
link = "https://www.facebook.com/app_scoped_user_id/xxxxxxxxx/";
locale = "xxxxx";
name = "xxxxxxx xxxxxxx";
timezone = 1;
"updated_time" = "2013-12-21T18:45:29+0000";
verified = 1;
}

P.S:出于隐私考虑,xxx。


对于Xcode 8.3.3和Swift-4(beta)使用: https://stackoverflow.com/a/45462114/1168602 - Sachindra Pandey
10个回答

64

实际上,个人资料照片是公开的,您只需将用户ID添加到Facebook指定的个人资料照片URL地址即可,例如:

个人资料照片实际上是公开的,您只需通过将用户ID添加到Facebook指定的个人资料照片URL地址来访问,例如:

var userID = user["id"] as NSString     
var facebookProfileUrl = "http://graph.facebook.com/\(userID)/picture?type=large"

这个特定的URL地址应该返回用户个人资料图片的“大”版本,但是文档中还提供了其他几个照片选项在文档中


嗨。虽然有些晚了,但我可以问一下...这些照片选项在文档的哪里可以找到?我似乎在Graph API 2.4上找不到它们:https://developers.facebook.com/docs/graph-api/reference/v2.4/user/picture - Alejandro Iván
@AlejandroIván 我现在链接的文档页面上写着“此文档是针对过时版本的Graph API。请使用最新版本。Graph API版本v2.2”,所以也许在2.4中这些照片选项不再可用了。 - Lyndsey Scott
2
这正是我所想的。令人惊讶的是,即使没有“官方”文档,使用type=large或其他类型(我正在使用width=150&height=150)似乎也能正常工作。谢谢! - Alejandro Iván
1
这个答案指引了我正确的方向。所以为了完成我的函数,我加入了以下代码:if let data = NSData(contentsOfURL: facebookProfileUrl!) { imageProfile.image = UIImage(data: data) }谢谢 @LyndseyScott - Jorge Casariego
2
谢谢@LyndseyScott - 对于将来使用此功能的人,请不要忘记使用“https”而不是“http”,以消除苹果安全警告 :) - trdavidson
simple and sweet - Krutika Sonawala

53

如果你想在同一请求中获取图片和其他用户信息,可以通过一个图形请求来完成。虽然有点混乱,但比再次发出另一个请求要好。

一种更为Swift 3的方法

let request = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, email, picture.type(large)"])
let _ = request?.start(completionHandler: { (connection, result, error) in
    guard let userInfo = result as? [String: Any] else { return } //handle the error

    //The url is nested 3 layers deep into the result so it's pretty messy
    if let imageURL = ((userInfo["picture"] as? [String: Any])?["data"] as? [String: Any])?["url"] as? String {
        //Download image from imageURL
    }
})

Swift 2

let request = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, email, picture.type(large)"])
request.startWithCompletionHandler({ (connection, result, error) in
    let info = result as! NSDictionary
    if let imageURL = info.valueForKey("picture")?.valueForKey("data")?.valueForKey("url") as? String {
        //Download image from imageURL
    }
})

25

使用Facebook SDK 4.0,您可以使用:

Swift:

    let pictureRequest = FBSDKGraphRequest(graphPath: "me/picture?type=large&redirect=false", parameters: nil)
    pictureRequest.startWithCompletionHandler({
        (connection, result, error: NSError!) -> Void in
        if error == nil {
            println("\(result)")
        } else {
            println("\(error)")
        }
    })

Objective-C:

FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
                                  initWithGraphPath:[NSString stringWithFormat:@"me/picture?type=large&redirect=false"]
                                  parameters:nil
                                  HTTPMethod:@"GET"];
    [request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
                                          id result,
                                          NSError *error) {
    if (!error){
       NSLog(@"result: %@",result);}
    else {
       NSLog(@"result: %@",[error description]);
     }}];

这指引我正确地获取其他用户信息,参见:https://dev59.com/vV0Z5IYBdhLWcg3wiw_n - CularBytes
id/picture?type=normal&redirect=false 对我非常管用,谢谢。redirect=false 奇妙无比。 - Terry Bu

14

Swift 4方法:

private func fetchUserData() {
    let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"id, email, name, picture.width(480).height(480)"])
    graphRequest?.start(completionHandler: { (connection, result, error) in
        if error != nil {
            print("Error",error!.localizedDescription)

        }
        else{
            print(result!)
            let field = result! as? [String:Any]
            self.userNameLabel.text = field!["name"] as? String
            if let imageURL = ((field!["picture"] as? [String: Any])?["data"] as? [String: Any])?["url"] as? String {
                print(imageURL)
                let url = URL(string: imageURL)
                let data = NSData(contentsOf: url!)
                let image = UIImage(data: data! as Data)
                self.profileImageView.image = image
            }
        }
    })
}

你的if-else语句有误。应该是if error == nil,而且你还需要改变代码。 - emresancaktar
@emresancaktar 这是正确的。如果 error != nil,那么它会打印出错误信息。 - Sandeep Vishwakarma

7

如果您想获得更大的图片,只需将"type=large"替换为width=XX&height=XX

但您能得到的最大图片是原始图片。

FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] 
                              initWithGraphPath:@"me/picture?width=1080&height=1080&redirect=false" 
                              parameters:nil 
                              HTTPMethod:@"GET"]; 

[request startWithCompletionHandler:^(
                            FBSDKGraphRequestConnection *connection,
                            id result, 
                            NSError *error) { 
if (!error) 
{ 
   NSLog(@"result = %@",result);
   NSDictionary *dictionary = (NSDictionary *)result; 
   NSDictionary *data = [dictionary objectForKey:@"data"]; 
   NSString *photoUrl = (NSString *)[data objectForKey:@"url"]; 
} 
else 
{ 
   NSLog(@"result = %@",[error description]); } 
}];

4

@Brandon Gao的解决方案给了我一个200X200的缩略图... 为了获得更大的尺寸,我使用了FBSDKProfile来获取带有尺寸的路径,这也更加模块化而不是硬编码(虽然我确实需要输入graph.facebook.com部分...)

let size = CGSize(width: 1080, height: 1080)
let path = FBSDKProfile.currentProfile().imagePathForPictureMode(.Normal, size: size)
let url = "https://graph.facebook.com/\(path)"
Alamofire.request(.GET, url, parameters: nil, encoding: ParameterEncoding.URL).response { 
    (request, response, data, error) -> Void in
    if  let imageData = data as? NSData,
        let image = UIImage(data: imageData) {
            self.buttonImage.setImage(image, forState: .Normal)
    }
}

不知道为什么我没有得到一个1080X1080的图片,但是FB给了我一个1117X1117的... :\


1
不错的解决方案,但我需要先加载个人资料: FBSDKProfile.loadCurrentProfileWithCompletion - bbjay

4
对于Swift来说,这是获取具有特定大小的照片的URL的简单方法:
    let params: [NSObject : AnyObject] = ["redirect": false, "height": 800, "width": 800, "type": "large"]
    let pictureRequest = FBSDKGraphRequest(graphPath: "me/picture", parameters: params, HTTPMethod: "GET")
    pictureRequest.startWithCompletionHandler({
        (connection, result, error: NSError!) -> Void in
        if error == nil {
            print("\(result)")


           let dictionary = result as? NSDictionary
           let data = dictionary?.objectForKey("data")
           let urlPic = (data?.objectForKey("url"))! as! String
           print(urlPic)



        } else {
            print("\(error)")
        }
    })

}

3

针对Swift 5

首先添加所需的字段。

let params = ["fields": "first_name, last_name, email, picture"]

创建图形请求
let graphRequest = GraphRequest(graphPath: "me", parameters: params, tokenString: token.tokenString, version: nil, httpMethod: .get)
graphRequest.start { (connection, result, error) in }

您将会得到JSON格式的结果。
{
  "first_name": "",
  "last_name": "",
  "picture": {
    "data": {
      "height": 50,
      "is_silhouette": false,
      "url": "",
      "width": 50
    }
  },
  "id": ""
}

根据JSON响应,捕获结果。
if let error = error {
            print("Facebook graph request error: \(error)")
        } else {
            print("Facebook graph request successful!")
            guard let json = result as? NSDictionary else { return }
            if let id = json["id"] as? String {
                print("\(id)")
            }
            if let email = json["email"] as? String {
                print("\(email)")
            }
            if let firstName = json["first_name"] as? String {
                print("\(firstName)")
            }
            if let lastName = json["last_name"] as? String {
                print("\(lastName)")
            }
            if let profilePicObj = json["picture"] as? [String:Any] {
                if let profilePicData = profilePicObj["data"] as? [String:Any] {
                    print("\(profilePicData)")
                    if let profilePic = profilePicData["url"] as? String {
                        print("\(profilePic)")
                    }
                }
            }
        }
    }

您可以通过在参数中发送所需的宽度来获取定制宽度的个人资料图片。
let params = ["fields": "first_name, last_name, email, picture.width(480)"]

这是整个代码的样子。
if let token = AccessToken.current {
            let params = ["fields": "first_name, last_name, email, picture.width(480)"]
            let graphRequest = GraphRequest(graphPath: "me", parameters: params,
                                            tokenString: token.tokenString, version: nil, httpMethod: .get)
            graphRequest.start { (connection, result, error) in
                if let error = error {
                    print("Facebook graph request error: \(error)")
                } else {
                    print("Facebook graph request successful!")
                    guard let json = result as? NSDictionary else { return }
                    if let id = json["id"] as? String {
                        print("\(id)")
                    }
                    if let email = json["email"] as? String {
                        print("\(email)")
                    }
                    if let firstName = json["first_name"] as? String {
                        print("\(firstName)")
                    }
                    if let lastName = json["last_name"] as? String {
                        print("\(lastName)")
                    }
                    if let profilePicObj = json["picture"] as? [String:Any] {
                        if let profilePicData = profilePicObj["data"] as? [String:Any] {
                            print("\(profilePicData)")
                            if let profilePic = profilePicData["url"] as? String {
                                print("\(profilePic)")
                            }
                        }
                    }
                }
            }
        }

请查看图形API Explorer以获取更多字段。

0

你可以使用以下代码获取用户信息,适用于Swift 3.0

  func getFbId(){
if(FBSDKAccessToken.current() != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id,name , first_name, last_name , email,picture.type(large)"]).start(completionHandler: { (connection, result, error) in
    guard let Info = result as? [String: Any] else { return } 


    if let imageURL = ((Info["picture"] as? [String: Any])?["data"] as? [String: Any])?["url"] as? String {
        //Download image from imageURL
    }
if(error == nil){
print("result")
}
})
}
}

0

感谢 @Lyndsey Scott。 对于Kingfisher,请在.plist文件中添加启用请求http。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>http://graph.facebook.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

然后将用户的个人图片设置为ImageView。

let facebookId = "xxxxxxx"
let facebookProfile: String = "http://graph.facebook.com/\(facebookId)/picture?type=large"
let url: URL = URL(string: facebookProfile)!
myImageView.kf.setImage(with: url)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接