Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Aug 19 2019 11:25

    evermeer on master

    Fix deprecation warnings Revert "Fix deprecation warning… Merge remote-tracking branch 'u… and 2 more (compare)

  • Aug 19 2019 11:25
    evermeer closed #106
  • Aug 17 2019 07:04
    evermeer commented #106
  • Aug 06 2019 21:09
    MortenGregersen opened #106
  • Apr 17 2019 06:13

    evermeer on 3.6.1

    (compare)

  • Apr 17 2019 06:13

    evermeer on master

    remove swift version file (compare)

  • Apr 17 2019 06:07

    evermeer on 3.6.0

    (compare)

  • Apr 17 2019 06:02

    evermeer on master

    fixed some warnings (compare)

  • Apr 17 2019 05:34

    evermeer on master

    ready for Xcode 10.2 Merge branch 'master' of https:… (compare)

  • Nov 02 2018 05:58
    evermeer commented #105
  • Nov 02 2018 05:58

    evermeer on master

    fix words mistake Merge pull request #105 from ix… (compare)

  • Nov 02 2018 05:58
    evermeer closed #105
  • Nov 02 2018 05:57
    evermeer commented #104
  • Nov 02 2018 05:57

    evermeer on master

    fix words mistake fix words mistake Merge pull request #104 from ix… (compare)

  • Nov 02 2018 05:57
    evermeer closed #104
  • Nov 02 2018 05:28
    ixongju opened #105
  • Nov 02 2018 02:58
    ixongju synchronize #104
  • Nov 02 2018 02:53
    ixongju opened #104
  • Aug 22 2018 15:06
    skrew commented #103
  • Jun 16 2018 18:46
    mgregory commented #103
pengqian
@misuqian
one more question
I find deleteItems(using ModifyOperation) or deleteItem(using recordName) both not work,is it my wrong?
mattdotmac
@mattdotmac

@evermeer Using CloudKit without EVCloudKitDao, I have in the past been able to fetch all records belonging to the current user:

private func fetchLists() {
        // Fetch Public Database
        let defaultContainer: CKContainer = CKContainer.defaultContainer()
        let publicDatabase = defaultContainer.publicCloudDatabase

       defaultContainer.fetchUserRecordIDWithCompletionHandler { (userID, error) -> Void in
            if let userID = userID {
                // here's your userID (recordID) to play with
                let reference = CKReference(recordID: userID, action: .None)
                let predicate = NSPredicate(format: "creatorUserRecordID == %@", reference)

                // Initialize Query
                let query = CKQuery(recordType: RecordTypeLists, predicate: predicate)

                // Configure Query
                query.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]

                // Perform Query
                publicDatabase.performQuery(query, inZoneWithID: nil) { (records, error) -> Void in
                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
                        // Process Response on Main Thread
                        self.processResponseForQuery(records, error: error)
                    })
                }
            }

How would I do this in EVCloudKitDao, whilst still using this?

let reference = CKReference(recordID: specie.recordID, action: CKReferenceAction.None)

