Skip to content

Instantly share code, notes, and snippets.

@ShawnBaek
Last active March 10, 2019 14:56
Show Gist options
  • Save ShawnBaek/1397f2ac4bb4d0b90c5f9e37ecc50ca9 to your computer and use it in GitHub Desktop.
Save ShawnBaek/1397f2ac4bb4d0b90c5f9e37ecc50ca9 to your computer and use it in GitHub Desktop.
ParseServerManager for iOS
@IBAction fileprivate func facebookTapped(_ sender: Any) {
ParseServerManager.shared.loginWithFacebook { [weak self] results in
guard let self = self else {
return
}
self.handleLogin(results)
}
}
@IBAction fileprivate func twitterTapped(_ sender: Any) {
ParseServerManager.shared.loginWithTwitter { [weak self] results in
guard let self = self else {
return
}
self.handleLogin(results)
}
}
@IBAction fileprivate func loginTapped(_ sender: Any) {
guard let id = idTextField.text, let password = passwordTextField.text else {
return
}
ParseServerManager.shared.login(username: id, password: password) { [weak self] results in
guard let self = self else {
return
}
self.handleLogin(results)
}
}
fileprivate func handleLogin(_ results: LoginHandler) {
switch results {
case .success(let .some(title), let .some(message)):
//Add Your Logic
break
case .failure(let message):
//Add Your Logic
break
case .success:
//Add Your Logic
break
}
}
func configureParse() {
User.registerSubclass()
}
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
Fabric.with([Crashlytics.self])
Parse.enableLocalDatastore()
Parse.setLogLevel(PFLogLevel.info);
let configuration = ParseClientConfiguration {
$0.applicationId = ""
$0.clientKey = ""
$0.server = "https://parseapi.back4app.com/"
}
Parse.initialize(with: configuration)
PFTwitterUtils.initialize(withConsumerKey: "", consumerSecret: "")
PFFacebookUtils.initializeFacebook(applicationLaunchOptions: launchOptions)
PFConfig.getInBackground{(config: PFConfig?, error: Error?) -> Void in
if error == nil {
//Handle
}
}
PFUser.enableAutomaticUser()
configureParse()
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(
application,
open: url,
sourceApplication: sourceApplication,
annotation: annotation
)
}
//
// ParseServerManager.swift
//
// Created by ShawnBaek on 9/9/18.
// Copyright © 2018 ShawnBaek. All rights reserved.
//
import Foundation
import Parse
enum LoginHandler {
case success(title: String?, message: String?)
case failure(String?)
}
class ParseServerManager {
static let shared = ParseServerManager()
private init() { }
func login(username: String, password: String, completion: @escaping (_ handler: LoginHandler) -> Void) {
User.logInWithUsername(inBackground: username, password: password) { parseUser, error in
if let userAccount = parseUser,
let id = userAccount.username,
error == nil {
UserDefaults.standard.set(id, forKey: "username")
UserDefaults.standard.synchronize()
completion(.success(title: nil, message: nil))
} else {
completion(.failure(error?.localizedDescription))
}
}
}
func signup(username: String, password: String, completion: @escaping (_ handler: LoginHandler) -> Void) {
let currentUser = PFUser()
currentUser.username = username
currentUser.email = username
currentUser.password = password
currentUser.signUpInBackground { success, error in
guard success, error == nil else {
completion(.failure(error?.localizedDescription))
return
}
//linkFaceBook?
completion(.success(title: "Registration is successful", message: nil))
}
}
func loginWithTwitter(completion: @escaping (_ handler: LoginHandler) -> Void) {
PFTwitterUtils.logIn { [weak self] user, error in
guard let self = self else {
return
}
if let user = user {
if user.isNew {
self.getTwitterData() { results in
completion(results)
}
} else {
completion(.success(title: nil, message: nil))
}
} else {
completion(.failure(error?.localizedDescription))
}
}
}
fileprivate func getTwitterData(completion: @escaping (_ handler: LoginHandler) -> Void) {
guard let twitter = PFTwitterUtils.twitter(),
let twitterId = twitter.userId,
// let twitterScreenName = twitter.screenName,
let twitterAPIURL = URL(string: "https://api.twitter.com/1.1/account/verify_credentials.json"),
let currentUser = User.current() else {
completion(.failure("Can't fetch twitter account"))
return
}
let request = NSMutableURLRequest(url: twitterAPIURL)
twitter.sign(request)
URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
guard let fetchedData = data, let json = try? JSONSerialization.jsonObject(
with: fetchedData,
options: .mutableContainers
) as? NSDictionary,
let fetchedJSON = json,
error == nil else {
completion(.failure(error?.localizedDescription))
return
}
if let profileImagePath = fetchedJSON["profile_image_url"] as? String,
let profileImageURL = URL(string: profileImagePath),
let profileImageData = try? Data(contentsOf: profileImageURL),
let profileFileObject = PFFileObject(data: profileImageData) {
currentUser.setObject(profileFileObject, forKey: "profileImg")
}
currentUser.username = twitterId
currentUser.saveInBackground(block: { (success, error) in
guard error == nil, success else {
completion(.failure(error?.localizedDescription))
return
}
UserDefaults.standard.set(twitterId, forKey: "username")
UserDefaults.standard.synchronize()
completion(.success(title: nil, message: nil))
})
}.resume()
}
func loginWithFacebook(completion: @escaping (_ handler: LoginHandler) -> Void) {
let permissions = ["public_profile", "email"]
PFFacebookUtils.logInInBackground(
withReadPermissions: permissions,
block: { [weak self] parseUser, error in
guard let self = self else {
return
}
if let facebookUser = parseUser, error == nil {
if facebookUser.isNew {
self.getFaceBookUserData(completion: { results in
completion(results)
})
}
else {
UserDefaults.standard.set(facebookUser.username, forKey: "username")
UserDefaults.standard.synchronize()
completion(.success(title: nil, message: nil))
}
} else {
completion(.failure(error?.localizedDescription))
}
})
}
fileprivate func getFaceBookUserData(completion: @escaping (_ handler: LoginHandler) -> Void)
{
let requestParameters = ["fields": "id, email"]
let userDetails : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: requestParameters)
userDetails.start(completionHandler: { connection, result, error in
guard let dict = result as? [String: AnyObject],
let userId = dict["id"] as? String,
let email = dict["email"] as? String,
let parseUser = User.current(),
error == nil else {
completion(.failure(error?.localizedDescription))
return
}
parseUser.username = userId
parseUser.email = email
let userProfile = "https://graph.facebook.com/" + userId + "/picture?type=large"
if let profilePictureUrl = URL(string:userProfile),
let profilePictureData = try? Data(contentsOf: profilePictureUrl),
let profileFileObject = PFFileObject(data: profilePictureData) {
if parseUser.object(forKey: "profileImg") == nil {
parseUser.setObject(profileFileObject, forKey: "profileImg")
}
}
parseUser.saveInBackground(block: { success, error in
guard success, error == nil else {
completion(.failure(error?.localizedDescription))
return
}
UserDefaults.standard.set(userId, forKey: "username")
UserDefaults.standard.synchronize()
completion(.success(title: nil, message: nil))
})
})
}
func linkWithFaceBook(completion: @escaping (_ handler: LoginHandler) -> Void) {
guard let currentUser = User.current(), !PFFacebookUtils.isLinked(with: currentUser) else {
completion(.success(title: "Registration is successful. Facebook is already linked", message: nil))
return
}
PFFacebookUtils.linkUser(inBackground: currentUser, withReadPermissions: nil, block: { success, error in
guard success, error == nil else {
completion(.failure("Registration is successful. Facebook linked is failed."))
return
}
completion(.success(title: "Registration is successful", message: nil))
})
}
}
//
// User.swift
//
// Created by ShawnBaek on 12/28/17.
// Copyright © 2017 ShawnBaek. All rights reserved.
//
import UIKit
import Parse
class User: PFUser {
override class func query() -> PFQuery<PFObject>? {
let query = PFQuery(className: "_User")
query.cachePolicy = .networkElseCache
return query
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment