I get an error when I try to call objective-c method from swift.
my objective-c .h class:
#class myType;
#interface myClass : NSObject
- (myType *)myMethod;
then I will create an object form myClass and try to call myMethod in swift (I have declared anObject of type myClass):
let a = anObject.myMethod();
but I get an error:
Value of type 'myClass' has no member 'myMethod'
If I change myType to something else, the error goes away. So it should be a problem of not recognizing myType in swift..
I appreciate any help
#class myType;
is only a "forward declaration" of that class. In order to call the
- (myType *)myMethod;
method from either Objective-C or Swift, the compiler needs to know the
actual interface declaration of that class. So "myType.h" or whatever
file contains
#interface myType : NSObject
// ...
#end
must be included from the bridging header file.
Remark: Class names should start with a capital letter.
turned out the real problem for me was something else!
I had to simply delete the derived data:
Window -> Projects -> Derived Data -> Delete
Clean Project
Quit Xcode
Open Xcode
Build Project
Apparently, using swift I have to these steps more often..
Related
I am trying to use a method that was defined as Objective C method, from a swift file
the method in objective c is defined as
-(instancetype) init:(NSString*)string data:(id)data;
the method name cannot be refactored.
I am trying to invoke it as follows
let myObject = MyObject("MyString",data:["1","2","3"])
in return i am getting the compile error : "String! does not conform to protocol 'ExpressibleByStringLiteral'"
How can I fix it?
EDIT:
MyObject is defined as follows
`#interface MyObject<__covariant Type> : NSObject #end
#implementation
#end`
In Swift 3, ObjC generics are imported as Swift generics. And you always need to specify the type parameter in Swift generics. (And Swift 3 is not yet so refined as to generate appropriate diagnostics...)
let myObject = MyObject<NSString>("MyString",data:["1","2","3"])
worked.
Is your data actually data, or a [String]?
I am working on an existing large codebase that is predominately Objective-C but is in the process of converting to Swift.
New classes are being implemented in Swift, but some of these classes need to be accessed from existing ObjC code. In an attempt to follow both ObjC and Swift best practices, the new classes do not have a prefix, but are defined with a prefix for ObjC.
/**
Create contrived class that is named XXClassA in ObjC and ClassA in Swift.
*/
#objc(XXClassA) class ClassA: NSObject {
let foo = "bar"
}
So far this has been working great; Swift code uses ClassA() and ObjC uses [[XXClassA alloc] init]. Once all ObjC code that references XXClassA is removed, #objc(XXClassA) can also be removed from the Swift class.
Unfortunately this breaks down if you have an ObjC class reference XXClassA and then the Swift code attempts to use that new class inside of ClassA.
Say I create an ObjC class, named XXClassC and it instantiates itself using an XXClassA (which is really the Swift class ClassA)
//
// XXClassC.h
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#class XXClassA;
#interface XXClassC : NSObject
-(instancetype)initWithA:(XXClassA *)classA;
#end
NS_ASSUME_NONNULL_END
The circular reference is now in place. If I attempt to use XXClassC from inside of the ClassA, the initializer is not available.
If I redefine ClassA as this instead, all is well again.
class XXClassA: NSObject {
let foo = "bar"
}
I understand why this is happening and the fix I have in place, however I want to continue to use this pattern of prefixed ObjC classes. Any ideas on how to avoid the circular import, but also keep the naming convention?
Full code sample here: https://gist.github.com/justAnotherDev/78483f9d94e40fd90c38
I'm having the same problem. My workaround is:
Use an objc-style prefixed name for the Swift class.
Add a typealias: typealias ClassA = XXClassA.
Always use the unprefixed name from Swift code.
With this pattern it's at least easy to remove the prefix when the last objc dependency is gone.
I'm working on a obj-c project and I want to implement the NSCoding protocol for a class, but I can't get it right. The code looks like this:
#include <Foundation/Foundation.h>
class Object: NSObject, NSCoding {
//Somecode
}
And I get the error: "Base specifier must name a class" and "Expected class name". What am I doing wrong?
You are declaring a C++ class, not a Objective-C one, and you cannot have inheritance from one language to another. You'll need to change your class declaration to something like
#interface Object: NSObject <NSCoding> {
// iVar declarations
}
// method and property declarations
#end
Although not sure how much it will help if your class already has defined C++ methods, as you'll need to port those one to Objective-C definitions.
I highly recommend you go through the link I posted in my comments, and read Apple's documentation on working with classes and objects. This will help you with the transition.
I cannot compile my because of this error in my header:
error: expected identifier [1]
-(void) removeAllEntitiesOfClass:(Class)class;
with the caret pointing to the lowercase class.
Removing this function makes it compile again.
My class is a subclass of NSObject, which has public methods that use Class, so I thought this would automagically be declared.
I also tried changing Class to Class* and forward declaring with #Class Class, and this doesn't work - it says it is a redefinition because I am changing the type. Apparently Class is a typedef'd struct pointer. I'm not sure how to forward declare that here, and I seem to recall it can be nasty business to forward declare a pointer typedef. Please correct me if I'm wrong, and tell me what file to import or how to forward declare.
#interface GameState : NSObject {
...
}
...
-(void) removeAllEntitiesOfClass:(Class)class;
#end
I suspect your header is visible in an Objective-C++ translation. In C++, class is a keyword. To fix this, change the parameter's name from class to some non-keyword.
I'm receiving the following warning:
Instance method 'method name' not found (return type defaults to 'id')
when this code is invoked:
#protocol SomeProtocol <NSObject> {
#property (nonatomic, retain) SpecificClassName* someDelegate;
}
...
+ (void) aMethod : (id <SomeProtocol>) object {
[object.someDelegate doSomeThing]; // warning statement show up here
}
I feel like this is a short coming of the compiler at this point, but that just may be the pot calling the kettle black ... does anyone have any feedback on this?
You need to #import the header file for SpecificClassName, in your implementation (.m file).
If you're going to use the type name SpecificClassName in the header file, a forward declaration #class SpecificClassName will do, but calling a method on the class requires the compiler to know the return type of the method.
If you want to call a method on an instance of SpecificClassName, include the header in which it's defined.
I means that the header file for the class doesn't include the method signature. So the compiler can't tell if the method is actually there. Fix the header file to get rid of the warning.
In Java or C++, this would be a compilation failure. That's because they do method binding at compile-time, so the compiler needs to find the methods. Objective-C does it at run-time; it sends a method call to an object, and the object may or may not have such a method.