EVCloudData.publicDB.connect(Sighting()
            , predicate: NSPredicate(format: "%K == %@", "specie" ,reference)
            , filterId: "Sighting_All" // etc etc

Thanks again!

Edwin Vermeer
@evermeer
And then in the code block in the discoverUserInfo function you could call the code that you have above
then your specie.recordID would be the user.recordID from that sample code
mattdotmac
@mattdotmac
Thanks, I'm having a go at that now :smile:
mattdotmac
@mattdotmac

I'm also having trouble with the following error message: "Cannot assign value of type 'CKRecordID' to type 'CKReference?'".

I can successfully display the specie of an existing sighting to a label in one of two ways: by using the object passed to the view controller via prepareForSegue - specieLabel.text = specie.recordID.recordName; by using the ID of the referenced record in this property to fetch the record on the other end of the link - specieLabel.text = sighting.specie?.recordID.recordName. My issue arises when I to create a new sighting record and try to set its specie field to be that of the selected specie's recordID:

var name: String = ""
var specieRef: CKRecordID?

@IBAction func save(sender: AnyObject) {

        // Assign values
        name = nameTextField.text!
        specieRef = specie.recordID

        // Populate fields
        sighting.name = name
        sighting.specie = specieRef // Cannot assign value of type 'CKRecordID' to type 'CKReference?'

        EVCloudData.publicDB.saveItem(self.sighting, completionHandler: {_ in }, errorHandler: {_ in })

    }

I hope this makes sense! Thanks again

Edwin Vermeer
@evermeer
Hi, the message tels you exactly what you should do :) You should make a CKReference object from your recordID. So You couls say: sighting.specie = CKReference(recordID: CKRecordID(recordName: specieRef), action: CKReferenceAction.None)
Or when assigning values you could have said specieRef = specie end not get the .recordID because that is a property of the CKReference
mattdotmac
@mattdotmac
Thanks! I've given that a go, but I am given two errors that I've never encountered before:
Edwin Vermeer
@evermeer
That’s easy… Again the message tells you what to do :) In your code the CKRecordID is a placeholder. you should replace that with a variable like for instance specie.recordID
mattdotmac
@mattdotmac
That got rid of the first error :smile: Regarding the second, a quick Google suggests that it could be related to Swift syntax? I'm not too sure though
Edwin Vermeer
@evermeer
I would think that the second error will be gone the moment you fix the first one.
mattdotmac
@mattdotmac
Nope, this one remains after fixing the first :worried:
I've tried clean and build etc
mattdotmac
@mattdotmac

@evermeer I actually solved it by removing part of the code:

sighting.specie = CKReference(recordID: specieRef!, action: CKReferenceAction.None)

Thanks again! :smile:

Edwin Vermeer
@evermeer
Ah… specieRef already was a recordID… Overlooked that.
mattdotmac
@mattdotmac

@evermeer Hello again. I'd like to revisit my question regarding fetching records belonging the active user, if you have the time to spare!

I've had a go at using the discoverUserInfo func as suggested to try and solve my problem:

    // MARK: -
    // MARK: Fetch Specie data
    func connectToSighting() {
        EVCloudKitDao.publicDB.discoverUserInfo({ (user) -> Void in
            let reference = CKReference(recordID: user.userRecordID!, action: .None)
            EVCloudData.publicDB.connect(Sighting()
                //, predicate: NSPredicate(value: true) //returns records that have a value
                , predicate: NSPredicate(format: "creatorUserRecordID == %@", reference)
                , filterId: "Sighting_All"
                , configureNotificationInfo: { notificationInfo in
                    notificationInfo.alertBody = "New sighting record"
                    notificationInfo.shouldSendContentAvailable = true
                    notificationInfo.shouldBadge = true
                }
                , completionHandler: { results, status in
                    EVLog("There are \(results.count) existing sighting records")
                    self.sightingTableView.reloadData()
                    return results.count < 200 // Continue reading if we have less than 200 records and if there are more.
                }, insertedHandler: {item in
                    Helper.showStatus("New sighting record: '\(item.name)'")
                    self.sightingTableView.reloadData()
                }, updatedHandler: {item in
                    Helper.showStatus("Updated sighting record")
                    self.sightingTableView.reloadData()
                }, deletedHandler: {recordId in
                    Helper.showStatus("Sighting record was removed")
                    self.sightingTableView.reloadData()
                }, dataChangedHandler : {
                    EVLog("Some Sighting data was changed")
                }, errorHandler: {error in
                    Helper.showError("Could not load sightings: \(error.description)")
            })
        })
    }

The debug console returns 'unexpectedly found nil while unwrapping an Optional value'. By telling the numberOfRowsInSection to return 0 instead of return EVCloudData.publicDB.data["Sighting_All"]!.count, I am able to trigger this message in the console:

EVCloudKitDao.swift(228) handleCallback(_:errorHandler:completionHandler:):
Error: Optional(0) = Optional("Error Domain=NSCocoaErrorDomain Code=0 \"function returend nil without an error\" UserInfo={NSLocalizedDescription=function returend nil without an error}")
Optional([NSLocalizedDescription: function returend nil without an error])

I think I'm on the right track, perhaps there's something I'm missing? Thanks :smile:

