Skip to content

Added automatic PFObject subclass registration. #967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 13, 2016

Conversation

richardjrossiii
Copy link
Contributor

@richardjrossiii richardjrossiii commented Jul 11, 2016

Older discussion visible here: #5

This is a breaking change.

What's new

Currently, every PFObject subclass must be registered with parse before it is used. This can create some hard-to-track-down issues if you're not aware of this, and it isn't exactly the cleanest API.

In Objective-C/Swift, it is relatively easy to search at run-time for subclasses of PFObject, and have them register with parse automatically (in the case of dynamic libraries, even as soon as they load from their bundles).

This should prevent needing your app delegate to have lots of extra lines of code related to simply registering all of your PFObject subclasses.

What's breaking

  • If you had a subclass of PFObject, which implemented PFSubclassing, but intentionally did not register it with parse (or only conditionally registered it with parse), then you may run into errors printed to the console and a crash on start. The error message in the console should be concrete enough to help you track down the issue.
    • If you would still like to use the old-style manual registration (not recommended), you can opt-out on specific subclasses by conforming to the new protocol PFSubclassingSkipAutomaticRegistration.
  • If you remove your calls to [MySubclass registerSubclass] in AppDelegate or similar, and MySubclass is located in a not-yet loaded dynamic library/framework, then until you manually load that library (by using a class/method/function inside it), your subclass will not be registered.
    • Note that this, however, allows for a much better potential plugin model using the Parse SDK using dlopen & friends, if your application needs such a feature.

These breaking changes shouldn't effect 99% of our users, and workarounds should be fairly simple for those it will break for.

Fixes #963
Closes #964

