Retrieve information from Parse Local Data Store - ios

i am trying to retrieve data from parse local stat store.
i assume that it is pinning because there is no error when running the following:
let contact = PFObject(className: "temp")
contact["firstName"] = "steve"
contact["lastName"] = "smith"
contact["email"] = "steve.smith#example.com"
contact.pinInBackground()
the error comes when trying to retrieve:
let query = PFQuery(className: "temp")
query.whereKey("firstName", equalTo: "steve")
query.fromLocalDatastore()
query.findObjectsInBackground { (object, error) in
if error == nil {
for object in object! {
print(object["firstName"] as! String)
}
}
}
returns this error:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Method requires Pinning
enabled.'
I've read a bit online about the call location of
Parse.enableLocalDatastore()
in the app delegate but i haven't been able to produce any results and this template was dl direct from parse, this is the first part of my app delegate:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
//--------------------------------------
// MARK: - UIApplicationDelegate
//--------------------------------------
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Enable storing and querying data from Local Datastore.
// Remove this line if you don't want to use Local Datastore features or want to use cachePolicy.
Parse.enableLocalDatastore()
let parseConfiguration = ParseClientConfiguration(block: { (ParseMutableClientConfiguration) -> Void in
ParseMutableClientConfiguration.applicationId = "XXX"
ParseMutableClientConfiguration.clientKey = "XXX"
ParseMutableClientConfiguration.server = "XXX"
})
Parse.initialize(with: parseConfiguration)

Sorted....
Parse.enableLocalDatastore()
seems to be a legacy item that i got from somewhere.
simply adding:
ParseMutableClientConfiguration.isLocalDatastoreEnabled = true
fixes the problem.
You will need to remove or comment out all instances of
Parse.enableLocalDatastore()

Related

Got an "configurationError" when sending a transaction in Xcode

When I try to send a transaction on the Aion network, I keep getting the "configurationError". I am using Xcode to create my IOS dApp.
The code i have to send a transaction is:
#IBAction func sendTxButton(_ sender: Any) {
//deleted my address and pk
let address = "0x0"
let privateKey = "0x0"
let nonce = BigInt.init(3)
let to = "0xa0d969df9232b45239b577c3790887081b5a22ffd5a46a8d82584ee560485624"
let value = BigInt.init(10000000)
let nrgPrice = BigInt.init(10000000000)
let nrg = BigInt.init(21000)
var txParams = [AnyHashable: Any]()
txParams["nonce"] = HexStringUtil.prependZeroX(hex: nonce.toString(radix: 16))
txParams["to"] = to
txParams["data"] = ""
txParams["value"] = HexStringUtil.prependZeroX(hex: value.toString(radix: 16))
txParams["nrgPrice"] = HexStringUtil.prependZeroX(hex: nrgPrice.toString(radix: 16))
txParams["nrg"] = HexStringUtil.prependZeroX(hex: nrg.toString(radix: 16))
do {
let importWallet = try PocketAion.importWallet(privateKey: privateKey, subnetwork: "32", address: address, data: nil)
try PocketAion.eth.sendTransaction(wallet: importWallet, nonce: nonce, to: to, data: "", value: value, nrgPrice: nrgPrice, nrg: nrg, handler: { (result, error) in
if error != nil {
print(error!)
return
} else {
print("the hash:", result!)
}
})
} catch{
print(error)
}
}
I have met all of the requirements on sending a transaction, but cant figure out what is wrong.(this is for sending test tokens on the Aion test net "32").
check your AppDelegates class. make sure you have added "configuration" and point it to the right URL and under the application function you make sure you have the configuration is set to "self".
class AppDelegate: UIResponder, UIApplicationDelegate, Configuration {
public var nodeURL: URL{
get {
return URL.init(string: "https://aion.pokt.network")!
}
}
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
PocketAion.shared.setConfiguration(config: self)
return true
}

How do I fetch all children of the parent CKRecord when `userDidAcceptCloudKitShareWith(:)` is called?

#available(iOS 10.0, *)
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {
let acceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
acceptSharesOperation.perShareCompletionBlock = { metadata, share, error in
let operation = CKFetchRecordsOperation(recordIDs: [cloudKitShareMetadata.rootRecordID])
operation.perRecordCompletionBlock = { record, _, error in
//do something with root record
}
CloudAssistant.shared.container.sharedCloudDatabase.add(operation)
}
acceptSharesOperation.qualityOfService = .userInteractive
CKContainer(identifier: cloudKitShareMetadata.containerIdentifier).add(acceptSharesOperation)
}
That way I am able only to download rootRecord, but along with this record I associated lot of records using setParent().
Is there a way to fetch them also here?

How to set the default SyncConfiguration for Realm, so I can get it in multiple ViewControlllers without redundant code?

