Search code examples
iosswiftfacebook-graph-apifacebook-ios-sdk

getting profile picture from Facebook too slow


I'm trying to get the user's profile picture form Facebook, to display it on his Account screen. It works, but the problem is, it's too slow. The screen will load, and a good half a second later, the profile picture loads. Here is my viewDidLoad code, where I make the graph API request:

override func viewDidLoad() {
    super.viewDidLoad()

    currentUser = User.CurrentUser

    editProfileButton.layer.cornerRadius = 2.5

    // checking for logged in user
    let defaults = NSUserDefaults.standardUserDefaults()

    if FBSDKAccessToken.currentAccessToken() != nil {
        // logged in through facebook, do nothing
        updateCurrentUser()
    } else {
        // log in
        presentLoginViewController()
    }

    userNameLabel.text = currentUser.first_name + " " + currentUser.last_name
    userPhoneLabel.text = currentUser.phone_number

    //getting profile picture: too slow for now. 
    if FBSDKAccessToken.currentAccessToken().hasGranted("user_photos") {
        let userId = FBSDKProfile.currentProfile().userID
        let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"picture.type(large)"])
        graphRequest.startWithCompletionHandler({(connection: FBSDKGraphRequestConnection!, response: AnyObject?, error: NSError!) in
            if error != nil {
                // error
            }

            if let resultDic = response as? NSDictionary {
                let data = resultDic["picture"] as? NSDictionary
                let dataDict = data!["data"] as? NSDictionary
                let imageStringUrl = dataDict!["url"] as? String
                let imageUrl = NSURL(string: imageStringUrl!)
                let imageData = NSData(contentsOfURL: imageUrl!)
                self.currentUser.profilePicture = UIImage(data: imageData!)
                self.userPicImageView.image = self.currentUser.profilePicture
            }
        })
    }


    // user profile picture set up
    userPicImageView.clipsToBounds = true
    userPicImageView.contentMode = .ScaleAspectFill
    userPicImageView.layer.cornerRadius = userPicImageView.frame.height / 2.67
}

Anyway I can make it faster?


Solution

  • For starters, putting the FBSDKGraphRequest call further back in the life cycle is definitely not going to help you get your data faster. viewDidLoad is a good place to put it - if you have to start it within a particular screen.

    Next, you doing the image fetching asynchronously will help improve user experience. The code that you currently have will block the main thread, since the downloading process is on the main thread. I suggest you read up on NSURLSession to deal with obtaining the images.

    Techniques to get photos faster

    There are a couple of reliable ways to get your photos "faster". One way is to grab a smaller image, if acceptable.

    If you must have a large image, a good method is to abstract the network call in another class, and initialize the process as early as possible, for instance, in the didFinishLaunchingWithOptions method of the AppDelegate.

    For instance, you can have a class:

    class FacebookDetails {
        static let sharedInstance = FacebookDetails()
        var image: UIImage?
    
        private init() {
            populateImage()
        }
        func populateImage() {
            let graphRequest = FBSDKGraphRequest... //continue with populating image
        }
    }
    

    Now you can initialize this class as early as possible in your application life cycle:

      func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        FacebookDetails.sharedInstance
        return true
      }
    

    When you get to the view controller that requires the image, call FacebookDetails.sharedInstance.image to retrieve the already loaded image (image load times is still subjected to network strength), but it's a method to start loading your images as early as possible in your application life cycle.