KCOrderedAccessorFix icon indicating copy to clipboard operation
KCOrderedAccessorFix copied to clipboard

Q: Is KCOrderedAccessorFix still needed? (A: not on 10.12 or later)

Open Motti-Shneor opened this issue 6 years ago • 9 comments

Hello. This is a question - but I don't know how to tag it so. I am using KCOrderedAccessorFix in my 2014 Obj-C project, and it has been serving me well. I am now required to overhaul my project, adapt to latest OS-X SDK, add features etc. Do you (the writers) know if this fix is still needed? Hasn't Apple resolve their issue already in later OS versions / CoreData versions?

Is there a recommended way to determine this? (say remove your code from the build, and call something at the debugger level that will tell me if needed accessors exist)?

Did Apple improve their (rather lousy) support of Ordered-Sets elsewhere (binding, ArrayControllers etc.) ?

And if so - how can I conditionally add your code, so that it will only run on older OS versions?

Thanks.

Motti-Shneor avatar Jan 02 '18 06:01 Motti-Shneor

Well, it may be of benefit to others reading my question, that @CFKevinRef and I verified that Apple has fixed this long-standing issue in Mac OS 10.12, so there is no need to use this extension when running on 10.12 or later. However - to have your app deployed for earlier versions, it is recommended to do something like this:

`- (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil) return _managedObjectModel; // model already created - return it.

//  first access - create model
if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12)
    return [super managedObjectModel];  // on new OS - revert to superclass implementation.

// on older OS - first create the model
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]]];

// then fix the ordered relationships accessors using  KCOrderedAccessorFix
[_managedObjectModel kc_generateOrderedSetAccessors];

// return the newly created model
return _managedObjectModel;

} `

Motti-Shneor avatar Nov 10 '18 08:11 Motti-Shneor

I just attempted to remove KCOrderedAccessorFix from my project, and unfortunately, it seems like there are still issues. Specifically, the - (void)insert<Key>:(NSArray *)value atIndexes:(NSIndexSet *)indexes; selector does not seem to be implemented by Core Data. I haven't checked any of the others.

I'm using Xcode 11.0 with the latest macOS SDK.

chrisvasselli avatar Sep 25 '19 18:09 chrisvasselli

Thanks very much!

Where and how have you hit into a problem by CoreData not generating this method?

Have you hit a crash when something assumed the existence of the method?

My project is striving to almost no code related to CoreData — most everything in my project is just sophisticated bindings between CoreData contexts and entities, to Interface-builder controllers and views. Since on these bindings I do not know which selectors are used by the implementation of, say, NSArrayController, or NSTableColumn — especially when “filters” (Predicates) and other things are involved — I’m worried that maybe my app may crash because of this lacuna.

Can you share your experience?

In my project, I put KCOrderedAccessorFix to action depending on the OS-X version I’m running on. I have not received crash reports from users.

Here is my usage in my Document subclass implementation:

  • (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil) return _managedObjectModel; // model already created - return it.

    // first access - create model if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) return [super managedObjectModel]; // on new OS - revert to superclass implementation.

    // on older OS - first create the model _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]]];

    // then fix the ordered relationships accessors using NSManagedObjectModel+KCOrderedAccessorFix [_managedObjectModel kc_generateOrderedSetAccessors];

    // now return the newly created model return _managedObjectModel; }

Motti Shneor, CEO, Tchelet Technologies LTD. Software Development for Apple Platforms

Address: 34 Emek-Ha-Ella St. Appt.1 Modiin, ISRAEL, 7173147 Tel/Fax: +972-8-9267730 eMail: [email protected] Mobile phone: +972-54-3136621

ceterum censeo microsoftiem delendam esse

On 25 Sep 2019, at 21:21, Chris Vasselli [email protected] wrote:

I just attempted to remove KCOrderedAccessorFix from my project, and unfortunately, it seems like there are still issues. Specifically, the - (void)insert<Key>:(NSArray *)value atIndexes:(NSIndexSet *)indexes; selector does not seem to be implemented by Core Data. I haven't checked any of the others.

I'm using Xcode 11.0 with the latest macOS SDK.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/CFKevinRef/KCOrderedAccessorFix/issues/16?email_source=notifications&email_token=AAUGO25UOAHWJMUKYTMZ7I3QLOT3TA5CNFSM4EKBKXCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7S3VBI#issuecomment-535149189, or mute the thread https://github.com/notifications/unsubscribe-auth/AAUGO24WBCLL7ID4H2RWNIDQLOT3TANCNFSM4EKBKXCA.