Edwin Vermeer
@evermeer
In order to prevent a crash you could use: EVCloudData.publicDB.data["Sighting_All”]?.count ?? 0
Then when the .connect completionHandler is executed, you will do a .reloadData and at that moment you will be sure that you will have a value
mattdotmac
@mattdotmac
Ok, so that prevents the app from crashing :smile: The fact that the tableview is still empty however, suggests that something is not working when fetching by current user?
Edwin Vermeer
@evermeer
That depends on the moment when you execute that line of code. It should be executed after the completionHandler is called. Usually something like this is triggered by the reloadData
mattdotmac
@mattdotmac
I added some console prints to work out what's going on, and it seems that for some reason, the completion handler never gets called!: Gif of debug
connectToSighting gets called, then the whole of discoverUserInfo is skipped!
mattdotmac
@mattdotmac
So I solved the problem with the following code. I still think that discoverUserInfo could have worked, but I could not for the life of me work out how!
    private func fetchUserRecord(recordID: CKRecordID) {
        // Fetch Default Container
        let defaultContainer = CKContainer.defaultContainer()

        // Fetch Private Database
        let privateDatabase = defaultContainer.privateCloudDatabase

        // Fetch User Record
        privateDatabase.fetchRecordWithID(recordID) { (record, error) -> Void in
            if let responseError = error {
                print(responseError)

            } else if let userRecord = record {
                print("\(userRecord)")
            }
        }
    }

    // MARK: -
    // MARK: Fetch Specie data
    func connectToSighting() {

        // Fetch Default Container
        let defaultContainer = CKContainer.defaultContainer()

        // Fetch User Record
        defaultContainer.fetchUserRecordIDWithCompletionHandler { (recordID, error) -> Void in
            if let responseError = error {
                print(responseError)

            } else if let userRecordID = recordID {
                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    self.fetchUserRecord(userRecordID)

                    let sightingReference = CKReference(recordID: userRecordID, action: CKReferenceAction.None)

                    EVCloudData.publicDB.connect(Sighting()
                        //, predicate: NSPredicate(value: true) //returns records that have a value
                        , predicate: NSPredicate(format: "creatorUserRecordID == %@", sightingReference)
                        , filterId: "Sighting_All"
                        , configureNotificationInfo: { notificationInfo in
                            notificationInfo.alertBody = "New sighting record"
                            notificationInfo.shouldSendContentAvailable = true
                            notificationInfo.shouldBadge = true
                        }
                        , completionHandler: { results, status in
                            EVLog("There are \(results.count) existing sighting records")
                            self.sightingTableView.reloadData()
                            return results.count < 200 // Continue reading if we have less than 200 records and if there are more.
                        }, insertedHandler: {item in
                            Helper.showStatus("New sighting record: '\(item.name)'")
                            self.sightingTableView.reloadData()
                        }, updatedHandler: {item in
                            Helper.showStatus("Updated sighting record")
                            self.sightingTableView.reloadData()
                        }, deletedHandler: {recordId in
                            Helper.showStatus("Sighting record was removed")
                            self.sightingTableView.reloadData()
                        }, dataChangedHandler : {
                            EVLog("Some Sighting data was changed")
                        }, errorHandler: {error in
                            Helper.showError("Could not load sightings: \(error.description)")
                    })

                    print("\nThe user record id is \(userRecordID)...")
                    print("\n... and the user record is \(userRecordID.recordName)\n")

                })
            }
        }
    }
mattdotmac
@mattdotmac

@evermeer I can use this to update the specie of a selected sighting:

let specie: Specie? = (EVCloudData.publicDBForContainer(containerIdentifier).data["Specie_All"]![indexPath.row] as? Specie)!
var specieRef: CKRecordID?
specieRef = specie!.recordID

sighting.specie = CKReference(recordID: specieRef!, action: CKReferenceAction.DeleteSelf)
EVCloudData.publicDBForContainer(containerIdentifier).saveItem(sighting, completionHandler: {_ in }, errorHandler: {_ in })

How can save the sighting so that the reference to the specie is removed?

mattdotmac
@mattdotmac

trying

sighting.specie = nil
EVCloudData.publicDBForContainer(containerIdentifier).saveItem(sighting, completionHandler: {_ in }, errorHandler: {_ in })

returns no errors, but the specie does not change

Thanks
Matt

