Any way to use a plain Swift class in Objective C files? - ios

This question isn't about bridging headers and all that. I've got all that working. My question is specifically about what I need to do to my Swift classes to get them to show up in Obj-C code.
Take, for example, this simple class:
class MyClass {
var value: String = ""
}
If I have this class in my Project, it doesn't get included in the MyProject-Swift.h file that gets auto-generated. My understanding is that in order to use a Swift class in Objective-C, my class needs to derive from a class that Objective-C knows about. This is where I start to doubt the actual requirements.
If my class were derived from a UIViewController, then no problem. But if this is just a model object, then it's not deriving from anything. While it is entirely possible to easily make my class derive from NSObject, and thus, it gets properly imported into the Obj-C code, deriving from NSObject can cause other issues down the road.
So if I don't want to make my class derive from NSObject, what can I do to make it visible to my Obj-C files? Is there a doc I just couldn't find that explains how to do this?

As far as I am aware currently, Only Swift classes that inherit from NSObject can be declared #objc and bridged into an Objective-C project.
Without that conformance/inheritance, you'll end up missing some crucial functionality to Objective-C like message sending.
All of that being said, an Objective-C class has to inherit from a parent class and the default root class is NSObject. You almost definitely want to just inherit and make your class a PONSO.

Related

Question about Importing Swift code into objective c code

I read this documentation for importing swift code into objective c.
https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c
I have a few questions.
Can I put #objc annotation for a Struct?
Do I need to inherit all the class that I want to export to obj to be child of NSobject ? I am getting error 'error: only classes that inherit from NSObject can be declared #objc'
When I export a swift class with #objc, I need to add #objc to all its parent classes, protocol and interface and also class and structure in all its methods, is that correct?
No. Objective-C cannot see a native Swift struct.
Yes. Objective-C classes must basically be derived from NSObject. Objective-C can be made aware of the existence of other classes, but it cannot do anything useful with them.
You can mark the class with #objcMembers, in which case you will give everything within it full visibility to Objective-C.

Class prefixes in project with both objective-c and swift

I'm aware that we no longer need to prefix class names in swift. But I'm working on a project containing both swift and Objective-c.
Should I prefix the swift class names of keep them the "swift way"?
You can go ahead and keep it the Swift way. If you're worried about name-clashes and adding a prefix, you can change the Objective-C class name by adding #objc(...) before the class declaration.
E.g.
#objc(XXMyClass) class MyClass: ... {
...
}

#objc error when migrated to Swift 2

I had a Swift class declared like this:
#objc class MyHelper {
// class code
}
I had to do this to access such class from Objective-C classes, since I'm mixing languages in my project. Now that I upgraded to Xcode 7, I get this error:
Only classes that inherit from NSObject can be declared #objc
And such class is not known by my Objective-C classes anymore. I guess that then I should inherit my Swift class from NSObject, will that have any impact in the way the app was working?
Thanks
See the Apple staff SevenTenEleven's reply in the Apple Developer Forum.
He mentioned that this is because of #objc on Swift-rooted classes never quite behaved like an NSObject-rooted class, leading to various weirdness in the generated header and at runtime.
We can still treat any Swift class instance as an AnyObject, mark methods and properties on a Swift class as #objc, and conform to Objective-C protocols; the class just isn't exposed in the generated header and doesn't default to having its members available in Objective-C.

Swift build error (involving word "class" as argument) with subclassed Objective-C class

I have a build error when trying to subclass a custom Objective-C class (a subclass of UIViewController) in Swift.
When I try to subclass in Swift, I get the build errors in the picture below. All of them relate to the use of the word class as an argument in the OCMapper library (where I've opened an issue as well).
Some more notes:
In the project, I both import and use Objective-C code in the Swift code and import and use Swift code in the Objective-C code.
I import the compiled Module-Swift.h only in .m and .mm files and forward declare classes that I need in .h files.
I've attempted to create a Module-Swift-Fixed.h class where I forward declare and/or import the custom Objective-C class headers (as recommended here), but that hasn't made a difference.
Has anyone seen anything like this before or have a solution?
I have as yet not been able to trace where in the language spec this is documented, but I suspect you have come across the same problem that I recently faced in objective-c since moving to Xcode 6.4.
I had a message (method) defined as follows
- (BOOL)canProcessClass:(Class) class {
return [class isSubclassOfClass:[NSSet class]];
}
with the same compile error as you mentioned Expected identifier. The fix was simple - just rename the the class argument to something like classToProcess. Which would give you the following
- (BOOL)canProcessClass:(Class) classToProcess {
return [classToProcess isSubclassOfClass:[NSSet classToProcess]];
}
Hence just rename the arguments in your Swift code to not use the (key)word class and you should be fine.
If anyone can point me to the language spec that documents this I would really appreciate it. As far as I'm aware you shouldn't use Class, but I haven't able to find anything about class except the obvious that it is a message (method) available on classes.

Class Extension vs Header file [duplicate]

This question already has answers here:
Objective-C class extension
(5 answers)
Closed 9 years ago.
What exactly are class extensions and header files? What are the differences? What is the difference between declaring a property/method in a header file vs in a class extension. I am completely new to objective-c so beginner terminology would be beneficial :)
Thanks in advance!
As the name suggests, they extend the class. A class continuation is another name. The class extension is commonly used to declare private methods and properties. You want the class extension to be visible to the #implementation, and not in the header file (i.e. you want the class extension and #implementation to be in MONClass.m).
Types and methods in the header file are generally intended to be public -- available to any client.
Example: The property declared in the class extension will not be visible/accessible to clients who #import the header, but it will be usable by the #implementation because the #implementation can see the declarations of the class extension.
So this can be used to emulate restricted access for your ivars and methods. This is useful because ObjC methods and properties cannot be specified as private/protected/public (e.g. using #public).
Class extensions differ from categories primarily because extensions may declare storage (e.g. properties which will produce backing ivars).
A header file (.h) is where you would declare properties, methods, and protocols publicly in an existing class. You can then import this file and, of course, use it for your implementation.
An extension is another #interface in your implementation (.m) file. This extends the imported header's internal implementation, adding methods that would not be available should someone or something else import the header file associated with the class.
For more information, check out Apple's documentation on customizing existing classes
Q: What exactly are ... header files
A: Header file - is a file, content of which compiler 'inserts' instead of #import... (#include and other similar directives) line. Header files contains public code: forward declarations of classes, enums, variables, functions and other and other.
Q: What exactly are class extensions …
A: Class Extension - is a language construct, which allows you to extends the interface to the class.
To better understand what it is you must understand what is a class category.
Category - is a language construct, which allows you to add functionality (methods only!) to existing class. Even without subclassing.
Example:
You can add new method to NSImage:
#interface NSImage(YourExtensionName)
- (CGImageRef)CGImage;
#end
A Class Extension (also known as a class continuation, or unnamed category) bears some similarity to a category, but it can only be added to a class for which you have the source code at compile time.
In class extension you can use same things you use in a usual #interface block.
Q: What are difference
A: Header file uses for include to your program some ability (structures, data types, constants, functions and so one). Class extensions uses for extends existing class with some functionality. Usually, class extension is a private interface of a class. The functionality declared by a class extension are implemented in the #implementation block for the original class so you can’t, for example, declare a class extension on a framework class, such as a Cocoa or Cocoa Touch class like NSString.
Q: What is the difference between declaring a property/method in a header file vs in a class extension
A: If you declare property/method in header file, then any user of .h file can access to this property/method. Class extensions uses for declare private interface for you class.
I strongly recommend to you read Apple's Objective-C Programming Guide.

Resources