CloudKit- update record: "client oplock error" when updating record using "saveRecord" - cloudkit

I am trying to update a CKRecord to public databse. Up and downloading works very well.
func upDatePublicRecord() {
let database:CKDatabase = CKContainer.defaultContainer().publicCloudDatabase
if let myID = self.ID {
database.fetchRecordWithID(myID, completionHandler: { (myRecord, error) in
if error != nil {
print("Error fetching record: \(error!.localizedDescription)")
} else {
print("publicrecord fetched")
myRecord!["name"] = self.name
//and more code to change other properties
//save back to iCloud
CKContainer.defaultContainer().privateCloudDatabase.saveRecord(myRecord!) { [unowned self] (record, error) -> Void in
dispatch_async(dispatch_get_main_queue()) {
if error == nil {
print("update success")
} else {
print("Error in update public: \(error!.localizedDescription)")}
}
}
}
})
}
}
This works for updating in privateCloudDatabase, for the public database i get this error:
Error in update public: Error saving record CKRecordID: 0x7f855dbcdb70; F3C192C8-6E81-493E-9E1A-75C5F3826F78:(_defaultZone:defaultOwner) to server: client oplock error updating record
What does this mean? What should I do to update a public record?

You have a copy and paste problem. You are fetching from the public database but you are trying to save to the private database.
Change this:
CKContainer.defaultContainer().privateCloudDatabase.saveRecord(myRecord!) { [unowned self] (record, error) -> Void in
to:
CKContainer.defaultContainer().publicCloudDatabase.saveRecord(myRecord!) { [unowned self] (record, error) -> Void in

Related

Firebase Data Swift

I've got a little problem gaining objects from data base.It contains 4 objects(4 images specifically), they're coming but for some reason they overlap. If I print out query item, the logo shows 4 references to the images which is completely correct but when start setting data up to the image, instead of getting 4 images, I get 16. Is there any way to fix? I though it could be fixed by changing the model from struct to class to avoid duplicating but it didn't work out. Maybe a triple loop causes the problem.
class APIManager {
private init() {}
static let shared = APIManager()
func fetchData(collectionType: CollectionType, completion: #escaping (Document) -> Void) {
let dataBase = self.configureFireBase()
dataBase.collection(collectionType.rawValue).getDocuments { (querySnapshot, error) in
if let error = error {
print("Error received trying to get data: \(error)")
}else{
guard let query = querySnapshot?.documents else {return}
for queryItem in query {
for(name, price) in queryItem.data() {
if name == "field1" {
self.getImage { (sneakerImage) in
let documentToAppend = Document(name: queryItem.documentID, field1: price as? String ?? "", field2: queryItem.documentID, image: sneakerImage)
completion(documentToAppend)
}
}
}
}
}
}
}
private func getImage(imageHandler: #escaping (UIImage)->Void) {
let storage = Storage.storage()
let reference = storage.reference(forURL: "gs://sneakershop-b309a.appspot.com").child("pictures")
reference.listAll { (result, error) in
for item in result.items {
print(item)
item.getData(maxSize: 1024 * 1024) { (data, error) in
if let error = error {
print("error: \(error.localizedDescription)")
}else{
guard let image = UIImage(data: data ?? Data()) else {return}
imageHandler(image)
}
}
}
}
}
private func configureFireBase() -> Firestore {
var db: Firestore!
let settings = FirestoreSettings()
Firestore.firestore().settings = settings
db = Firestore.firestore()
return db
}
}

How to remove SnapShot listener (Firestore - Swift)

func addUserObserver(_ update: #escaping () -> Void) {
FriendSystem.system.USER_REF.addSnapshotListener { snapshot, error in
self.userList.removeAll()
guard error == nil else {
print("Error retreiving collection")
return
}
for document in snapshot!.documents {
let email = document.get("email") as! String
if email != Auth.auth().currentUser?.email! {
self.userList.append(User(userEmail: email, userID: document.documentID))
}
update()
}
}
}
I have added a listener but can't figure out how to disconnect/remove it. Thanks!
As shown in the documentation on detaching a listener, you need to keep the value you get back from addSnapshotListener:
var listener = FriendSystem.system.USER_REF.addSnapshotListener { snapshot, error in
...
And then later you can remove the listener with:
listener.remove()

Value of type 'AVCapturePhotoOutput' has no member 'captureStillImageAsynchronously'

Please help me to refactor this code, it does not work, I have searched in the internet but did not found any solution. I could not refactor it by myself.
This line:
imageOutput.captureStillImageAsynchronously(from: connection) { (sampleBuffer, error) -> Void in
throws this error:
Value of type 'AVCapturePhotoOutput' has no member 'captureStillImageAsynchronously'
imageOutput.captureStillImageAsynchronously(from: connection) { (sampleBuffer, error) -> Void in
if (sampleBuffer == nil || error != nil) {
DispatchQueue.main.async {
completion(nil, error)
}
return
}
guard let data = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer!, previewPhotoSampleBuffer: nil) else {
DispatchQueue.main.async {
completion(nil, StillImageError.noData)
}
return
}
guard let image = UIImage(data: data) else {
DispatchQueue.main.async {
completion(nil, StillImageError.noImage)
}
return
}
var saver = ImageSaver()
.onSuccess { image, assetId in
completion(assetId, nil)
}
.onFailure { error in
}
saver = saver.save(image, filter: nil)
}
captureStillImageAsynchronously(from:completionHandler:) is a function of AVCaptureStillImageOutput, not AVCapturePhotoOutput.
Since AVCaptureStillImageOutput is deprecated since iOS 10, you should use AVCapturePhotoOutput instead, like you do in your code. It has a function with the same use case: capturePhoto(with:delegate:).
For more information about the usage of AVCapturePhotoOutput, check out this question.

Core data inserts blocks UI

I'm running a URLSession data task to download some data asynchronously - and after that inserting it to core data (can be around 2000 items). Saving data to the db freezes the UI. Seen other posts on this. What am I missing?
self?.api.getData(param1, param2: id, success: { (data) -> Void in
let myData = JSON(data!)["Data"]
self?.insertDataToDb(myData){result in ...
...
func insertDataToDb(_ data: JSON, success: #escaping SuccessClosure, failure: #escaping FailureClosure){
let privateMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateMOC.parent = context
privateMOC.perform {
self.insertJSONdata(data[Keys.FirstData])
do {
try privateMOC.save()
self.context.performAndWait {
do {
try self.context.save()
success()
} catch let error as NSError {
failure(error)
}
}
} catch let error as NSError {
failure(error)
}
}
}
Update the UI in main thread
DispatchQueue.main.async {
self.updateUI()
}

Anyway to save an object to another user with parse?

Im trying to create an app where you can follow users, I can save the userId of the user I am trying to follow to a "following" key in the user class. However i cannot save the current userId to a "followers" key for the user being followed. I get the error "User cannot be saved unless they have been authenticated via logIn or signUp"
func followUser() {
//User to be followed's username
var userName = self.title!
let myUserId = PFUser.currentUser()?.objectId
var query = PFUser.query()
query?.whereKey("objectId", equalTo: myUserId!)
query?.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let users = objects {
for user in users {
//thisUserId = objectId of user being followed
user.addUniqueObject(self.thisUserId, forKey: "following")
user.saveInBackgroundWithBlock({ (success, error) -> Void in
if error != nil {
println(error)
} else {
println("You favorited \(self.title)")
var otherQuery = PFUser.query()
otherQuery?.whereKey("objectId", equalTo: self.thisUserId)
otherQuery?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
for object in users {
if let user = object as? PFUser {
user.addUniqueObject(myUserId!, forKey: "followers")
user.saveInBackgroundWithBlock({ (success, error) -> Void in
if error == nil {
println("You are following \(self.title)")
} else {
println(error)
}
})
}
}
}
})
}
})
}
}
}
}
The parse website seems much better equipped to handle this. There's nothing wrong with your code (although it is painfully nested and could use some functional abstraction)
https://parse.com/questions/user-cannot-be-saved-unless-they-have-been-authenticated-via-login-or-signup