Use Parse.com Data in iOS 8 Notification Center widget - ios

I am trying to download a few strings from parse.com inside of a Notification Center widget.
Therefore I first need to sign the user in to parse. First I am loading the credentials, which are saved from the app itself in the NSUserDefaults (I know about the safety aspect.). This step works fine, but when I am performing the following code, the widget says, that the loading of data is not possible.
func signUserIn(username: String, password: String) {
PFUser.logInWithUsernameInBackground(username, password:password) {
(user: PFUser!, error: NSError!) -> Void in
if (user != nil) {
SMKeychainService.saveToken(password)
var defaults = NSUserDefaults(suiteName: "group.xxx.xxx")
defaults.setObject(username, forKey: "UsernameKey")
defaults.synchronize()
self.delegate?.signedIn!(true)
} else {
self.delegate?.signedIn!(false)
}
}
}
Has anyone of you tried to load data from parse.com inside of an widget and how did you do it. I canĀ“t even load the data, because like I mentioned the widget crashes at the sign in of the user.
The app itself has no problems with signing in to parse and loading the data.
I solved the problem
I did not implemented Parse.setApplicationId("xxx", clientKey: "xxx"), now I implemented it in viewDidLoad and the code works!

Setting the
Parse.setApplicationId(appID, clientKey: clientKey)
in the AppDelegate does not work for the extension. Use this code in the viewDidLoad of the extension and it works fine.

Related

Users can't open CKShare record when they accepted the record and application starts

Working my way thru implementing the CKShare functionality of CloudKit.
I Haven manged to get to the part to share a record (via email for example) and also can confirm the user received the invite. The problem is that when user accepts the record then the app pops up but nothing happens. In order to assist here are some key Elements of the app, and please tell me if i am wrong.
1) The application does not require user to login using their Apple ID
2) I am testing the application via a direct built on two different phones (with seperate Apple IDs) when i Connect the phones to the computer with a Cable (aka not using TestFlight yet).
3) I have checked in the CloudkitDashboard and i can see the record that hah been shared and also see that the recored hah been shared, but instead of seeing the user email I sent the invite I see my email and the fact that the record hah been "accepted"
4) I Haven added the CKSharingSupported key in the Info.plist file.
5) The code in the AppDelegate.swift file am using to accept the CKShare is below. I world like to raw your attention to the fact that the string "User Accepted the Share" never gets printed, which makes me think that this part of the code never runs.
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
print("User Accepted the Share")
let acceptShareOperation: CKAcceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
acceptShareOperation.qualityOfService = .userInteractive
acceptShareOperation.perShareCompletionBlock = {meta, share,
error in
print("The Record Share was Accepted")
}
acceptShareOperation.acceptSharesCompletionBlock = {
error in
/// Send your user to where they need to go in your app
let viewController: SNPDetailsViewController = self.window?.rootViewController as! SNPDetailsViewController
viewController.fetchShare(cloudKitShareMetadata)
}
CKContainer(identifier:
cloudKitShareMetadata.containerIdentifier).add(acceptShareOperation)
}
Any insight to guide me where I am wrong, will be much appreciated.
Thank you for your time!
Please see this answer for more context: CloudKit CKShare URL Goes Nowhere
But make sure that:
You specify a fallback URL for your CloudKit Container that redirects to your application.
Inside your app in Xcode, you set up a URL scheme so that custom URLs like yourapp:// open your application and the query parameter from the fallback URL gets passed into userDidAcceptCloudKitShareWith.
After weeks of trial and error, research and LUCK I managed to find out the problem. All tutorials and online solutions relate to the below code in the AppDelegate.swift, to accept a CKShare record:
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
let acceptShareOperation: CKAcceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
acceptShareOperation.qualityOfService = .userInteractive
acceptShareOperation.perShareCompletionBlock = {meta, share,
error in
DispatchQueue.main.async() {
print("The Record Share was Accepted")
}
}
acceptShareOperation.acceptSharesCompletionBlock = {
error in
guard (error == nil) else{
print("Error \(error?.localizedDescription ?? "")")
return
}
let viewController: SNPDetailsViewController = self.window?.rootViewController as! SNPDetailsViewController
viewController.fetchShare(cloudKitShareMetadata)
}
CKContainer(identifier:
cloudKitShareMetadata.containerIdentifier).add(acceptShareOperation)
}
The solution in my case was to add it in the SceneDelegate.swift in the following function:
func windowScene(_ windowScene: UIWindowScene, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
(add above code)
}
Hope this helps others!

