drewmccormack / ensembles

A synchronization framework for Core Data.
MIT License
1.63k stars 132 forks source link

CDEEEventIntegrator mergeEventsWithCompletion:_block_invoke.91 Causing App Crash #244

Closed JDSX closed 7 years ago

JDSX commented 7 years ago

My project was already up and running using Ensembles however once I migrated to Swift 3 my app now crashes. However the errors all point to the framework when debugging. I keep seeing the following error in the console when syncing;

Could not load any Objective-C class information. This will significantly reduce the quality of type information available.

or when I leave the app running I get the following memory issue

Message from debugger: Terminated due to memory issue

And when I dig further using instruments I found that the CPU over 100%, and memory and energy impact both high. When the app crashes It takes me to CDEEventIntegrator class, mergeEventsWithCompletion function and the dispatch line for `"integrate on background queue".

Im unsure how to resolve this error, and I even turned iCloud drive for the app off in settings however the app still crashes sometime after launching. I have found with iCloud ManagedObjects would keep duplicating.

Here's my Swift 3 functions in the appDelegate.

    // MARK: Ensembles

    var cloudFileSystem: CDECloudFileSystem!
    var ensemble: CDEPersistentStoreEnsemble!

    func syncWithCompletion(completion:@escaping (_ completed:Bool) -> Void) {

        if !ensemble.isLeeched {
            ensemble.leechPersistentStore { error in
                if error != nil {
                    print("cannot leech \(error!.localizedDescription)")
                    completion(false)
                }
                else {
                    print("leached!!")
                    completion(true)
                }
            }
        }
        else {
            ensemble.merge{ error in
                if error != nil {
                    print("cannot merge \(error!.localizedDescription)")
                    completion(false)
                }
                else {
                    print("merged!!")
                    completion(true)
                    //NSNotificationCenter.defaultCenter().postNotificationName("Updated-DB", object: nil)
                }
            }
        }
    }

    func persistentStoreEnsemble(_ ensemble: CDEPersistentStoreEnsemble, didSaveMergeChangesWith notification: Notification) {
        managedObjectContext.performAndWait {
            print("Database was updated from iCloud")
            self.managedObjectContext.mergeChanges(fromContextDidSave: notification as Notification)
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Updated-DB"), object: nil)
        }
    }

    private func persistentStoreEnsemble(ensemble: CDEPersistentStoreEnsemble!, globalIdentifiersForManagedObjects objects: [AnyObject]!) -> [AnyObject]! {
        return (objects as NSArray).value(forKeyPath: "uniqueIdentifier") as! [AnyObject]
    }

This is what I am seeing in the console

screen shot 2016-09-12 at 17 16 51

As mentioned the project was working in previous versions of Swift, but now that my functions have been migrated to Swift 3 I am getting the errors mentioned. Does anyone have any ideas why this might be happening ?

PS: I was actually running final tests before submitting my app for iOS 10 and unfortunately this issue has prevented that. Weird how I haven't had any issues until today

drewmccormack commented 7 years ago

I am fairly sure we fixed this a couple of weeks ago. What version of the code do you have?

You should either download the latest code using the link you received when you purchased, or — if you have access to the github repo — update to the latest master branch.

Kind regards, Drew

On 12 Sep 2016, at 19:11, Jas Singh notifications@github.com wrote:

My project was already up and running using Ensembles however once I migrated to Swift 3 my app now crashes when trying to sync with the following error;

Could not load any Objective-C class information. This will significantly reduce the quality of type information available.

Im unsure how to resolve this error, here's my functions in the appDelegate.

// MARK: Ensembles

var cloudFileSystem: CDECloudFileSystem!
var ensemble: CDEPersistentStoreEnsemble!

func syncWithCompletion(completion:@escaping (_ completed:Bool) -> Void) {

    if !ensemble.isLeeched {
        ensemble.leechPersistentStore { error in
            if error != nil {
                print("cannot leech \(error!.localizedDescription)")
                completion(false)
            }
            else {
                print("leached!!")
                completion(true)
            }
        }
    }
    else {
        ensemble.merge{ error in
            if error != nil {
                print("cannot merge \(error!.localizedDescription)")
                completion(false)
            }
            else {
                print("merged!!")
                completion(true)
                //NSNotificationCenter.defaultCenter().postNotificationName("Updated-DB", object: nil)
            }
        }
    }
}

func persistentStoreEnsemble(_ ensemble: CDEPersistentStoreEnsemble, didSaveMergeChangesWith notification: Notification) {
    managedObjectContext.performAndWait {
        print("Database was updated from iCloud")
        self.managedObjectContext.mergeChanges(fromContextDidSave: notification as Notification)
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Updated-DB"), object: nil)
    }
}

private func persistentStoreEnsemble(ensemble: CDEPersistentStoreEnsemble!, globalIdentifiersForManagedObjects objects: [AnyObject]!) -> [AnyObject]! {
    return (objects as NSArray).value(forKeyPath: "uniqueIdentifier") as! [AnyObject]
}

And I see the error occurs on thread 10 when CDEEEventIntegrator mergeEventsWithCompletion:_block_invoke.91

and this is what I am seeing in the console

https://cloud.githubusercontent.com/assets/5117290/18445163/23e7d388-7914-11e6-8e9d-87ed2597fa44.png As mentioned the project was working in previous versions of Swift, but now that my functions have been migrated to Swift 3 I am getting the errors mentioned.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/drewmccormack/ensembles/issues/244, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEuABjRCJef2cMJwKTXXtBdXsgANp9Qks5qpYe1gaJpZM4J60B3.

JDSX commented 7 years ago

Unfortunately I am using the latest release. I even updated today, removed the project app from both devices, cleared iCloud data and started fresh to see what would happen. At first neither device would sync with the error cannot merge The operation couldn’t be completed. (CDEErrorDomain error 101.) then the got runtime crashes with the error warning: could not load any Objective-C class information. This will significantly reduce the quality of type information available.

Previously when I have been able to fetch iCloud data after removing the app from the device the data would get duplicated. For each time the data would x2, I actually eded up with 26x data with 300mb taken up at one point after removing the app from the device for a few hours then re-installing.

Was hoping to update an app on the App Store for iOS 10 however am unable to with the current sync ing bugs. Am tempted to go for the CloudKit ensembles framework but unsure how quick I would be able to set up as iCloud seems to be creating to much hassle. Also

drewmccormack commented 7 years ago

I just updated the Simple Sync example to Swift 3, and it seems to be working OK.

Maybe it is worth trying to run your project with the Zombies enabled, to see if that gives us a clue.

drewmccormack commented 7 years ago

Ah, I just realised you are using the open source Ensembles. Is that right? There may well still be a problem there. I have only been updating Ensembles 2.

I will see if I can bring back the relevant changes to the open source project. Setting Zombies would still help to confirm this.

JDSX commented 7 years ago

Yes I am, oh right that makes sense. I wanted to get familiar with the open source framework, however I have just purchased Ensembles 2 because 1 has served me well for a few months, and with Swift 3 support and CloudKit the upgrade makes sense. Will try to update my project and hopefully everything will run smooth again

JDSX commented 7 years ago

How can I get access to the Simple Sync project in Swift 3 ? As the download files are still in swift 2.2

drewmccormack commented 7 years ago

It’s currently only in the github repo master branch. If you send me your github username, I will give you access.

Drew

On 13 Sep 2016, at 15:37, Jas Singh notifications@github.com wrote:

How can I get access to the Simple Sync project in Swift 3 ?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/drewmccormack/ensembles/issues/244#issuecomment-246683292, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEuAGo9OOC5A2HNBEm3myWEH0igbeN-ks5qpqcKgaJpZM4J60B3.

JDSX commented 7 years ago

I just actually sent over an email but my username is JDSX, do you have any CloudKit examples in Swift yet ?

drewmccormack commented 7 years ago

Just added you to repo.

No, we only have the Simple Sync example in Swift. The Idiomatic example (ObjC) does include CloudKit. Should only be small differences in Swift.

smallhorse1987 commented 7 years ago

I still have this problem with v1.6. Xcode8+iCloud

drewmccormack commented 7 years ago

Can you turn on Zombies in your app and tell me where it is crashing? This info is a bit vague at the moment.

smallhorse1987 commented 7 years ago

Well, I will collect more information tomorrow.

So far, I rollback to Xcode7, then the issue is gone.

smallhorse1987 commented 7 years ago

Pre-condition: 1,compiled by Xcode8. 2, refresh installation 3, first time to fetch& rebase data from iCloud.

Debug Infomation: default

**Zombie debug info: -[NSError retain]: message sent to deallocated instance 0x174c420a0

drewmccormack commented 7 years ago

Is that the release version (1.6)? If possible, can you pull the latest trunk from GitHub? I made a bunch more improvements to NSError handling, and I think I caught that one.

drewmccormack commented 7 years ago

Just checked. Yes, I did change that code. See very end of this commit: https://github.com/drewmccormack/ensembles/commit/bedc3f8adfe3c617ef439025a2797278721764dd https://github.com/drewmccormack/ensembles/commit/bedc3f8adfe3c617ef439025a2797278721764dd

Drew

On 14 Oct 2016, at 04:12, smallhorse1987 notifications@github.com wrote:

Pre-condition: 1,compiled by Xcode8. 2, refresh installation 3, turn app to foreground quickly right after it switch to background.

Debug Infomation: https://cloud.githubusercontent.com/assets/18483946/19373422/5f8a79ae-91f6-11e6-8a32-92e5bb21c554.png **Zombie debug info: -[NSError retain]: message sent to deallocated instance 0x174c420a0

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/drewmccormack/ensembles/issues/244#issuecomment-253692153, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEuADsrujLpZbKlsmyPHOMc2PA-UzKJks5qzuUEgaJpZM4J60B3.

mastro35 commented 7 years ago

yep, 1.6.1 solve the problem. Unfortunately the version provided by CocoaPods is still the 1.6 so be sure to get the latest version from here by using in your PodFile

pod 'Ensembles', :git => 'https://github.com/drewmccormack/ensembles.git'

drewmccormack commented 7 years ago

Sorry, somehow must have forgotten to push the update. Now done.

DAEUN-pixo commented 2 years ago

@drewmccormack Hello... I still have this problem with latest ensembles 😢 My podfile is configured like @mastro35

image
drewmccormack commented 2 years ago

That doesn't look like the same problem. Not also that this thread is from 5 years ago, so unlikely.

Looking at your error, it seems that Ensembles thinks it has NSData, and it actually has an NSArray. Do you have transformable attributes? In particular, an array of values that you are transforming to data?

DAEUN-pixo commented 2 years ago

Thank you for quick response :)

As you said, I have transformable attributes. And the type of the array is [Date]. I don't know why this error happed 😢

drewmccormack commented 2 years ago

What is the transformer you are using? Can you screenshot the attribute in the Core Data model?

drewmccormack commented 2 years ago

I think I see the problem. This was changed by Apple. We have a fix for the change in Git, but it hasn't yet been released for Cocoapods yet.

I will try to release that in the coming days. For now, if you are able to use the HEAD of the Git repo, that should work.

Eg. In your pod file

pod 'Ensembles', :git => 'https://github.com/drewmccormack/ensembles.git', :commit => 'db261baa0a532408637a594055b0396fae15a91a'

Then

pod update
DAEUN-pixo commented 2 years ago

I applied your suggestion, but another crash is occurs.. 😢 My CoreData model has a to-many relationship, and one attribute of the entity is transformable, optional, and the type is [Date]. I also used CDEPropertyChangeValueTransformer for configure Transformer filed in my CoreData model :)

Additionally, the completion of CDEEnsemble.merge method is not called.. So CDEEventIntergrator.mergeEventsWithCompletion always works on private thread. This is identified as the cause of the increased memory usage and cpu usage of my app. Enabling ensemble uses significantly more resources than disabling it.

스크린샷 2021-08-12 오전 9 44 28
drewmccormack commented 2 years ago

You shouldn't use CDEPropertyChangeValueTransformer. That is an internal transformer. Just use whichever transformer you were using before.

I'm not sure about the optional part. I may need to check if we handle that properly.

You may need to clear all the sync data that was created before the change. It may have the wrong values.