2016年1月16日 星期六

iOS筆記:Parse and Facebook SDK

這部分的流程會根據iOS的版本而有誤, 建議還是按照Parse跟Facebook官方的文件來做即可.

目的:使用 Parse 的 Facebook 登入功能.

enter image description here

a. 利用cocoapods來管理Framework. 在新開的專案中新增“Podfile”, 接著執行 pod install.

ParseFacebookUtilsV4 會選用1.8.5是因為我在使用最新版本的時候遇到了一些編譯上的問題, 但這問題在這一版不存在.

platform :ios, '9.0'

pod 'Parse'
pod 'FBSDKCoreKit'
pod 'FBSDKLoginKit'
pod 'FBSDKShareKit'
pod 'ParseFacebookUtilsV4', "~> 1.8.5"

b. 設定Parse
先去Parse官網自訂一個APP名稱.
enter image description here

接著照著以下的設定步驟:
https://parse.com/apps/quickstart#parse_data/mobile/ios/native/new

AppDelegate.m中的application:didFinishLaunchingWithOptions:中新增, 並且#import <Parse.h>.

[Parse setApplicationId:@"eEUFWMCQjmRTAFXXXXXXXSI0JYJ"
                  clientKey:@"BKko60sluQisKwSvyEyKOFrXXXXXXXXXXXX"];

c. Setting up Facebook
使用 Facebook 登入功能,基本上分成三步:

  1. https://developers.facebook.com 創立一個新應用。

enter image description here

只要照著步驟設定即可.
enter image description here

記得在Setting中輸入mail去enable APP.

enter image description here

  1. 透過 CocoaPods 把 Facebook 相關的Library加入專案裡。
  2. 最後就是把登入功能加到 ViewController 裡面。
    Parse provides an easy way to integrate Facebook with your application.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //...

    [PFFacebookUtils initializeFacebookWithApplicationLaunchOptions:launchOptions];

    [[FBSDKApplicationDelegate sharedInstance] application:application
                             didFinishLaunchingWithOptions:launchOptions];

    return YES;
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                          openURL:url
                                                sourceApplication:sourceApplication
                                                       annotation:annotation];
}

PFUser

The PFUser class is a local representation of a user persisted to the Parse Data.

- (void)updateUserInformation
{
    if ([FBSDKAccessToken currentAccessToken]) {
        [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields" : @"name,first_name,gender,birthday,location"}]
//從Facebook那讀取上述的使用者資料

         startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
             if (!error) {
                 NSDictionary *userDictionary = (NSDictionary *)result;

                 //Create URL
                 NSString *facebookID = userDictionary[@"id"];
                 NSURL *pictureURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://graph.facebook.com/%@/picture?type=large&return_ssl_resources=1", facebookID]];

                 NSLog(@"%@",userDictionary);

                 NSMutableDictionary *userProfile = [[NSMutableDictionary alloc] initWithCapacity:7];

                 if (userDictionary[@"name"]) {
                     userProfile[PFUserProfileNameKey] = userDictionary[@"name"];
                 }
                 if (userDictionary[@"first_name"]) {
                     userProfile[PFUserProfileFirstNameKey] = userDictionary[@"first_name"];
                 }
                 if (userDictionary[@"location"][@"name"]) {
                     userProfile[PFUserProfileLocationKey] = userDictionary[@"location"][@"name"];
                 }
                 if (userDictionary[@"gender"]) {
                     userProfile[PFUserProfileGenderKey] = userDictionary[@"gender"];
                 }
                 if (userDictionary[@"birthday"]) {
                     userProfile[PFUserProfileBirthdayKey] = userDictionary[@"birthday"];
                 }
                 if ([pictureURL absoluteString]) {
                     userProfile[PFUserProfilePictureURL] = [pictureURL absoluteString];
                 }

                 [[PFUser currentUser] setObject:userProfile forKey:PFUserProfileKey];
                 [[PFUser currentUser] saveInBackground];

                 [self requestImage];
             }
             else {
                 NSLog(@"Error in Facebook Request %@", error);
             }

         }];
    }
}

如何抓取使用者的照片並呈現出來

主要是使用NSURLSession的NSURLSessionDownloadTask來顯示image.

- (void)uploadPFFileToParse:(UIImage *)image
{
    NSData *imageData = UIImageJPEGRepresentation(image, 0.8);

    if (!imageData) {
        NSLog(@"imageData was not found");
        return;
    }

    PFFile *photoFile = [PFFile fileWithData:imageData];

    [photoFile saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
        if (succeeded) {
            PFObject *photo = [PFObject objectWithClassName:PFPhotoClassKey];
            [photo setObject:[PFUser currentUser] forKey:PFPhotoUserKey];
            [photo setObject:photoFile forKey:PFPhotoPictureKey];
            [photo saveInBackgroundWithBlock:^(BOOL succeeded, NSError * _Nullable error) {
                NSLog(@"Photo save successfully");
            }];
        }
    }];
}

- (void)requestImage
{
    PFQuery *query = [PFQuery queryWithClassName:PFPhotoClassKey];
    [query whereKey:PFPhotoUserKey equalTo:[PFUser currentUser]];
    [query countObjectsInBackgroundWithBlock:^(int number, NSError * _Nullable error) {
        if (number == 0) {
            PFUser *user = [PFUser currentUser];

            self.imageData = [[NSMutableData alloc] init];

            NSURL *profilePictureURL = [NSURL URLWithString:user[PFUserProfileKey][PFUserProfilePictureURL]];

            NSURLSession *session = [NSURLSession sharedSession];

            NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:profilePictureURL completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                UIImage *downloadedImage = nil;
                if (!error) {
                    downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
                } else {
                    NSLog(@"downloadTaskWithRequest failed: %@", error);
                    return;
                }

                dispatch_async(dispatch_get_main_queue(), ^ {
                    UIImage *profileImage = downloadedImage;
                    [self uploadPFFileToParse:profileImage];
                });
            }];
            [downloadTask resume];
        }
    }];
}

遭遇過的問題如下:
1.Could not build module ‘FBSDKCoreKit’
http://stackoverflow.com/questions/29466683/could-not-build-module-fbsdkcorekit-for-facebooksdk-4/29466739#29466739

2.Duplicate symbols for architecture x86_64
http://stackoverflow.com/questions/29466683/could-not-build-module-fbsdkcorekit-for-facebooksdk-4

3.Facebook Friend List Save As Array to Parse
http://stackoverflow.com/questions/32951433/facebook-friend-list-save-as-array-to-parse-swift

4.In developer.facebook.com, APP’s show “Not available to all users because your app is not live.”
http://stackoverflow.com/questions/21329250/the-developers-of-this-app-have-not-set-up-this-app-properly-for-facebook-login

5.How to get user email address from FBSDKProfile in Facebook SDK 4.0.
http://stackoverflow.com/questions/31410793/ios-facebook-sdk-login-doesnt-return-email-despite-permissions-granted/31503463#31503463

http://stackoverflow.com/questions/29323244/facebook-ios-sdk-4-0how-to-get-user-email-address-from-fbsdkprofile

參考網址:
1. https://developers.facebook.com/
2. https://www.parse.com/apps
3. http://blog.winwu.today/2014/05/ios-facebooksdk-facebook.html
4. https://swiftlyios.com/swift-parse-login-signup/
5. https://swiftlyios.com/parse-facebook-login-register/
6. https://www.parse.com/docs/ios/guide

沒有留言:

張貼留言