Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Objective-C load class method?

In Objective-C, NSObject had a class method called load that gets called when the class is loaded for the first time. What is the equivalent in Swift?

@implementation MyClass

+ (void)load
{
   [self registerClass];
}

@end
like image 790
aryaxt Avatar asked Jul 22 '14 21:07

aryaxt


4 Answers

Prior to Swift 1.2:

override class func load() {
   NSLog("load");
}

EDIT:

As of Swift 1.2 you can no longer override the load method. Look into the method initialize instead, it behaves different than load though, it get's called the first time the class is being referenced somewhere rather than on application initial load

like image 164
aryaxt Avatar answered Oct 29 '22 02:10

aryaxt


Support for overriding load was removed in Swift 1.2

like image 41
Eric Avatar answered Oct 29 '22 04:10

Eric


Update: Starting from Swift 5 class extensions and categories on Swift classes are not allowed to have +load methods, +initialize doesn’t seem to be prohibited, though.

While direct equivalent is not available with Swift, this can be achieved relatively elegantly with Objective-C and categories. Foo should still inherit from NSObject and have a class / static non-private swiftyLoad/Initialize methods, which get invoked from Objective-C in Loader.m, which you include in compile sources alongside Foo.swift:

# Loader.m

#import <Foundation/Foundation.h>
#import <MyProject/MyProject-Swift.h>

// This was a more concise solution in Swift 4.2 and earlier. If you try
// this with Swift 5 you'd get "Swift class extensions and categories
// on Swift classes are not allowed to have +load methods" runtime error.

// @implementation Foo (private)
//     + (void)load { [self swiftyLoad]; }
//     + (void)initialize { [self swiftyInitialize]; }
// @end

// This is what you'd want to use with Swift 5 onwards, basically 
// just a pure Objective-C defined class.

@interface Loader : NSObject
@end

@implementation Loader : NSObject
    + (void)load { [Foo swiftyLoad]; }
    + (void)initialize { [Foo swiftyInitialize]; }
@end


# Foo.swift

import Foundation
public class Foo: NSObject {
    @objc public static func swiftyLoad() {
        Swift.print("Rock 'n' roll!")
    }
    @objc public static func swiftyInitialize() {
        Swift.print("Hello initialize!")
    }
}

The best part there's no need to mess with bridging headers or anything else, it just works. There are couple of gotchas, especially when using this approach in static libraries, check out the complete post on Medium for details! ✌️

like image 4
Ian Bytchek Avatar answered Oct 29 '22 04:10

Ian Bytchek


in Swift 2.0, Please use this method

public override class func initialize()
like image 1
Alix Avatar answered Oct 29 '22 04:10

Alix