getting Swift Object from Objective C class using another Swift File - objective-c

I have been trying with no success the following structure:
ClassA.swift
class ClassA:NSObject{
var varA = ""
}
then I have a ClassB.h and ClassB.m (Objective c) and I am not able to define "Project-Swift.h" in the .h file so i import it into the .m
#interface ClassB()
#property ClassA *myClassA;
#end
and
#synthesize myClassA = theAClass;
The problem comes when I try
class ClassC:NSObject{
let theClassAFromC = ClassB.myAClass
}
I get an error message Value of type 'ClassB' has no member 'theClassA'

Add your objc header to bridging header
In your objc header use #class notation for your swift class, e.g. #class ClassA;, instead of import "Project-Swift.h" file. You can import that one in your objc implementation file.
Don't forget that you cannot access non-static property of objc class the way you're declaring. Instead, initialize your ClassB object in your swift class and access it's property when needed. For instantiating the ClassA object you can use dependency injection in ClassB
As part of the convenience, use #objc declaration for your Swift classes accesible to objc runtime

try to search with keyword "Bridging-Header" and then add
#import "ClassB.h"
That does not work in my case.
adding ClassB.h in my Bridge File makes properties from .h Visible But not the the properties in my .m file. If i add Class.m In my header file then Module-Swift.h is not found

Related

#interface and #implementation in same file (no header file, Xcode unit test template)

Xcode generates this template code for a new Objective-C test case. Why does it not generate a header file and puts the #interface in the implementation file?
#import <XCTest/XCTest.h>
#interface BYObjCTest : XCTestCase
#end
#implementation BYObjCTest
// test methods
#end
How is this construct called? Is this a private class? Test cases are generally not needed to be called from outside of user code, is this the reason this is generated this way?
It's ok to have the interface ClassName : Superclass block (called the class declaration block) in a .m file.
Declaring a class in a Header (.h) file is more common because it's for class that needs be public (class that will be used in other class), but if your class is not meant to be used in outside of the .m file, then it's ok to have the declaration and implementation in the same .m or .mm file.
In the test of TestClass for example, they are not used anywhere else,so no need for a header.
Other language would call those private class. Well private class in objC have no .h file :)

Are methods declared in categories visible to other classes

Suppose I have the following
FileName : DBManager.h
#import <Foundation/Foundation.h>
#interface DBManager : NSObject
//Notice no method is declared here
#end
Now its implementation file looks like this
FileName: DBManager.m
#import "DBManager.h"
#interface DBManager()
+ (DBManager*) SomeMethod;
#end
#implementation DBManager
+ (DBManager*) SomeMethod
{
....
return SomePtr;
}
#end
Now in some other class method if I do the following
[DBManager SomeMethod] ; //Error No known class method for selector 'SomeMethod'
However if SomeMethod is declared inside the .h file inside of category then this works fine. I wanted to know if this was a limitation of categories that the methods are not visible to other classes ?
First, #interface DBManager() is not a category, it's a class extension. There's no identifier between the parentheses.
Second, the issue isn't visibility based on whether the method is declared in a class, category, or class extension, it's whether it was declared in the same translation unit.
A translation unit is a source file after the preprocessor has included/imported the header files (or whatever other files have been included/imported).
The error is telling you that the declaration of +SomeMethod was not declared in the translation unit. If it were, there'd be no error, regardless of whether it were declared in the class interface, a category, or a class extension.
It follows that if you declare the interface of a category in a header file and include the header file in a source file, you can use the methods declared by that category in that source file.

objective-c - Swift classes are not visible in Objective-C .h file

I'm trying to use Swift class in my Objective-C file.
I included "moduleName-Swift.h" file in my SuperViewController.m file, but when I try to declare a public method in SuperViewController.h with Swift-class as method parameter, I obviously get an error: "Expected a type"
How can I use swift-class in a header file if I can only include projectModule-Swift.h in .m files??
Make sure to put #objc before the swift class name.
#objc myclassname { ... }
Also add
#class myclassname;
in your obj-c header file where you want to access the swift class
Remember to import the project generated swift header file in your source file, for example #import <MyProjectName-Swift.h>
I had the same problem. Adding #class MyClassName in obj-c .h file created the "Receiver 'MyClassName' for class message is a forward declaration" error, so I deleted that and ONLY added the "#objc" before the swift class name, BUT I also had to make sure that the swift class is a subclass of NSObject.
#objc class MySwiftClass:NSObject { ... }
WITHOUT #class MyClassName in obj-c .h file!
I had to use:
#obj public class MySwiftClass: NSObject { ... }
I created a class with no subclass, adding #objc and #objcmembers did not work.
After I change do :NSObject the entire class turn visible to objective-C

Swift class using Objective-C class using Swift class