// Skipping a bundle. Not entirely sure of the best solution to that here.
if (shouldSubscribe) {
@weakify(self);
[[NSNotificationCenter defaultCenter] addObserverForName:NSBundleDidLoadNotification
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From offline discussion:
Store the registration token in the ivar, validate that it's nil here to avoid double subscribe as well as clean up the registration in dealloc.

@nlutsenko
Copy link
Contributor

Looks great, can't wait to see this feature!
Feel free to merge after the tests pass.

@richardjrossiii richardjrossiii force-pushed the richardross.subclassing.autoreg branch from a491c1e to 645b29e Compare July 12, 2016 22:40

// There are two different paths that we will need to check for the bundle, depending on the platform.
// - First, we need to check the raw executable path fom the bundle.
// This should be valid for most frameworks on OS X.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Not OSX, macOS.

This will scan all loaded code bundles for classes which inherit from `PFObject`, and register them upon Parse initialization. Still have opt-in support for manual-only registration, though it shouldn't be necessary for most cases.
@richardjrossiii richardjrossiii force-pushed the richardross.subclassing.autoreg branch from 645b29e to e9a4e59 Compare July 12, 2016 22:55
@richardjrossiii richardjrossiii merged commit b5beb7c into master Jul 13, 2016
@richardjrossiii richardjrossiii deleted the richardross.subclassing.autoreg branch July 13, 2016 00:45
@levigroker
Copy link
Contributor

levigroker commented Jul 21, 2016

We're seeing this crash which appears to be related, but we don't have subclasses of PFObjects, so I'm not sure where to look or what to do except downgrade to 1.13. Any suggestions would be appreciated.

#0. Crashed: com.parse.object.subclassing
0  libsystem_c.dylib              0x1804ecfb8 strnlen + 24
1  libsystem_c.dylib              0x1804ee1fc strncpy + 40
2  libsystem_c.dylib              0x1804ee1fc strncpy + 40
3  ------------                   0x1003ca2dc __61-[PFObjectSubclassingController _registerSubclassesInBundle:]_block_invoke (PFObjectSubclassingController.m:355)
4  libdispatch.dylib              0x18048d47c _dispatch_client_callout + 16
5  libdispatch.dylib              0x180498728 _dispatch_barrier_sync_f_invoke + 100
6  ------------                   0x1003ca214 -[PFObjectSubclassingController _registerSubclassesInBundle:] (PFObjectSubclassingController.m:394)
7  ------------                   0x1003c8ca8 __63-[PFObjectSubclassingController scanForUnregisteredSubclasses:]_block_invoke (PFObjectSubclassingController.m:131)
8  Foundation                     0x18132d4c8 -[__NSObserver _doit:] + 308
9  CoreFoundation                 0x1809e4dfc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
10 CoreFoundation                 0x1809e461c _CFXRegistrationPost + 396
11 CoreFoundation                 0x1809e439c ___CFXNotificationPost_block_invoke + 60
12 CoreFoundation                 0x180a4d414 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1532
13 CoreFoundation                 0x1809226c8 _CFXNotificationPost + 368
14 Foundation                     0x181386a9c -[NSBundle loadAndReturnError:] + 2164
15 UIAccessibility                0x18b2f4528 -[NSBundleAccessibility loadAndReturnError:] + 52
16 Foundation                     0x181397a28 -[NSBundle principalClass] + 56
17 UIAccessibility                0x18b2f5190 +[UIAccessibilityLoader loadActualAccessibilityBundle:didLoad:loadSubbundles:] + 100
18 UIAccessibility                0x18b2f5514 +[UIAccessibilityLoader _loadAXBundleForBundle:didLoad:forceLoad:loadSubbundles:] + 460
19 UIAccessibility                0x18b2f56f0 __54+[UIAccessibilityLoader _accessibilityLoadSubbundles:]_block_invoke_2 + 36
20 libdispatch.dylib              0x18048d4bc _dispatch_call_block_and_release + 24
21 libdispatch.dylib              0x18048d47c _dispatch_client_callout + 16
22 libdispatch.dylib              0x180492b84 _dispatch_main_queue_callback_4CF + 1844
23 CoreFoundation                 0x1809f8d50 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
24 CoreFoundation                 0x1809f6bb8 __CFRunLoopRun + 1628
25 CoreFoundation                 0x180920c50 CFRunLoopRunSpecific + 384
26 GraphicsServices               0x182208088 GSEventRunModal + 180
27 UIKit                          0x185c0a088 UIApplicationMain + 204
28 ------------                   0x1002b86b8 main (main.m:16)
29 libdispatch.dylib              0x1804be8b8 (Missing)

@nlutsenko
Copy link
Contributor

This should be fixed as of 1.14.2. Please update the SDK and comment here if it helped or if you are still running into an issue here.

@levigroker
Copy link
Contributor

Thanks @nlutsenko. I don't see 1.14.2 on cocoapods yet... I just see 1.14.1. Can cocoapods be updated to 1.14.2 please?

@nlutsenko
Copy link
Contributor

Please run 'pod repo update' to make sure you have the latest specs locally.
1.14.2 was pushed to CocoaPods a while ago.

@levigroker
Copy link
Contributor

levigroker commented Jul 21, 2016

I was looking on cocoapods.org, and saw only 1.14.1, but now I see 1.14.2, so -shrug-. Many thanks for being responsive.

@levigroker
Copy link
Contributor

Well, with 1.14.2 we are still seeing an issue, but so far only against iOS 10.0.0:

Fatal Exception: NSInternalInconsistencyException
0  CoreFoundation                 0x18ccd36f8 __exceptionPreprocess
1  libobjc.A.dylib                0x18c2cc578 objc_exception_throw
2  CoreFoundation                 0x18ccd3640 -[NSException initWithCoder:]
3  ------------                   0x1004121d4 -[PFObjectSubclassingController _registerSubclassesInBundle:] (PFObjectSubclassingController.m:344)
4  ------------                   0x100410cc4 __63-[PFObjectSubclassingController scanForUnregisteredSubclasses:]_block_invoke (PFObjectSubclassingController.m:131)
5  Foundation                     0x18d6495fc -[__NSObserver _doit:]
6  CoreFoundation                 0x18cc6e740 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__
7  CoreFoundation                 0x18cc6de44 _CFXRegistrationPost
8  CoreFoundation                 0x18cc6dbc0 ___CFXNotificationPost_block_invoke
9  CoreFoundation                 0x18ccdc0cc -[_CFXNotificationRegistrar find:object:observer:enumerator:]
10 CoreFoundation                 0x18cbb1484 _CFXNotificationPost
11 Foundation                     0x18d6a1da4 -[NSBundle loadAndReturnError:]
12 UIAccessibility                0x19924c49c -[NSBundleAccessibility loadAndReturnError:]
13 UIAccessibility                0x19924dc54 +[UIAccessibilityLoader __loadActualAccessibilityBundle:didLoadCallback:loadSubbundles:]
14 UIAccessibility                0x19924d374 +[UIAccessibilityLoader _loadAXBundleForBundle:didLoadCallback:forceLoad:loadSubbundles:loadAllAccessibilityInfo:]
15 UIAccessibility                0x19924e6d8 __54+[UIAccessibilityLoader _accessibilityLoadSubbundles:]_block_invoke_2
16 libdispatch.dylib              0x18c71d7c4 _dispatch_call_block_and_release
17 libdispatch.dylib              0x18c71d784 _dispatch_client_callout
18 libdispatch.dylib              0x18c722330 _dispatch_main_queue_callback_4CF
19 CoreFoundation                 0x18cc820cc __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
20 CoreFoundation                 0x18cc7fcb8 __CFRunLoopRun
21 CoreFoundation                 0x18cbaf8d8 CFRunLoopRunSpecific
22 GraphicsServices               0x18e5b6198 GSEventRunModal
23 UIKit                          0x192b597c8 -[UIApplication _run]
24 UIKit                          0x192b54534 UIApplicationMain
25 ------------                   0x1003006d4 main (main.m:16)
26 libdispatch.dylib              0x18c7505b8 (Missing)

@nlutsenko
Copy link
Contributor

@levigroker, just tested on iOS 10 and it works just fine on both Simulator and Device.
Any chance you can create a new issue and attach a sample project (and specify run destination) on where this problem happens.
Also, would be very helpful to know the bundle for which it fails to extract the executablePath.

@levigroker
Copy link
Contributor

@nlutsenko Thanks... unfortunately this is happening in production and we're not able to reproduce it locally either. Perhaps the NSInternalInconsistencyException could report the offending bundle?

levigroker added a commit to levigroker/Parse-SDK-iOS-OSX that referenced this pull request Aug 3, 2016
This will help track down the issue should this assert arrise. See @levigroker’s comments in parse-community#967
@levigroker
Copy link
Contributor

#1000

@zadr
Copy link

zadr commented Aug 25, 2016

I'm seeing reports this crash as well, on iOS 9 and iOS 10, also without being able to reproduce locally.

PhilJacobsen pushed a commit to CrowdTunes/Parse-SDK-iOS-OSX that referenced this pull request Sep 12, 2016
* parseOriginal: (211 commits)
  Parse 1.14.2 ☁️ (parse-community#988)
  Fixed crash when an NSBundle without executable is loaded (parse-community#981)
  Parse 1.14.1 ☁️ (parse-community#977)
  Fix not automatically registered subclasses of built-in subclasses of PFObject. (parse-community#976)
  Parse 1.14.0 ☁️ (parse-community#973)
  Update xctoolchain to latest.
  Improve code coverage for PFFileState.
  Update Carthage dependencies.
  Update gem dependencies.
  Update PFObjectState.m (parse-community#922)
  Added automatic PFObject subclass registration. (parse-community#967)
  Fix non-faulted task when loading installationId from persistence group fails. (parse-community#970)
  Remove no longer required bitcode flag for iOS.
  Update Travis-CI configuration to use macOS name.
  Update Rakefile to use macOS instead of OSX.
  Update all gems to latest.
  Update xctoolchain to latest.
  Update all xcode configurations to latest.
  Update Carthage dependencies.
  Update starter projects to use configuration-based initialization API. (parse-community#957)
  ...
@levigroker
Copy link
Contributor

We are still seeing this issue consistently. I've filed #1068

flovilmart pushed a commit that referenced this pull request Jun 19, 2017
This will help track down the issue should this assert arrise. See @levigroker’s comments in #967
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants