Object C, Public Functions and Classes - objective-c

Brand new to objective C, have been working on some Swift, converting some reusable files into an importable framework. For swift, I mostly only had to make the classes as well as some functions public so that they could be accessed when imported as a framework, how is this achieved in objective C? (& how are bridging files handled when this is done) Thanks!

In Objective-C, you generally define the #interface in a .h file and include any public methods and properties in that .h file. And then to expose those in your framework, you #include that .h file in the umbrella header. Or, if including this in Swift project, you'd import that .h file in the bridging header.
Define any private properties or ivars inside a private class extension inside the .m file. That keeps them from being exposed in the .h file.

Related

Exclude Swift Class from Bridging Header

In a Swift project that has mixed Obj-C and C++, I have a class that extends the class belonging to a 3rd party framework. When I compile the project, the compiler complains that it Cannot find interface declaration for '<Framework Class Name>', superclass of '<My Subclass Name>'
The semantic error points to the auto-generated bridging header ('MyProjectName-Swift.h').
Is there a way to not have a particular class included in the bridging header besides marking it private or fileprivate? (Which makes the subclass not much use in the rest of the project..) I've looked through the Apple docs on this matter and there doesn't seem to be any specific direction on this.
Alternatively, any clues as to how to fix this? The header includes this bit:
#if __has_feature(modules)
#import UIKit;
#import Material;
#import CoreGraphics;
#import ObjectiveC;
#endif
Which seems like it should make the proper reference to the superclass (in this case, if it matters, Material.PresenterCard) But — I'm pretty sure this pre-compiler directive isn't being referred to as I've heard of a related bug.
I recently had a very similar problem and solved it by defining an empty Objective-C class for the case where modules weren't available.
My situation was App -> Framework -> Package (Swift Package)
Framework implemented DerivedClass, which subclassed BaseClass defined in Package
When importing Framework-Swift.h internally or externally within any Objective-C++ code, the compiler would complain that BaseClass could not be found in the generated header
I solved this by adding the following code to Framework's umbrella include (Framework.h):
#if !__has_feature(modules)
#interface BaseClass: NSObject
#end
#endif
So when modules are unavailable (Objective-C++), BaseClass is defined as an empty Objective-C class. This allowed the framework to be imported into Objective-C++ code to use other features of the framework

How do .swift files keep the 'privacy' which the .h and .m files did in Obj-C

I have just started to shift from Obj-C to Swift in Xcode.
My question is about the new .swift files which replace the .h and .m files. The answers to this question partially tells me the differences, but I am still puzzled by the issue of 'privacy' with the new .swift file.
If I look up the definition of a class in Obj-C, I will be only be able to view the .h file (#interface) which contains the declaration of the class, its variables and methods. I cannot view the .m file (#implementation) which contains the code which controls how the class works (they are private which stops others from seeing/possibly plagiarising your code, I guess).
However, in Swift, it seems that something such as:
class NewClass: ParentClass {...}
creates a class in one go without the need for 2 sections - the #interface and #implementation. But when I look up the definition of a class (say, SKScene) in Swift, the code for the methods, etc, are still kept private somehow... How is this done?
The same situation in which you only see header files (e.g. a pre-compiled framework) will, with Swift, only make the interface available. The Swift files themselves will not be included in the framework. Instead, Xcode will generate pseudo-interface files that will be visible to users of the framework. You get property definitions and method signatures, but no implementations.

In Swift how do I declare a reference to a global pointer that's declared in objective-c code?

My App is objective-c origin, with all new files being Swift. My main.m file has:
ConfigMgr* configMgr;
All my objective-c (.m) files have:
extern ConfigMgr* configMgr;
It's a global pointer because everyone needs to access some info about the configuration. (It's my only global and I make no apology for it.) So what do I add to my Swift files to be able to access this instance of this object as well, by using the global, not passing a pointer to every .swift file? (My main concern is to make sure I don't end up instantiating another ConfigMgr object.)
Assuming that the interface of the ConfigMgr class is declared in ConfigMgr.h, include the following in the bridging header:
#import "ConfigMgr.h"
extern ConfigMgr* configMgr;
You should be good to go!

Access KeychainAccess methods from Objective-C

I have an Objective-C project and this project uses KeychainAccess (Swift project) on some of my Swift file. However, I do have the need to access KeychainAccess on some of my Objective-C file as well.
I imported the following:
#import "MyProject-Swift.h"
#import KeychainAccess;
I can't seem to reference KeychainAccess classes besides: KeychainAccessVersionNumber and KeychainAccessVersionString
What do I need to do to use its classes?
Thanks

How can I add forward class references used in the -Swift.h header?

I'm integrating Swift code into a large Objective-C project, but I'm running into problems when my Swift code refers to Objective-C classes. For example, suppose I have:
An Objective-C class called MyTableViewController
An Objective-C class called DeletionWorkflow
I declared a Swift class as follows:
class DeletionVC: MyTableViewController {
let deleteWorkflow: DeletionWorkflow
...
}
If I now try to use this class by importing ProjectName-Swift.h into Objective-C code, I get undefined symbol errors for both MyTableViewController and DeletionWorkflow.
I can fix the problem in that individual source file by importing DeletionWorkflow.h and MyTableViewController.h before I import ProjectName-Swift.h but this doesn't scale up to a large project where I want my Swift and Objective-C to interact often.
Is there a way to add forward class references to ProjectName-Swift.h so that these errors don't occur when I try to use Swift classes from Objective-C code in my app?
You can create another header file that forward declares or imports the necessary classes, and then imports ProjectName-Swift.h. For example, create a file named ProjectName-Swift-Fixed.h with the contents:
// ProjectName-Swift-Fixed.h
// Forward declarations for property classes
#class DeletionWorkflow;
// Imports for superclasses
#import "MyTableViewController.h";
#import "ProjectName-Swift.h"
Then, instead of #import "ProjectName-Swift.h" in your codebase, use #import "ProjectName-Swift-Fixed.h.
This is a little silly, but it sounds like your "workaround" is what Apple intended, at least for now. From the interoperability guide:
If you use your own Objective-C types in your Swift code, make sure to import the Objective-C headers for those types prior to importing the Swift generated header into the Objective-C .m file you want to access the Swift code from.
In this devforums thread, someone mentioned they already filed a bug in Radar. You probably should too.