According to the:
Proper Realm usage patterns/best practices
What is the best practice or design pattern to maintain sync activity across multiple views
Design Pattern for Realm Database Swift 3.1 - Singleton
my approach is like:
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
DispatchQueue.main.async {
let username = "test#test.com"
let password = "Test123"
let serverUrl = URL(string: "http://test.com:9080")
let realmUrl = URL(string: "realm://test.com:9080/~/realmtest")
if let user = SyncUser.current {
Realm.Configuration.defaultConfiguration.syncConfiguration = SyncConfiguration(user: user, realmURL: realmUrl!)
} else {
SyncUser.logIn(with: .usernamePassword(username: username, password: password, register: false), server: serverUrl!, onCompletion: { (user, error) in
guard let user = user else {
print("Error: \(String(describing: error?.localizedDescription))")
return
}
Realm.Configuration.defaultConfiguration.syncConfiguration = SyncConfiguration(user: user, realmURL: realmUrl!)
})
}
}
return true
}
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
print("SyncConfiguration: \(String(describing: Realm.Configuration.defaultConfiguration.syncConfiguration))")
self.realm = try! Realm()
}
When I open app for the first time nothing happens but when I open app the second time, Realm works fine.
Whenever I open app, the printed SyncConfiguration is nil. No errors!
Searched here and there and can't find an answer...
The problem is that you are using an async method to configure your Realm, but you don't call the print inside the completion handler of your method. You should only present your viewcontoller once your asynchronous call has finished.

Facebook SDK 4.0 stay logged in/Save FBSDKAccessToken in iOS (Swift 3)

I'm trying to somehow save my Access Token/stay logged in upon app quit/crash. I am able to login to Facebook and retrieve data with the FBSDKGraphRequest but every time I quit the app, I am confronted with yet another login screen asking for my authentication (and saying I've already authorized this application) After doing numerous Google searches pertaining to the specific FBSDK version, I've found close to nothing that can help me with somehow keeping the current user logged into Facebook.
FBSession is deprecated (thus I cannot use it since it's not in the most current SDK anymore) and instead I have to do something with FBSDKAccessToken but I really have no clue as to what I have to do.
Here is the current code I'm using to check if currently logged in:
AppTabBarController (type UITabBarController)
override func viewDidAppear(_ animated: Bool) {
if FBSDKAccessToken.current() == nil {
//Go to Facebook Login Screen
performSegue(withIdentifier: "toFBLogin", sender: self)
}
}
AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FBSDKApplicationDelegate.sharedInstance()
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
FBSDKAppEvents.activateApp();
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}
...//Plus rest of protocol-required functions.
My problem is that there is no way to save the AccessToken that I know of. (Whenever the app launches, the FBSDKAccessToken.current() is nil)
With swift in AppDelegate, you can check if the user is logged with this:
if (FBSDKAccessToken.currentAccessToken() != nil) {
}
Just to know, if you use it in
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
}
It's better to call
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
before the if , otherwise FBSDKAccessToken will be nil and you will see the login screen again.
Example:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
if (FBSDKAccessToken.currentAccessToken() != nil) {
//if you are logged
} else {
//if you are not logged
}
return 0
}
So I found my own version of the answer. Basically what I did was that I created a plist file that would store the auth data and upon app launch, I would ask to see if the plist had been initialized beforehand and if it did, I would then ask for all the requirements such as appID and expirationDate etc.
I created a few new files as shown below; It's a fairly lengthy process but it works for now. I'm not sure how safe it is having these values available upon app launch but I don't think it's too bad.
Files:
Plist.swift
Contains instructions on receiving and sending data to and from Plist file types
How to Save and Retrieve Data from a Plist
UserInfo.plist
Profile.swift
Lots in file, only showing code for this problem
Used as an access from anywhere class (static)
import FBSDKCoreKit
class Profile {
static private var name:String!
static private var birthday:String?
static private var email:String?
static private var plist:Plist!
//PlistAuth
static private var refreshDate:Date!
static private var expirationDate:Date!
static private var appID:String!
static private var declinedPermissions:[AnyObject]!
static private var permissions:[AnyObject]!
static private var tokenString:String!
static private var userID:String!
static func saveAuth(){
Profile.refreshDate = FBSDKAccessToken.current().refreshDate
Profile.expirationDate = FBSDKAccessToken.current().expirationDate
Profile.appID = FBSDKAccessToken.current().appID
Profile.declinedPermissions = Array(FBSDKAccessToken.current().declinedPermissions)
Profile.permissions = Array(FBSDKAccessToken.current().permissions)
Profile.tokenString = FBSDKAccessToken.current().tokenString
Profile.tokenString = FBSDKAccessToken.current().userID
Profile.plist = Plist(name: "UserInfo")
if Profile.plist != nil{
let dict = Profile.plist.getMutablePlistFile()!
dict["refreshDate"] = Profile.refreshDate
dict["expirationDate"] = Profile.expirationDate
dict["appID"] = Profile.appID
dict["declinedPermissions"] = Profile.declinedPermissions
dict["permissions"] = Profile.permissions
dict["tokenString"] = Profile.tokenString
dict["userID"] = Profile.userID
dict["isReady"] = true
do {
try Profile.plist.addValuesToPlistFile(dictionary: dict)
}catch{
print(error)
}
print(plist.getValuesInPlistFile())
}else{
print("rip plist")
}
}
static func setAuth(){
Profile.plist = Plist(name: "UserInfo")
if Profile.plist != nil {
let dict:NSDictionary = Profile.plist.getValuesInPlistFile()!
if dict["isReady"] as! Bool{
Profile.refreshDate = dict["refreshDate"] as! Date
Profile.expirationDate = dict["expirationDate"] as! Date
Profile.appID = dict["appID"] as! String
Profile.declinedPermissions = dict["declinedPermissions"] as! [AnyObject]
Profile.permissions = dict["permissions"] as! [AnyObject]
Profile.tokenString = dict["tokenString"] as! String
//Profile.userID = dict["userID"] as! String
FBSDKAccessToken.setCurrent(FBSDKAccessToken.init(
tokenString: Profile.tokenString,
permissions: Profile.permissions,
declinedPermissions: Profile.declinedPermissions,
appID: Profile.appID,
userID: Profile.userID,
expirationDate: Profile.expirationDate,
refreshDate: Profile.refreshDate))
}else{
print("No user data found")
}
}
}
...
}
Let me know what you guys think and if there's anything I should be aware about when it comes to storing these files safely (or even if they need to be stored safely)
I had to downgrade the FBSDKCoreKit and FBSDKLoginKit from 4.18.0 to 4.17.0 to make it work as intended.