Motti-Shneor avatar Sep 26 '19 13:09 Motti-Shneor

I put together a little test.

I have a type KanjiEntry in my app, that has an ordered to-many relationship called readings to a type called KanjiEntryReading.

Core data automatically generates a header with the following methods on KanjiEntry related to this relationship:

- (void)insertObject:(KanjiEntryReading *)value inReadingsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromReadingsAtIndex:(NSUInteger)idx;
- (void)insertReadings:(NSArray<KanjiEntryReading *> *)value atIndexes:(NSIndexSet *)indexes;
- (void)removeReadingsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInReadingsAtIndex:(NSUInteger)idx withObject:(KanjiEntryReading *)value;
- (void)replaceReadingsAtIndexes:(NSIndexSet *)indexes withReadings:(NSArray<KanjiEntryReading *> *)values;
- (void)addReadingsObject:(KanjiEntryReading *)value;
- (void)removeReadingsObject:(KanjiEntryReading *)value;
- (void)addReadings:(NSOrderedSet<KanjiEntryReading *> *)values;
- (void)removeReadings:(NSOrderedSet<KanjiEntryReading *> *)values;

I setup the following code to test which of these are actually implemented:

NSArray<NSString*>* selectors = @[
        NSStringFromSelector(@selector(insertObject:inReadingsAtIndex:)),
        NSStringFromSelector(@selector(removeObjectFromReadingsAtIndex:)),
        NSStringFromSelector(@selector(insertReadings:atIndexes:)),
        NSStringFromSelector(@selector(removeReadingsAtIndexes:)),
        NSStringFromSelector(@selector(replaceObjectInReadingsAtIndex:withObject:)),
        NSStringFromSelector(@selector(replaceReadingsAtIndexes:withReadings:)),
        NSStringFromSelector(@selector(addReadingsObject:)),
        NSStringFromSelector(@selector(removeReadingsObject:)),
        NSStringFromSelector(@selector(addReadings:)),
        NSStringFromSelector(@selector(removeReadings:))
    ];
    
    for ( NSString* selector in selectors )
    {
        if ( [entry respondsToSelector:NSSelectorFromString(selector)] )
            NSLog(@"%@ exists.", selector);
        else
            NSLog(@"%@ does not exist.", selector);
    }

The results were:

insertObject:inReadingsAtIndex: exists.
removeObjectFromReadingsAtIndex: exists.
insertReadings:atIndexes: does not exist.
removeReadingsAtIndexes: exists.
replaceObjectInReadingsAtIndex:withObject: exists.
replaceReadingsAtIndexes:withReadings: does not exist.
addReadingsObject: exists.
removeReadingsObject: exists.
addReadings: exists.
removeReadings: exists.

So it looks like insertReadings:atIndexes: and replaceReadingsAtIndexes:withReadings: were not actually generated by Core Data.

chrisvasselli avatar Sep 26 '19 14:09 chrisvasselli

This is a rather sad find. I wonder what happened at Apple - like this is a decade-standing issue, that was already addressed once - Why is it breaking? Why don’t they implement it once and for all? OrderedSets are so old now — It seems like CoreData is decaying for incompatibility with the new fashionable technologies that don’t go the Cocoa-bindings (KVC/KVO) way. Maybe anything un-swifty gets neglected?

By any means, this should be reported a s a new bug on coreData - and you have just the sample-code they require as proof of the bug.

Moreover - since you say CoreData generates the headers for these unimplemented methods — it means they already obliged to implementing them, and we can expect a fix sometime.

Have you opened a Radar bug already?

Motti Shneor, CEO, Tchelet Technologies LTD. Software Development for Apple Platforms

ceterum censeo microsoftiem delendam esse

On 26 Sep 2019, at 17:08, Chris Vasselli [email protected] wrote:

I put together a little test.

I have a type KanjiEntry in my app, that has an ordered to-many relationship called readings to a type called KanjiEntryReading.

