How to change the namespace of a Swift class?

2.1k Views Asked by At

When you implement a class MyGreatClass in Swift its fully qualified name will by <MyPackageName>.MyGreatClass. This is different to Objective-C, where the fully qualified name of that same class is MyGreatClass.

Unfortunately this introduces a problem for me. When I am using NSUnarchiver and the archive was written with Objective-C objects I cannot unpack it with Swift-classes(see below for a detailed description).

This means I need to find a way to rename the namespace for my Swift classes. How do I do that?

Any help would be great!

Background: Why can't NSUnarchiver see/load my swift class?

I have implemented a small program to read a file, which was archived with NSArchive.
These are my files:

main.swift:

import Foundation

// parse command line - total path to *.trace file (from Apple's Instruments app)
var traceFilePath = Process.arguments[1]

var traceFile = NSURL(fileURLWithPath: traceFilePath)
var error:NSError?

// check if the file exists
if (traceFile?.checkResourceIsReachableAndReturnError(&error) == false){
    // file does not exist or cannot be accessed
    println("\(error)")
    exit(1)
}

var rawData = NSData(contentsOfURL: traceFile!)
var data = NSUnarchiver(forReadingWithData: rawData!)
var decodedObject: AnyObject? = data?.decodeObject()

XRObjectAllocRun.swift:

import Foundation

class XRObjectAllocRun: NSObject {
    // class to be implemented   
}

When I now run my application on an Instruments-file I am getting the following error: Terminating app due to uncaught exception 'NSArchiverArchiveInconsistency', reason: '*** class error for 'XRObjectAllocRun': class not loaded'.

This is really strange because when I add the exact same class in an Objective-C file with a bridging header file I have no issues.

trace file reader-Bridging-Header.h: is empty.

XRObjectAllocRun.h:

#import <Foundation/Foundation.h>
@interface XRObjectAllocRun : NSObject
@end

XRObjectAllocRun.m:

#import "XRObjectAllocRun.h"
@implementation XRObjectAllocRun
@end

What am I missing? Why is my Objective-C class found, whereas my Swift class is not? Swift has no issues for example with var x = XRObjectAllocRun() in main.swift, but yet the NSUnarchiver still complaints about a missing XRObjectAllocRun class when I stay purely within Swift. Is the NSUnarchiver looking in the wrong places - does it for some reason only accept Objective-C classes?

If you want to know what I am trying to do check this stackoverflow question out.

Update

This is what apple writes:

Swift classes are namespaced based on the module they are compiled in, even when used from Objective-C code. Unlike Objective-C, where all classes are part of a global namespace

Further more:

For example, when you create a document–based Mac app, you provide the name of your NSDocument subclass in your app’s Info.plist file. In Swift, you must use the full name of your document subclass, including the module name derived from the name of your app or framework.

Yikes, trying to figure out the mess now...

1

There are 1 best solutions below

1
On BEST ANSWER

Try this when you declare your class:

@objc(XRObjectAllocRun) class XRObjectAllocRun: NSObject {
    // class to be implemented   
}

That will give this class the same name as the archived class, namely XRObjectAllocRun, instead of the namespaced Swift name trace_file_reader.XRObjectAllocRun.

This is always a concern when you're translating from Objective-C to Swift and you've got an existing archive to deal with. See Apple's documentation:

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html

Note the discussion under "Exposing Swift Interfaces in Objective-C".