FBSDKLoginManager error code 308 and singleton does not resolve it - objective-c

I am using Facebook iOS SDK 4.5.1 . Didn't want to use 4.6 as it force login flow to SafariVirwcontrollee only.
I always get error 308 when trying to login if FBSDKLoginManager was called before. Creating singleton as other threads suggested does not work
To summarize error 308 occured in two cases
1. Call login twice.
2. Logout and then login again.
Here is the code for singleton
static FBSDKLoginManager *sharedLoginManager = nil;
+(FBSDKLoginManager*)sharedLoginManager;
{
static dispatch_once_t oncePredecate;
dispatch_once(&oncePredecate,^{
sharedLoginManager=[[FBSDKLoginManager alloc] init];
});
return sharedLoginManager;
}
- (id)init {
if (self = [super init]) {
}
return self;
}
Code to login
if ([FBSDKAccessToken currentAccessToken])
{
[self processLoginInfo];
} else
{
[FBSDKSettings enableLoggingBehavior:FBSDKLoggingBehaviorNetworkRequests];
[[FacebookLoginSingleton sharedLoginManager] logOut];
[[FacebookLoginSingleton sharedLoginManager]
logInWithReadPermissions: #[#"public_profile",#"email",#"user_friends"]
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {//}
}];
Code to logout
if ([FBSDKAccessToken currentAccessToken])
{
[[FacebookLoginSingleton sharedLoginManager] logOut];
[FBSDKAccessToken setCurrentAccessToken:nil];
}

I'm still dealing with this same error, and (assuming your info.plist, AppDelegate, and Facebook app are set up correctly), the issue completely goes away when not running the app with Xcode.
Yeah, it appears to be a bug where the only solution is to not use the debugging tools.
If you need to debug the login flow, there are probably a dozen different ways to do it outside if Xcode, but I had crashlytics installed and just let it log the crash enough times until I got out all the other kinks in my login code.

Related

How to get the Ad Unit ID in Rewarded Video AdMob callbacks in Objective-C

We're developing an iOS app in objective-C and we've decided to add Firebase in our app. We also decided to add the GoogleMobileAds framework that comes with it in order to have Rewarded Video Ads.
I've implemented AdMob as detailed in the official guide but I can't figure out how to get the ad unit ID in each of the callbacks.
The only parameter I have is of type GADRewardBasedVideoAd and it doesn't seem to have any accessible data that provide the ad ID.
Here's one of the callbacks:
- (void)rewardBasedVideoAdDidOpen:(GADRewardBasedVideoAd *)rewardBasedVideoAd
{
NSLog(#"Opened reward based video ad.");
}
I need the ad ID because we're using several ads in our app and I need to know which one is ready/opened/completed/failed/etc.
I tried to use rewardBasedVideoAd.adMetadata[#"AdId"] but it returns nil.
Any help would be appreciated.
Thanks
here:
#implementation GameViewController{
GADRewardedAd *gameOverRewardedAd, *extraCoinsRewardedAd;
}
-(void)viewDidLoad{
gameOverRewardedAd = [self createAndLoadRewardedAdForAdUnit:#"ca-app-pub-YOURID"];
extraCoinsRewardedAd = [self createAndLoadRewardedAdForAdUnit:#"ca-app-pub-YOURID"];
}
-(GADRewardedAd *)createAndLoadRewardedAdForAdUnit:(NSString *) adUnitId {
GADRewardedAd *rewardedAd = [[GADRewardedAd alloc] initWithAdUnitID:adUnitId];
GADRequest *request = [GADRequest request];
[rewardedAd loadRequest:request completionHandler:^(GADRequestError * _Nullable error) {
if (error) {
// Handle ad failed to load case.
} else {
// Ad successfully loaded.
}
}];
return rewardedAd;
}
Then:
#pragma mark admob reward Ad delegate
- (void)rewardedAdDidDismiss:(GADRewardedAd *)rewardedAd {
//NSLog(#"rewardedAdDidDismiss:");
if (rewardedAd == gameOverRewardedAd) {
//do your things here
}else if (rewardedAd == extraCoinsRewardedAd){
}
}
Hope this helps.

can't load Safari contentBlocker. because can't access app group's NSUserDefault

I am making iOS 9 Safari AdBlocker app.
I am using the module of AdBlockPlusSafari.
App works good on simulator.
But when try to run it on device(iPhone6), it fails to reload contentBlocker.
[SFContentBlockerManager
reloadContentBlockerWithIdentifier:self.contentBlockerIdentifier
completionHandler:^(NSError *error) {
if (error) {
NSLog(#"Error in reloadContentBlocker: %#", error);
}
dispatch_async(dispatch_get_main_queue(), ^{
wSelf.reloading = NO;
[wSelf checkActivatedFlag];
if (completion) {
completion(error);
}
});
}];
it gives error
Error Domain=ContentBlockerErrorDomain Code=3 "(null)"
It caused by accessing the values in NSUserDefault (App Group).
- (instancetype)init
{
if (self = [super init])
{
_bundleName = [[[[[NSBundle mainBundle] bundleIdentifier] componentsSeparatedByString:#"."] subarrayWithRange:NSMakeRange(0, 2)] componentsJoinedByString:#"."];
NSString *group = [NSString stringWithFormat:#"group.%#.%#", _bundleName, #"AdBlockerPro"];
NSLog(#"Group name: %#", group);
_adblockProDetails = [[NSUserDefaults alloc] initWithSuiteName:group];
[_adblockProDetails registerDefaults:
#{ AdblockProActivated: #NO,
AdblockProEnabled: #YES
}];
_enabled = [_adblockProDetails boolForKey:AdblockProEnabled];
_activated = [_adblockProDetails boolForKey:AdblockProActivated];
}
return self;
}
The App Group name in host app and safari extension is same.
But in Safari extension, when app accesses the setting in NSUserDefault, it gives me the error.
In Project setting/Capabilities, I did all for App Group. In app id, it involves app group name exactly.
This happens on only device. On simulator, it works good. I can't find the reason of this error.
Please help me if you are experienced this.
Looking forward to your help.
I found the reason myself.
I have put something (NSMutableDictionary) in app group container and did something to write file to extension bundle.
It is prohibited by Apple.
So I deleted all from AdBlockManager (interacts with app group) except flag variables (Boolean type).
And I proceeded the file management using NSFileManager.
http://www.atomicbird.com/blog/sharing-with-app-extensions
Finally, app extension is working for me on device.
Good luck!

After update iOS 9 and Facebook sdk 4.6 the login window not open

I update my Xcode to 7 , and Facebook to 4.6 sdk.
this My warning :
Warning: Attempt to present <FBSDKContainerViewController: 0x159337700> on <UIAlertController: 0x159262700> whose view is not in the window hierarchy!
in My project the BitCode is NO - because if I turn it to Yes I got this Error :
ld:'/Users/MyName/Desktop/MyProjectName/ProjectName/ProjectName/Resources/Frameworks/Fabric.framework/Fabric(Fabric.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
this is the parse method :
-(void)signInWithFacebookClicked
{
NSArray *permissions = [NSArray arrayWithObjects:#"email",#"user_friends", nil];
[PFFacebookUtils logInInBackgroundWithReadPermissions:permissions block:^(PFUser *user, NSError *error)
{
if (!user) // The user cancelled the Facebook login
{
NSLog(#"Uh oh. The user cancelled the Facebook login.");
}
else if (user.isNew) // New user (not stored on DB) - User signed up and logged in through Facebook
{
[self handleNewUser];
}
else if (user) // the user is exist at DB
{
// the user is exist at DB
}
else if (error)
{
// showAlertOfSomethingWentWrong
}
}];
}
this is FBSDKGraphRequest :
-(void)handleNewUser
{
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"friends, first_name, gender, last_name, link, name, verified, picture, email"}];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error)
{
NSMutableDictionary *userData = (NSMutableDictionary *)result;
}];
my problem is that that line :
[PFFacebookUtils logInInBackgroundWithReadPermissions:permissions block:^(PFUser *user, NSError *error)
the run never go into this block in iPhone , in simulator this work fine.
I had a similar problem where I was trying to show a login alert on top of FBSDKContainerViewController.
In this call
- (void)logInWithReadPermissions:(NSArray *)permissions
fromViewController:(UIViewController *)fromViewController
handler:(FBSDKLoginManagerRequestTokenHandler)handler;
Facebook presents its own view controller and if you don't specify the fromViewController, "the topmost view controller will be automatically determined as best as possible."
In your case, it sounds like Facebook is trying to present on top of an alert that was dismissed, even if this is not the call being invoked.
do you add NSAppTransportSecurity & LSApplicationQueriesSchemes key to your info.plist?
I did find a workaround to this, thanks to #PastryPup's answer.
The warning is displayed when trying to present the Facebook login view controller on top of a dismissed alertview. Switching to a UIAlertController, however, fixed the problem.
My impression is that this works because UIAlertController is a full-fledged controller, and thus exists in the view hierarchy even after it has been dismissed.
The solution is to basically replace the UIAlertView with a UIAlertController, and call [PFFacebookUtils logInInBackgroundWithReadPermissions:permissions block:^(PFUser *user, NSError *error) inside the default action of the UIAlerController.
Link on how to implement a UIAlertController
I did some trick to make this work. I don't know if it's the best way to do it. But i just made a boolean that is false before the activity executes (the fb button is tapped). So after it returns, just set the boolean to true and have a condition in the ViewDidAppear that if the boolean is true perform the segue to the next window you want to go.
I hope it helps!

Reporting score to gamecenter for ios7

According to https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/GameKit_Guide/LeaderBoards/LeaderBoards.html
Reporting score to gamecenter in ios7 should be done using
[GKLeaderboard reportScores:scores withCompletionHandler:^(NSError *error) {
//Do something interesting here.
}];
However, I could not find any reference to this method in GKLeaderboard.
The method does not exist here:
https://developer.apple.com/library/ios/documentation/GameKit/Reference/GKLeaderboard_Ref/Reference/Reference.html
GKLeaderboard.h does not contain a reportScores method also.
The former way of reporting score using GKScore's reportScoreWithCompletionHandler method had been deprecated so I am reluctant to use that.
Does anyone know whats the correct way to report score to gamecenter in ios7?
I can confirm that the reportScores:withCompletionHandler: method does work; I'm using it in one of my apps. It's located in the header file GKScore.h. This is how I'm using it:
- (void) reportHighScore:(NSInteger) highScore {
if ([GKLocalPlayer localPlayer].isAuthenticated) {
GKScore* score = [[GKScore alloc] initWithLeaderboardIdentifier:MY_LEADERBOARD_ID];
score.value = highScore;
[GKScore reportScores:#[score] withCompletionHandler:^(NSError *error) {
if (error) {
// handle error
}
}];
}
}

How do I cancel a previous Facebook reauthorize call?

A quick question about the Facebook SDK for iOS. I'm trying to implement the functionality for a user to grant my app access to extended permissions.
While the code works fine when the user accepts the extended permission request (from the Facebook iOS app the user gets redirected to), I'm having trouble detecting when the user has returned to the app while having neither accepted the permissions, or clicking cancel then returning to the app.
If I click 'Cancel' and multitask back into the app, there is nothing logged and nothing shown on-screen. When I try to re-authorize again, the Facebook SDK throws an exception:
FBSession: It is not valid to reauthorize while a previous reauthorize call has not yet completed.
While I can catch the exception, it still doesn't help as I can't figure out how to stop the previous call in order to allow the user to try to re-authorize again.
Here's the code I'm using at the moment:
#try {
[[FBSession activeSession] reauthorizeWithPermissions:[self requiredPermissions]
behavior:FBSessionLoginBehaviorWithFallbackToWebView
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
[self fetchUserPermissionsWithCompletionHandler:^(BOOL extendedGranted) {
if (extendedGranted) {
[self setCanPostToActivityStream:YES];
}
}];
}
else {
NSLog(#"%#", [error localizedDescription]);
}
}];
}
#catch (NSException *exception) {
NSLog(#"%#", exception);
}
Now, the issue is not with the code above - the code works fine. The issue I'm having, again, is cancelling the previous re-authorize call when the user doesn't return to the app successfully after allowing permissions. The Facebook SDK as it is doesn't seem to alert the app of this situation in any way.
From your App's delegate, when - (void)applicationDidBecomeActive:(UIApplication*)application is invoked, you need to make a call to the active session's handleDidBecomeActive method. Once you do that, the completion handler associated with your reauthorizeWithPublishPermissions call will be invoked, and will provide the appropriate error.
- (void)applicationDidBecomeActive:(UIApplication*)application
{
[[FBSession activeSession] handleDidBecomeActive];
}
What you should see coming back from the SDK is an error from the reauthorize completion handler.
{
"com.facebook.sdk:ErrorLoginFailedReason" = "com.facebook.sdk:ErrorReauthorizeFailedReasonUserCancelled";
}
I tested something similar with the following setup: Xcode 4.5, iOS 5, Authorize against m.facebook.com. After an initial authorization I put code to hit reauthorize, then clicked Cancel and got this error.
[FBSession.activeSession
reauthorizeWithPublishPermissions:
[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
// Success case
} else {
// Check the error, info
// [[error userInfo] objectForKey:#"com.facebook.sdk:ErrorLoginFailedReason"]
}
}];
If you are not seeing this then it is a bug and you may want to file it with Facebook.