I have an obj-c project to which I successfully added a new Swift class A, which is being used by some existing obj-c class B - the use of the automatically generated "MyProject-Swift.h" header worked as expected.
I also successfully added a new Swift class C that uses some existing obj-c class D - the use of the bridging header also worked as expected.
However, suppose I want to refer from my Swift class C to the existing obj-c class B (which in turn refers to the new Swift class A). In order to do that I need to import "B.h" to the bridging header. However, if I do that I get an error in class B: "'MyProject-Swift.h' file not found" (i.e., the file is no longer generated).
Am I doing something wrong or is this a kind of interaction between Swift and Objective-C that is not allowed? It looks like there is a kind of circular reference that the compiler is unable to solve.
--- EDIT ---
I'll try to make the question clearer by adding some code.
-- PREAMBLE --
I added a new Swift class to an obj-c project:
// SwiftClassA.swift
import Foundation
#objc class SwiftClassA : NSObject {
var myProperty = 0
}
The code compiles correctly and is translated into obj-c stubs in the automatically generated "MyProject-Swift.h" header like so:
// MyProject-Swift.h
...
SWIFT_CLASS("_TtC7MyProject11SwiftClassA")
#interface SwiftClassA : NSObject
#property (nonatomic) NSInteger myProperty;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
#end
Now, one obj-c class uses SwiftClassA:
// ObjCClass.h
#import <Foundation/Foundation.h>
#import <MyProject-Swift.h>
#interface ObjCClass : NSObject
#property (nonatomic, strong) SwiftClassA *aProperty;
#property (nonatomic) int *aNumber;
#end
This also works seamlessly.
-- THE QUESTION --
Can I now create a new Swift class that refers to the obj-c class (ObjCClass) that is using the Swift class SwiftClassA?
This is what I can't do.
If I add the new Swift class:
// SwiftClassB.swift
import Foundation
#objc class SwiftClassB : NSObject {
var aPropertyOfClassB = 1
func someFunc() {
var objCObject = ObjCClass()
var theProperty = objCObject.aProperty
print("The property is \(theProperty)")
}
}
this of course won't compile because of "Use of unresolved identifier 'ObjCClass'". So I need to add that to the bridging header file:
// BridgingHeader.h
#ifndef MyProject_BridgingHeader_h
#define MyProject_BridgingHeader_h
...
#import "ObjCClass.h"
#endif
However, if I do that, the ObjCClass.h file won't compile giving a "'MyProject-Swift.h' file not found".
I've read in several places (with no example, though) that this may mean that there is a circular reference and that a forward reference using #class could solve the problem. However, I'm not sure what needs to be forward referenced and where, and all my attempts failed.
I hope the question is no longer confusing now!
This is a typical cyclical referencing problem.
Be careful to read the docs:
To avoid cyclical references, don’t import Swift into an Objective-C header file. Instead, you can forward declare a Swift class to use it in an Objective-C header. Note that you cannot subclass a Swift class in Objective-C.
So, you should use "forward declare" in .h, and #import in .m:
// ObjCClass.h
#import <Foundation/Foundation.h>
#class SwiftClassA;
#interface ObjCClass : NSObject
#property (nonatomic, strong) SwiftClassA *aProperty;
#property (nonatomic) int *aNumber;
#end
// ObjCClass.m
#import "ObjCClass.h"
#import "MyProject-Swift.h"
#implementation ObjCClass
// your code
#end

Cocoa: Build Warning that s Forward Declared Class's and #interface May not Exist

I am trying to build the Clustering Plug in my project under Leopard. I have following two questions.
In the project an interface class is defined as
#interface ClusteringController : NSWindowController
{
.......
.....
....
}
#end.
And this class is used in implementation class using forward declaration:
#class ClusteringController;
then in one function it is used as:
- (long) filterImage:(NSString*) menuName
{
ClusteringController *cluster = [[ClusteringController alloc] init];
[cluster showWindow:self];
return 0;
}
When I build this project it produces the warning:
warning: receiver 'ClusteringController' is a forward class and corresponding #interface may not exist
Also there is one more warning produced:
warning: no '-updateProxyWhenReconnect' method found
This warning is coming for the following line of code:
if(delegate) [delegate updateProxyWhenReconnect];
Can anybody help me to overcome these warnings?
A forward declaration is used when the header file will be imported after the interface. It looks to me that you've used the #class directive after the interface for the class itself.
The normal use of a forward class declaration looks like this:
#import "SomeSuperClass.h"
#class Forwardclass;
#interface SomeClass : SomeSuperClass
{
Forwardclass anIvar;
}
#property Forwardclass anIvar;
#end
#import "SomeClass.h"
#import "ForwardClass.h"
#implementation SomeClass
#synthesize anIvar;
-(void) setAnIvar:(ForwardClass *) aForwardClass;
#end
The #class directive is never used in an implementation (.m) file.
That's not what #class is for.
You use #class in the header file for another class, to tell the compiler that the class you're declaring does exist. Without it, the compiler would not know that that's a class name, and when you declare a variable as holding a pointer to an instance of that class, the compiler would think that you're just making up words. Using #class is called forward-declaring the class.
Your situation is different. You're in the implementation file for that class.
What the compiler needs from you now is the class's #interface. The warning is telling you that the compiler needs an #interface, but you haven't given it one (so, as far it knows, the #interface “may not exist”).
Normally, you would have written the #interface in a header file; how now to get it into the implementation file?
That's where the preprocessor comes in, with its #import directive. At the top of the implementation file (ClusteringController.m), import the header file:
#import "ClusteringController.h"
The preprocessor will replace this with the contents of that file, then hand the preprocessed code to the compiler, which will see the #interface there.