Reputation: 6393
Some small steps to begin wrapping my head around Swift. I've basically ported an old class that simply finds the matching icon for a name and return the appropriate UIImage. The Swift part of things seems to be up and running, and looks (almost) like this:
@objc class ImageHandler{
func iconForData(data: MyData) -> UIImage{
let imagesAndNames = [
"1": "tree.png",
"2": "car.png",
"3": "house.png",
"7": "boat.png",
]
var imageName: String? = imagesAndNames[data.imageName]
if !imageName{
imageName = "placeholder.png"
}
let icon = UIImage(named: imageName)
return icon
}
}
There are no warnings on the above. My old Objective-C class is however asking for an alloc method on the swift class.
ImageHandler *imageHandler = [ImageHandler alloc] init];
Returns the error "No known class method for selector 'alloc' which is true enough I guess, but how do I escape this? Will I have to base my swift-class of NSObject to avoid this?
Upvotes: 23
Views: 18611
Reputation: 345
If we want to import swift file in Objective C, Should do
in Objective C file. Then can access alloc, init for specific imported swift class in Objective C.
Upvotes: 1
Reputation: 325
This answer is if you want to keep using pure swift objects, and do not want to inherit from NSObject. If you don't care about using pure swift objects then use akashivskyy's answer above.
I came across this same issue. I took Logan's answer and modified it so that the Objective-C caller does not have to change behavior. This is especially important if you are doing like I am and building a framework that could be consumed by Objective-C or Swift projects.
@objc public class TestClass {
public init(){}
public class func alloc() -> TestClass {return TestClass()}
}
The Objective-C implementation gets to stay familiar.
TestClass *testClass = [[TestClass alloc] init];
Swift implementation stays the same as well.
let testClass = TestClass()
Edit: Furthermore I went on to implement this into an class that can be subclassed by other pure swift objects.
@objc public class ObjectiveCCompatibleObject {
required public init(){}
public class func alloc() -> Self {return self()}
}
Upvotes: 4
Reputation: 122538
You could do this:
ImageHandler *imageHandler =
[[NSClassFromString(@"YourProjectName.ImageHandler") alloc] init];
(or, if you had done @objc(ImageHandler) class ImageHandler
in Swift, you would do [[NSClassFromString(@"ImageHandler") alloc] init]
)
Alternately, you can declare (but not implement) a dummy category containing the alloc
method at the top of your Objective-C file:
@interface ImageHandler (Dummy)
+ (instancetype)alloc;
@end
And then you can directly use it in your code:
ImageHandler *imageHandler = [[ImageHandler alloc] init];
Upvotes: -1
Reputation: 53142
Just wanted to comment here that if you don't want to subclass NSObject
or any other ObjC object, you can declare a class level initializer:
@objc class ImageHandler{
class func newInstance() -> ImageHandler {
return ImageHandler()
}
func iconForData(data: MyData) -> UIImage{
let imagesAndNames = [
"1": "tree.png",
"2": "car.png",
"3": "house.png",
"7": "boat.png",
]
var imageName: String? = imagesAndNames[data.imageName]
if !imageName{
imageName = "placeholder.png"
}
let icon = UIImage(named: imageName)
return icon
}
}
Then in ObjC
ImageHandler * imageHandler = [ImageHandler newInstance];
This way, you don't have to be dependent on ObjC Class inheritance unless you want to.
Upvotes: 25
Reputation: 45220
You declare your ImageHandler
class as a root class. It doesn't have alloc
method itself. You need to inherit from NSObject
:
@objc class ImageHandler : NSObject {
...
}
Referenced from this ADF thread.
Upvotes: 49