28

I'm using Parse and I'm creating a PFObject subclass conforming to the protocol PFSubclassing! It was working all fine, but now I'm using Swift 1.2 and it gives me this error:

1. override class func load() {
2.      self.registerSubclass()
3. }

On line 1: Method 'load()' defines Objective-C class method 'load', which is not permitted by Swift 1.2

Anyone have this problem yet? How can I fix?

txaidw
  • 485
  • 4
  • 13
  • You are really saying `function` instead of `func`? Is this some kind of Parse thing? – matt Feb 10 '15 at 02:55

5 Answers5

20

There is an NSHispster article about method swizzling that touches on this in different context:

Unfortunately, a load class method implemented in Swift is never called by the runtime, rendering that recommendation an impossibility. Instead, we're left to pick among second-choice options:

  • Implement method swizzling in initialize. This can be done safely, so long as you check the type at execution time and wrap the swizzling in dispatch_once (which you should be doing anyway).

  • Implement method swizzling in the app delegate. Instead of adding method swizzling via a class extension, simply add a method to the app delegate to be executed when application(_:didFinishLaunchingWithOptions:) is called. Depending on the classes you're modifying, this may be sufficient and should guarantee your code is executed every time.

Link: http://nshipster.com/swift-objc-runtime/

-

More info form dev forums:

Swift 1.1 allowed you to define "+load" methods with "class func load()", but they were not actually run at startup time of your app like Objective-C +load methods are. Swift 1.2 bans them to avoid the impression that this might work.

Link: https://devforums.apple.com/message/1102025#1102025

-

tl;dr initialize() and didFinishLaunchingWithOptions seem to be decent places for such things in Swift.

Nikita Kukushkin
  • 14,648
  • 4
  • 37
  • 45
9

Try this :

override class func initialize() {
   var onceToken : dispatch_once_t = 0;
   dispatch_once(&onceToken) {
      self.registerSubclass()
   }
}

The Parse documentation has been updated : https://www.parse.com/docs/ios/guide#objects-subclassing-pfobject

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
7

I'm calling registerSubclass() method in AppDelegate before Parse.setApplicationId for every subclass of PFObject and it works.

egor.zhdan
  • 4,555
  • 6
  • 39
  • 53
7

Overriding load() never worked with Swift. Earier it was simply not called. I filed a bug for Apple back then (Bug ID 18423731), and recently I got a response that the issue has been addressed by explicitly informing the developer that this is not allowed in Swift.

extension UIButton {
    // !! never called
    override public class func load() { // Method 'load()' defines Objective-C class method 'load', which is not permitted by Swift 1.2
        super.load()
        println("not called earlier anyway");
    }
}

So.... don't. Even if the documentation says otherwise.

matt
  • 515,959
  • 87
  • 875
  • 1,141
Marcin
  • 3,694
  • 5
  • 32
  • 52
5

I got it working by replacing it with:

override class func initialize() {
}
ashokgelal
  • 80,002
  • 26
  • 71
  • 84
  • 4
    Note that `+load` and `+initialize` are different. `+load` runs at the time the binary is loaded, regardless of whether the class is used; and you can have multiple `+load` methods -- one in each category in addition to the main one -- all without interfering with each other (normally category methods replace existing methods with the same name). `+initialize`, on the other hand, runs lazily when the class is messaged for the first time. – newacct Feb 10 '15 at 02:58
  • @newacct Do you know the equivalent of load() In Swift? For now I'm leaving the comment above as the answer because it solve my problem for now – txaidw Feb 10 '15 at 03:06