Core data automatically generates a header with the following methods on KanjiEntry related to this relationship:

  • (void)insertObject:(KanjiEntryReading *)value inReadingsAtIndex:(NSUInteger)idx;
  • (void)removeObjectFromReadingsAtIndex:(NSUInteger)idx;
  • (void)insertReadings:(NSArray<KanjiEntryReading *> *)value atIndexes:(NSIndexSet *)indexes;
  • (void)removeReadingsAtIndexes:(NSIndexSet *)indexes;
  • (void)replaceObjectInReadingsAtIndex:(NSUInteger)idx withObject:(KanjiEntryReading *)value;
  • (void)replaceReadingsAtIndexes:(NSIndexSet *)indexes withReadings:(NSArray<KanjiEntryReading *> *)values;
  • (void)addReadingsObject:(KanjiEntryReading *)value;
  • (void)removeReadingsObject:(KanjiEntryReading *)value;
  • (void)addReadings:(NSOrderedSet<KanjiEntryReading *> *)values;
  • (void)removeReadings:(NSOrderedSet<KanjiEntryReading *> *)values; I setup the following code to test which of these are actually implemented:

NSArray<NSString*>* selectors = @[ NSStringFromSelector(@selector(insertObject:inReadingsAtIndex:)), NSStringFromSelector(@selector(removeObjectFromReadingsAtIndex:)), NSStringFromSelector(@selector(insertReadings:atIndexes:)), NSStringFromSelector(@selector(removeReadingsAtIndexes:)), NSStringFromSelector(@selector(replaceObjectInReadingsAtIndex:withObject:)), NSStringFromSelector(@selector(replaceReadingsAtIndexes:withReadings:)), NSStringFromSelector(@selector(addReadingsObject:)), NSStringFromSelector(@selector(removeReadingsObject:)), NSStringFromSelector(@selector(addReadings:)), NSStringFromSelector(@selector(removeReadings:)) ];

for ( NSString* selector in selectors )
{
    if ( [entry respondsToSelector:NSSelectorFromString(selector)] )
        NSLog(@"%@ exists.", selector);
    else
        NSLog(@"%@ does not exist.", selector);
}

The results were:

insertObject:inReadingsAtIndex: exists. removeObjectFromReadingsAtIndex: exists. insertReadings:atIndexes: does not exist. removeReadingsAtIndexes: exists. replaceObjectInReadingsAtIndex:withObject: exists. replaceReadingsAtIndexes:withReadings: does not exist. addReadingsObject: exists. removeReadingsObject: exists. addReadings: exists. removeReadings: exists. So it looks like insertReadings:atIndexes: and replaceReadingsAtIndexes:withReadings: were not actually generated by Core Data.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/CFKevinRef/KCOrderedAccessorFix/issues/16?email_source=notifications&email_token=AAUGO2YBBG5CPGLL5WAUCR3QLS67NA5CNFSM4EKBKXCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7VWEWY#issuecomment-535519835, or mute the thread https://github.com/notifications/unsubscribe-auth/AAUGO25JIVYLFJMOK3DO7DLQLS67NANCNFSM4EKBKXCA.

Motti-Shneor avatar Sep 27 '19 06:09 Motti-Shneor

I just filed a radar, FB7330607. I also uploaded a simple test project illustrating the behavior here: https://github.com/clindsay/TestCoreDataOrderedRelationships

So if anyone finds this thread in the future and wants to check if they can finally drop KCOrderedAccessorFix, running that project and checking the output is a good start.

chrisvasselli avatar Sep 27 '19 18:09 chrisvasselli

Great work. By the way, do you have any idea what could happen if we do apply KCOrderedAccessorFix on OS versions with partial implementations? Could the implementations collide somehow? Who takes precedence?

Sent from my iPhone

On 27 Sep 2019, at 21:43, Chris Vasselli [email protected] wrote:

I just filed a radar, FB7330607. I also uploaded a simple test project illustrating the behavior here: https://github.com/clindsay/TestCoreDataOrderedRelationships

So if anyone finds this thread in the future and wants to check if they can finally drop KCOrderedAccessorFix, running that project and checking the output is a good start.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

Motti-Shneor avatar Sep 28 '19 04:09 Motti-Shneor

I've been using it for years without issue, long after some of the methods seem to have been fixed. Glancing through the code, it looks like the KCOrderedAccessorFix takes precedence to me: https://github.com/CFKevinRef/KCOrderedAccessorFix/blob/master/NSManagedObjectModel%2BKCOrderedAccessorFix.m#L127

chrisvasselli avatar Sep 28 '19 11:09 chrisvasselli

@Motti-Shneor it looks like this has finally been resolved in iOS 14. I can confirm that all of the accessors are implemented. I think we can finally retire this project for good. 🎉

chrisvasselli avatar Sep 21 '20 18:09 chrisvasselli