Edwin Vermeer
@evermeer
@mattdotmac Do you mean that both the completionHandler and the errorHandler are not called? or is the completionHandler called but you don’t see any result? If that last is the case, then print the recordID in the completionHandler. After that try getting the record using: EVCloudData.publicDBForContainer(containerIdentifier).getItem(recordId: yourID
mattdotmac
@mattdotmac

@evermeer I think the last one is the case for me. I am able to print the recordID in the completion handler:

sighting.specie = nil
EVCloudData.publicDBForContainer(containerIdentifier).saveItem(sighting, completionHandler: { _ in print("specie is: \(self.sighting.specie)") }, errorHandler: {_ in })

this returns: specie is: nil, showing that at least locally, the specie has been removed from the sighting.

I'm unable to get the record because my code is wrong:
EVCloudData.publicDBForContainer(containerIdentifier).getItem(recordID: self.sighting.recordID, completionHandler: { _ in }, errorHandler: {_ in})
The error is 'extraneous argument 'recordID' in call'. By looking in CloudKit dashboard, i can confirm that the specie was not replaced with nil

thanks again :smile:

mattdotmac
@mattdotmac
@evermeer how do I save a UIImage to CloudKit as a CKAsset?
Edwin Vermeer
@evermeer
You can only create a CKAsset using a fileUrl, json string or dictionary. When you want to save an image, then you need to use the fileUrl. So you first have tow save the UIImage to a file and then upload the CKAsset. Sample code for CKAsset usage can be found here: https://github.com/evermeer/EVCloudKitDao/blob/96b6a57a7a6728840e36d9287e24dd9fd1b7ff2d/AppMessage/AppMessage/DataObjects/Asset.swift#L12-L12
pengqian
@misuqian
Hi.i come back
i face a big problem : using accountStatusWithCompletionHandler and always get NoAccount status.Must i requestApplicationPermission or something before?
pengqian
@misuqian
OK.I find it is the iCloud drive turn off. so how can i exam the iCloud drive?
mattdotmac
@mattdotmac
@evermeer Can the EVCloudData class be used to save EVCloudKitDataObjects to cloudkit when internet becomes available (assuming that there was no internet when EVCloudData.publicDB.saveItem( etc was initially called? From looking, the modify local data section looks most relevant
Edwin Vermeer
@evermeer
In EVCloudKitDao there is no support for offline - online synchronization. Data will only be saved when online.
pengqian
@misuqian
Hi.i don't understand the query's completionHandler. what the isFinished and return boolean value mean?
Edwin Vermeer
@evermeer
When performing a query cloudkit will limit the number of records returned. The default is 100 records. If isFinished is false then you can return true to continue reading more records. This way you will be able to get all your data in batches of 100 records.
pengqian
@misuqian
Thank you
pengqian
@misuqian
My APP was rejected for review people can't get the account timely which must query from iCloud.for i set 60 sec to timeout.What can i do to solve it?
I know must open iCloud Drive.Is there something must be set when distribute app?
Edwin Vermeer
@evermeer
Instead of getting the account directly in the appdelegate you should first navigate to some sort of loading/connectin/loginin screen. If you do that, then you app is started fast and you are able to give direct feedback about the process
pengqian
@misuqian
all right.i find it's i forgot to deploy to production in Cloudkit dashboard
Terminating app due to uncaught exception 'CKException', reason: 'Invalid predicate: countryNo LIKE[cd] "N" (Error Domain=CKErrorDomain Code=12 "Invalid operator in <countryNo LIKE[cd] "*N*">: Unsupported operator: LIKE" UserInfo={ck_isComparisonError=true, NSLocalizedDescription=Invalid operator in <countryNo LIKE[cd] "*N*">: Unsupported operator: LIKE, NSUnderlyingError=0x7fde7966bc30 {Error Domain=CKErrorDomain Code=12 "Unsupported operator: LIKE" UserInfo={NSLocalizedDescription=Unsupported operator: LIKE, ck_isComparisonError=true}}})'
mattdotmac
@mattdotmac
This message was deleted
mattdotmac
@mattdotmac
@evermeer Hi, I'm having an issue where only one tableview (seemingly the first one loaded in the app) is able to restore backed up data from the cache. For table views where the data does not get restored, the Helper.showError called in the error handler does not appear either
pengqian
@misuqian
Something bag happen . i can't store image successfully
i successes with the same code last week.was that my environment setting wrong?
pengqian
@misuqian
Ok. when i back to 2.18.0 ,that's all right. @evermeer why?