Firebase Auth Login must allow single device login

I am developing app with the help of Firebase backend and I am using Firebase Auth for login into my application. I have done all integration and every thing and my app is working fine.
But I want only single session with single user as right now with single userId I am able to login through multiple devices.
So I want to restrict user that at a time user can login in in single device.
I am using Custom auth with username password login :
Auth.auth().signIn(withCustomToken: customToken ?? "") { (user, error) in
// ...
}
If user login with same id in another device I want to show alert that "You are already logged in another device".
Is there any possibility in Firebase Auth lib for single user single session?
Edit : Suggested duplicate question will not solve my query fully though it help me to understand scenireo and help to solve my problem.
Thanks #Frenk for pointing this out.
I search a lot on above issue which I was facing through firebase authentication and after lots of research I ended up with below solution which was working as per my requirements.
First of all firebase not providing this in their library so we need to apply our custom logic here to achieve this 1 session user login in our app.
Step 1: You need to add new child "SignIn" at your root of Database.
Step 2: While Auth.auth().signIn() return success in that block we need to check below Flag that is User already signIn in any other device ? for that I have create one method as mention below.
func alreadySignedIn() {
// [START single_value_read]
let userID = Auth.auth().currentUser?.uid
ref.child("SignIn").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
if let dict = snapshot.value as? [String: Any] {
if let signedIn = dict["signIn"] as? Bool {
if signedIn {
self.signOut()
}
else {
// change the screen like normal
print("First Session of user")
self.writeNewUserSigin(withUserID: userID!)
}
}else{
self.writeNewUserSigin(withUserID: userID!)
}
}else{
print(snapshot)
self.writeNewUserSigin(withUserID: userID!)
}
}) { (error) in
print(error.localizedDescription)
}
// [END single_value_read]
}
By this method we are checking that current user uId have in our SignIn Child with True value if data is there in our database with Boll value True we need to handle that and show some alert and signOut from firebase.
Note : As we allowed user to sign-in and than we are checking that
user already signin in any other device so if its returning True we
need to SignOut() from firebase.
Now last step while user manually signOut from the app
Step 3: While user click on SignOut button in app we need to update our Child with False value in it so after onwards user can able to SignIn in any other device. For that we can use below method.
func updateUserSigIn(withUserID userID: String) {
//Update SignIn Child with flase value on current UID
// [START write_fan_out]
let post = ["signIn": false]
let childUpdates = ["/SignIn/\(userID)": post]
let ref = Database.database().reference()
ref.updateChildValues(childUpdates) { (error, refDatabase) in
if (error != nil) {
print("error \(String(describing: error))")
}else {
print("New user Saved successfully")
self.signOut()
}
}
// [END write_fan_out]
}
Thats it now only one app user session will allow.
Hope this will helps others.
Thanks for this thread as I got some hints from this answer.

blank page after recaptcha verification Authenticate with Firebase on iOS using a Phone Number Swift