Notifications with Swift 2 and Cloudkit

I am making a "texting app" you can call it and it uses cloudkit and I have been looking everywhere to add notifications that work with cloudkit... Would someone be able to tell me the code to add push notifications for cloudkit in detail because I am very lost... Also I wan't the notifications to go to different "texting rooms" (in cloudkit it would be record types...) For instance I have one record type called "text" and another one called "text 2" I don't want notifications from "text" to get to people who use "text2" and vise versa.
Using Swift 2.0 with El Captain & Xcode 7.2.1
Elia, You need to add this to your app delegate. Which will arrive in a userInfo packet of data, which you can then parse to see which database/app sent it.
UIApplicationDelegate to the class
application.registerForRemoteNotifications() to the
func application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Than this method
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
let notification = CKQueryNotification(fromRemoteNotificationDictionary: userInfo as! [String : NSObject])
let container = CKContainer(identifier: "iCloud.com")
let publicDB = container.publicCloudDatabase
if notification.notificationType == .Query {
let queryNotification = notification as! CKQueryNotification
if queryNotification.queryNotificationReason == .RecordUpdated {
print("queryNotification.recordID \(queryNotification.recordID)")
// Your notification
}
}
print("userInfo \(userInfo["ck"])")
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: self, userInfo:dataDict)
}
}
}
}
}
That'll get you started.
You can use this method to check your subscriptions programmatically, of course while your developing you can use the dashboard.
func fetchSubsInPlace() {
let container = CKContainer(identifier: "iCloud.com")
let publicDB = container.publicCloudDatabase
publicDB.fetchAllSubscriptionsWithCompletionHandler({subscriptions, error in
for subscriptionObject in subscriptions! {
let subscription: CKSubscription = subscriptionObject as CKSubscription
print("subscription \(subscription)")
}
})
}
And finally when you got it; you can this routine to ensure you capture any subscriptions you missed while your app was sleeping and make sure that subscriptions don't go to all your devices, once you treated them too.
func fetchNotificationChanges() {
let operation = CKFetchNotificationChangesOperation(previousServerChangeToken: nil)
var notificationIDsToMarkRead = [CKNotificationID]()
operation.notificationChangedBlock = { (notification: CKNotification) -> Void in
// Process each notification received
if notification.notificationType == .Query {
let queryNotification = notification as! CKQueryNotification
let reason = queryNotification.queryNotificationReason
let recordID = queryNotification.recordID
print("reason \(reason)")
print("recordID \(recordID)")
// Do your process here depending on the reason of the change
// Add the notification id to the array of processed notifications to mark them as read
notificationIDsToMarkRead.append(queryNotification.notificationID!)
}
}
operation.fetchNotificationChangesCompletionBlock = { (serverChangeToken: CKServerChangeToken?, operationError: NSError?) -> Void in
guard operationError == nil else {
// Handle the error here
return
}
// Mark the notifications as read to avoid processing them again
let markOperation = CKMarkNotificationsReadOperation(notificationIDsToMarkRead: notificationIDsToMarkRead)
markOperation.markNotificationsReadCompletionBlock = { (notificationIDsMarkedRead: [CKNotificationID]?, operationError: NSError?) -> Void in
guard operationError == nil else {
// Handle the error here
return
}
}
let operationQueue = NSOperationQueue()
operationQueue.addOperation(markOperation)
}
let operationQueue = NSOperationQueue()
operationQueue.addOperation(operation)
}
}

Resources