Parse Seamless Login - ios

I have created an app using parse with Swift , when a user opens the app (not from the background) the login screen shows for a split second before moving to the main view. I wan't it to go straight to the main screen if the user is logged in.
I have tried putting the following code nearly everywhere.
if PFUser.currentUser() != nil {
}
I tried NSUserDefaults to check if the user is logged in, in the app delegate didFinishLaunching, couldn't get it to work.
Any help would be greatly appreciated , thanks.

You need to put the check into your "AppDelegate.swift" file.
Then depending on if the user is logged in or not load the MAIN viewcontroller or the LOGIN viewcontroller.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Other stuff you need to setup the app...
if PFUser.currentUser() == nil
{
//Load the Login ViewController
}
else
{
//Load the Main ViewController
}
return true
}

Related

SKStoreReviewController is being displayed the first time user launches the app

In my iOS app I'm using SKStoreReviewController to request users to rate the app. The Apple documentation says to put the code for requesting the "Rate Us" popup anywhere we want, and they will govern when it will be actually displayed.
I wrote the following code in the first view of the app:
func requestReview() {
SKStoreReviewController.requestReview()
}
The problem is that the popup is displayed to my app's users as soon as they first launch the app, which makes no sense. Is there any way to control the popup's appearance and avoid showing it before certain amount of uses of the app?
SKStoreReviewController.requestReview() will display the popup for the first few times (to be exact, for the first 3 times in a year).
Create a variable that you increment each time in your application delegate's didFinishLaunchingWithOptions method and save it to UserDefaults. After that, you can check whether a user opened the app enough times.
AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
var appLaunches = UserDefaults.standard.integer(forKey: "appLaunches")
appLaunches += 1
UserDefaults.standard.set(appLaunches, forKey: "appLaunches")
return true
}
The view controller where you want to display the store review controller
let appLaunches = UserDefaults.standard.integer(forKey: "appLaunches")
if appLaunches >= [enough number of app launches] {
SKStoreReviewController.requestReview()
}

Run methods on app installation

I want to prepopulate my database on app installation in the app store, so I have methods to retrieve data to put them in core data. It is possible ? Here is a method like onInstallation ?
No you can not run code after installation.
Only on first start of your app can your run code, this would be the place to setup some data that your app needs.
If the data is not subject to change I would suggest you create the data store for CoreData with all the initial data and copy this on first run from the main bundle to the directory where you store your CoreData store.
If you need to fetch data you might want to display a screen to the user explaining that you setting up the app and that this might take some time depending on the user data connection.
Not on install as far as I am aware, but how you could do is:
1 - in the AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if UserDefaults.standard.value(forKey: "alreadyLaunch") as? Bool == nil || UserDefaults.standard.value(forKey: "alreadyLaunch") as? Bool == false{
//populate your database
} else {
//do nothing
}
return true
}
2 - After populating the database, add:
UserDefaults.standard.set(true, forKey: "alreadyLaunch")

How to get rid of Back to Messenger after sharing link thru messenger sharing dialog

Currently here's my code to open the sharing dialog to share a link thru messenger:
let invitationLink = NSURL(string:"http://somelink.com")
if (UIApplication.sharedApplication().canOpenURL(NSURL(string: "fb-messenger-api://")!)){
let share = FBSDKMessageDialog()
share.shareContent = FBSDKShareLinkContent()
share.delegate = self
share.shareContent.contentURL = invitationLink
share.show()
}[![enter image description here][1]][1]
And I'm handling the response as well thru FBSDKSharingDelegate on my view controller
By doing so, the app opens Messenger and it seems like when the messenger sharing is done or cancelled, I still have "Back to Messenger" like if Messenger app was the originator ... I would have expected not to see that "Back to Messenger" button after closing the sharing dialog.. Any ideas?
Thanks in advance,
Try to add this line to AppDelegate
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
{
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}

How do you save global arrays in the applicationWillTerminate and reload them in the application function?

So I have been trying to make an app for my Mobile Apps Development class and I need to find a solution to a problem that I'm having when I save a global array called "events".
Here I tried to reload the saved event class in AppDelegate but it didn't change in the main screen view controller:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//Override point for customization after application launch.
//Load the events that were saved when application was terminated
let eventKey = NSUserDefaults.standardUserDefaults()
Global.events = (eventKey.arrayForKey("savedEvents") as? [Event])!
return true
}
Here is the function that is called when someone quits the app:
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
let myEvents = Global.events
NSUserDefaults.standardUserDefaults().setObject(myEvents, forKey: "savedEvents")
NSUserDefaults.standardUserDefaults().synchronize()
}
This might just be an error in the viewcontroller that displays this array but if you see something wrong with the code please let me know.
Two problems:
In iOS, there is no such thing as "someone quits the app", and thus what you're doing is unlikely to work, because applicationWillTerminate is never called. Save when the application is deactivated or backgrounded.
An array of Event cannot magically be saved in user defaults, because Event is not a Property List type. You will need to make Event archivable and archive the array.

User able to access app even after removing app from Facebook App Settings

I have an app that uses both Parse and FacebookSDK. Currently running into the problem where the user is still able to access my app even when going to their Facebook account App settings and removing my app from accessing their Facebook data.
So:
1: New user does a fresh install.
2: User signs up via Facebook Login and accesses app
3: User goes to Facebook.com>App Settings>Remove my app
4: Back on iPhone, user closes app, reopens and gains access again
Here is where I check the current status of the user and let them have access if they hold a currentAccessToken
override func viewDidLoad() {
super.viewDidLoad()
if FBSDKAccessToken.currentAccessToken() != nil{
moveToNextView() //Segue to next viewController
}
}
And my AppDelegate.swift:
import UIKit
import Parse
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
Parse.setApplicationId("ID", clientKey:"KEY")
PFFacebookUtils.initializeFacebookWithApplicationLaunchOptions(launchOptions)
FBSDKProfile.enableUpdatesOnAccessTokenChange(true)
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
}
I'm guessing the currentAccessToken is cached somewhere on the app or device, but unsure about how to clear/refresh that cache.
I have found the solution to this problem. It's not as straight forward as one would think. The Facebook developer console allows you to set a Deauthorize Callback URL which can be found here:
Select your app in the Facebook developer dashboard
Click Facebook Login on the side menu
Click Settings
Then uou can supply Deauthorize Callback URL
Whenever someone removes your app from facebook it generates a POST to your callback URL with a signed request parameter. You can parse the signed request to retrieve the user's facebookid. Once you have the user's facebookid you can update a record in your database that you can use to check on their next login.
Here is an example in PHP of how to handle the deauthorize callback
<?php
function parse_signed_request($signed_request) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$secret = "appsecret"; // Use your app secret here
// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
// confirm the signature
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
$signed_request = $_POST['signed_request'];
$data = parse_signed_request($signed_request);
$user_id = $data['user_id'];
//now use the user_id to look up your user in your database
//update a field called deauthorized to true so that you
//can check this value upon next login
?>
Now next time you check the your access token include a check in your database to see if the user has removed the app.
- (void)viewDidLoad
{
[super viewDidLoad];
if ([FBSDKAccessToken currentAccessToken]) {
// User is logged in, but they may have
// removed the app so we have to check our
// db using a REST API call to see if is deauthorized
// If the user has deauthorized then log them out
// send them back to the login/signup page
// if not, carry on as usual
//also don't forget to set the deauthorized value to 0
//whenever a user successfully logs into facebook
}
}
Hopefully this will help someone in the future.

Resources