After recaptcha verification, page only returned blank. It did nothing to do next step.
Screen Shot
In your app delegate's application(_:open:options:) method, call Auth.auth().canHandle(url).
For the blank re-captcha page issue I was able to resolve it by doing these 3 things:
1st thing-
Inside the GoogleSerivce-Info.plist file make sure the REVERSED_CLIENT_ID is added to your project via the URL types using this. Follow the first part of the second step there: Add custom URL schemes to your Xcode project (look at the screenshot).
2nd thing-
In the project navigator select the blue project icon
Select Capabilities
Open Background Modes
Select Background fetch
3rd thing-
Before verifying the phone number call PhoneAuthProvider.provider(auth: Auth.auth())
#IBAction func phoneButton(sender: UIButton) {
// ***step 5***
PhoneAuthProvider.provider(auth: Auth.auth())
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumberTextField.text!, uiDelegate: nil) {
(verificationID, error) in
if let error = error {
print(error.localizedDescription)
return
}
guard let verificationId = verificationID else { return }
// do something with verificationID
}
}
On iOS, the appVerificationDisabledForTesting setting has to be set to TRUE before calling verifyPhoneNumber. This is processed without requiring any APNs token or sending silent push notifications in the background, making it easier to test in a simulator. This also disables the reCAPTCHA fallback flow.
Firebase Docs
I face this issue and fix it by adding this code into my AppDelegate.m
- (BOOL) application: (UIApplication *) app
openURL: (NSURL *) url
options: (NSDictionary <UIApplicationOpenURLOptionsKey, id> *)
options {
if ([[FIRAuth auth] canHandleURL: url]) {
return YES;
} else {
// URL not auth related, developer should handle it.
return NO;
}
}

PFObject not being updated on IOS device

I have a project that should update a PFObject on Parse.com. It works fine on an IOS simulator, but when I downloaded it onto a phone, the inputs aren't updating in Parse. I've checked that the ID and ClientKey from Parse are still correct, and there are no errors in my code.
Does anyone know what is going on?
Are you making sure to use the .saveInBackgroundWithBlock { (success, error) ... block to save the values in the background when you have processed the information in your app that you want to be saved into your Parse database?
For example,
A following function for a standard social media app would have the following.
func follow(user: PFUser!, completionHandler:(error: NSError?) -> ())
{
// Storing the relation between current user and another user and then saving it in the database under the relationKey "following"
var relation = PFUser.currentUser().relationForKey("following")
relation.addObject(user)
PFUser.currentUser().saveInBackgroundWithBlock { (success, error) -> Void in
// we now have an error option for the signUp function second loop for the user following themself
completionHandler(error: error)
}
}

PFUser currentUser not saving in iOS7

I am using the below code to save the currently logged in user with custom field. I allow the user to fill in information and then save. I used both the save methods on my own threading using GCM and used the saveInBackgrounWithBlock. On iOS8, this works ok but on iOS7 saving never happens and the completion block is never called. Any ideas? Thanks
if PFUser.currentUser() != nil {
PFUser.currentUser().setObject(installation, forKey: "installation")
PFUser.currentUser().saveInBackgroundWithBlock({ (bool: Bool, error: NSError?) -> Void in
if(error != nil) {
let alert = UIAlertView(title: "Problem Saving", message: "Make sure you are connecte to the internet and try again", delegate: nil, cancelButtonTitle: "OK")
alert.show();
}
})
}
Update 1: I noticed that deleting the app resolves the issue temporarily. However, after signing out and signing in with other user (i.e. changing the current user), the issue will pop up again.
Update 2: The issue seems to be coming from PFInstallation somehow. Using addUniqueObject causes issues. After calling this method, any saves stops working iOS7. Even on the PFUser. The PFUser has the installation setup and vice versa. An array of them.
Update 3: Seems like it's not just the addUniqueObject, but any setObject on the PFInstallation.currentInstallation. Help!
you should check your first param (isSuccess) as well:
if (bool == YES && error != nil) -> success
else -> failure
It took me a long while to realise, and even though I never actually found a solution to the problem itself, I found a workaround. I was saving the currentUser in the currentInstallation and the currentInstallation in the currentUser. This was causing issues when saving. I also saved channels on the currentInstallation by sending an array of channels directly instead of using addUniqueObject.
let installation = PFInstallation.currentInstallation()
installation.channels = channels;
installation.saveInBackground()

Resources