示例代碼在末尾。
示例代碼在末尾。
今天用了Facebook的SDK,給app集成分享功能。本以為只要照著官方文檔來,一定能成功,沒想到,,確實(shí)成功了。
但是,且慢?。?!

FB給的示例代碼是這樣的
FBSDKShareLinkContent *content = [[FBSDKShareLinkContent alloc] init];
content.contentURL = [NSURL URLWithString:@"https://developers.facebook.com"];
[FBSDKShareDialog showFromViewController:self withContent:content delegate:nil];
代碼簡介明了, 先創(chuàng)建一個(gè)分享內(nèi)容對(duì)象content,再vc彈出一個(gè)分享對(duì)話框。
可是我發(fā)現(xiàn)在相同的環(huán)境下,同樣的代碼,卻有不同的效果:有兩臺(tái)iPhone,都裝了Facebook原生app。同樣的SDK和代碼,但有臺(tái)手機(jī)調(diào)用的是原生的分享對(duì)話框,另一臺(tái)調(diào)用的卻是SafariViewController(webview)來加載分享對(duì)話框。為什么?
好吧,這能忍能忍。。不過是分享的方式不一樣罷了,兩臺(tái)手機(jī)都能正常分享內(nèi)容的。然而我有這么個(gè)需求:分享結(jié)束之后,我希望知道結(jié)果,是分享成功還是失???或是取消了。
這個(gè)簡單,[FBSDKShareDialog showFromViewController:withContent:delegate:];方法可設(shè)一個(gè)代理來響應(yīng)對(duì)話框的回調(diào),正好!該代理可以實(shí)現(xiàn)三個(gè)回調(diào)方法,
- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results;
- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error;
- (void)sharerDidCancel:(id<FBSDKSharing>)sharer;
雞凍??!這不正是我想要的嗎?
測(cè)了一下,所有的方法都能正常回調(diào),打完收工。
但是,又且慢!

我發(fā)現(xiàn)如果使用webview來分享,如果用戶沒有確認(rèn)分享,甚至是頁面都還沒有加載完,只要點(diǎn)擊了左上角的『完成』按鈕,就會(huì)回調(diào)FBSDKSharingDelegate 的sharer:didCompleteWithResults:方法。而成功分享也是回調(diào)這個(gè)方法,很逗的,直接點(diǎn)完成應(yīng)該算取消分享啊。。。

好吧好吧,我們還可以從回調(diào)方法提供的參數(shù)results中讀取出詳細(xì)的信息,可以發(fā)現(xiàn)當(dāng)用戶真的分享成功時(shí),results中有個(gè)postId字段,而點(diǎn)擊『完成』按鈕時(shí),results是空的。
然而我又不小心測(cè)了下原生分享,遇到了另一個(gè)矛盾的情況:原生分享成功時(shí),回調(diào)的results參數(shù)居然也是空的空的空的!哦啦個(gè)去!
那么如果我能區(qū)分出對(duì)話框的類型,也就可以準(zhǔn)確的判斷出成功和取消了吧?
對(duì)了,回調(diào)的方法中還有個(gè)sharer參數(shù),可以強(qiáng)轉(zhuǎn)為FBSDKShareDialog對(duì)象,它有一個(gè)mode屬性,嘿嘿,我又要成功了!
mode是個(gè)枚舉,有Automatic、Navtive、ShareSheet、Browser、Web......還好我沒有高興得太早,我發(fā)現(xiàn)不管我用的是原生分享還是webview分享,mode都是Automatic,實(shí)在是郁悶。
總算的,我不想偷懶了,我想起了在官方文檔里看到的另一段代碼
// Example content. Replace with content from your app.
FBSDKShareLinkContent *content = [[FBSDKShareLinkContent alloc] init];
content.contentURL = [NSURL URLWithString:@"https://developers.facebook.com"];
FBSDKShareDialog *dialog = [[FBSDKShareDialog alloc] init];
dialog.fromViewController = self;
dialog.content = content;
dialog.mode = FBSDKShareDialogModeShareSheet;
[dialog show];
我寫了這段多了幾行,長了一點(diǎn)的代碼,我可以手動(dòng)指定用原生對(duì)話框分享?。。。?br>
到這里,只要指定dialog.mode = FBSDKShareDialogModeNative;安裝了FB app的用戶都會(huì)調(diào)出原生app分享。啊!總算美好了!
等等,我有個(gè)疑問。如果用戶沒有安裝app呢?
如果用戶沒有安裝app而我指定用native分享,SDK并不會(huì)去調(diào)用webview分享,而是直接回調(diào)失敗的方法。
So sad. 不過可以在失敗的回調(diào)里重新指定一下mode,再重新打開對(duì)話框。
那么又要回到之前那個(gè)郁悶的結(jié)果了:如果調(diào)用了成功的回調(diào),
如果有postId則一定成功,
如果沒有postId,是使用原生的,成功,
如果沒有postId,是使用webview的,失敗
好在,這次,再讀取sharer的mode時(shí),能區(qū)別出原生或webview,至此,是真的真的真的完美了!
代碼如下
- (void)facebookShareWithMessage:(id)message {
NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSString *contentUrlString = dictionary[@"content_url"];
NSString *imageUrlString = dictionary[@"image_url"];
NSString *description = dictionary[@"description"];
NSString *title = dictionary[@"title"];
NSString *quote = dictionary[@"quote"];
FBSDKShareLinkContent *content = [[FBSDKShareLinkContent alloc] init];
content.contentURL = [NSURL URLWithString:contentUrlString];
content.imageURL = [NSURL URLWithString:imageUrlString];
content.contentDescription = description;
content.contentTitle = title;
content.quote = quote;
FBSDKShareDialog *dialog = [[FBSDKShareDialog alloc] init];
dialog.shareContent = content;
dialog.fromViewController = self;
dialog.delegate = self;
dialog.mode = FBSDKShareDialogModeNative;
[dialog show];
}
#pragma mark - FaceBook Share Delegate
- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results {
NSString *postId = results[@"postId"];
FBSDKShareDialog *dialog = (FBSDKShareDialog *)sharer;
if (dialog.mode == FBSDKShareDialogModeBrowser && (postId == nil || [postId isEqualToString:@""])) {
// 如果使用webview分享的,但postId是空的,
// 這種情況是用戶點(diǎn)擊了『完成』按鈕,并沒有真的分享
NSLog(@"Cancel");
} else {
NSLog(@"Success");
}
}
- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error {
FBSDKShareDialog *dialog = (FBSDKShareDialog *)sharer;
if (error == nil && dialog.mode == FBSDKShareDialogModeNative) {
// 如果使用原生登錄失敗,但error為空,那是因?yàn)橛脩魶]有安裝Facebook app
// 重設(shè)dialog的mode,再次彈出對(duì)話框
dialog.mode = FBSDKShareDialogModeBrowser;
[dialog show];
} else {
NSLog(@"Failure");
}
}
- (void)sharerDidCancel:(id<FBSDKSharing>)sharer {
NSLog(@"Cancel");
}