I've been upgrading my project to Swift2.
After resolving many errors, i got an error when i build the project.
The error is located in the Objective-V Generated Interface Header,
Xcode is printing this error Type argument 'CGColorRef' (aka 'struct CGColor *') is neither an Objective-C object nor a block type
Here is the code, the error is printed on the line between the **:
SWIFT_CLASS("_TtC519RadialGradientLayer")
#interface RadialGradientLayer : CALayer
**#property (nonatomic, copy) NSArray<CGColorRef> * __nullable colors;**
#property (nonatomic, copy) NSArray<NSNumber *> * __nullable locations;
#property (nonatomic) CGPoint center;
#property (nonatomic) CGFloat startRadius;
#property (nonatomic) CGFloat endRadius;
- (nullable instancetype)initWithCoder:(NSCoder * __nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)initWithLayer:(id __nonnull)layer OBJC_DESIGNATED_INITIALIZER;
- (void)drawInContext:(CGContextRef __nonnull)ctx;
+ (BOOL)needsDisplayForKey:(NSString * __nonnull)key;
#end
I guess that is link to this class
class RadialGradientLayer: CALayer {
var colors: [CGColor]? {
didSet {
self.setNeedsDisplay()
}
}
var locations: [CGFloat]? {
didSet {
self.setNeedsDisplay()
}
}
...
}
I didn't found any answer anywhere or even a clue so here i'm.
the error is trying to tell you that you can't have an NSArray contain primitive types.
you would get a similar error if you attempted to do something like this:
#property (nonatomic, strong) NSArray <Int>* intArray;
one way to fix this would be to make your swift class hold an array of UIColor instead of CGColor.
Related
I'm trying to declare a private property but I'm getting this error:
Unexpected '#' in program
Here is my implementation
#implementation MyClassImplementation
#property (nonatomic,strong) NSArray *new;
#end
Here is where I get the error #property (nonatomic,strong) NSArray *new; any of you knows why I'm getting this error or if there is a work around this?
I'll really appreciate your help
Private properties usually are declared in .m file in class unnamed category and for following Cocoa naming convention shouldn't use new keyword:
#interface MyClassImplementation ()
#property (nonatomic, strong) NSArray *array;
#end
#implementation MyClassImplementation
....
#end
I'm using a swift pod in an objective C project.
I successfully access swift classes from objective-c, anyway I'm facing an issue to adopt swift protocol.
The compiler does not complain, generated bridging header seems correct.
Problem occurs at runtime when calling [self.sceneLocationView setLocationNodeTouchDelegate: self]; that results in [ARCL.SceneLocationView setLocationNodeTouchDelegate:]: unrecognized selector sent to instance.
I cannot find any solution to this issue, I spent time to search here, but still no luck to make this working.
Any help would be greatly appreciated.
Thanks
My swift and objective-c files are shown below.
SceneLocationView.swift:
#available(iOS 11.0, *)
open class SceneLocationView: ARSCNView {
...
#objc public weak var locationNodeTouchDelegate: LNTouchDelegate?
...
}
SceneLocationViewDelegate.swift :
#objc public protocol LNTouchDelegate: class {
func locationNodeTouched(node: AnnotationNode)
}
ViewController.h :
#import "ARCL-Swift.h"
#interface ViewController : UIViewController <LNTouchDelegate>{
}
#property (nonatomic, strong) SceneLocationView *sceneLocationView;
ViewController.m :
#import "ARCL-Swift.h"
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.sceneLocationView = [[SceneLocationView alloc] init];
[self.sceneLocationView run];
[self.view addSubview: self.sceneLocationView];
...
[self.sceneLocationView setLocationNodeTouchDelegate: self]; <-- ERROR HERE
}
-(void) locationNodeTouchedWithNode:(AnnotationNode *)node {
}
ARCL-Swift.h :
SWIFT_PROTOCOL("_TtP4ARCL15LNTouchDelegate_")
#protocol LNTouchDelegate
- (void)locationNodeTouchedWithNode:(AnnotationNode * _Nonnull)node;
#end
SWIFT_CLASS("_TtC4ARCL17SceneLocationView") SWIFT_AVAILABILITY(ios,introduced=11.0)
#interface SceneLocationView : ARSCNView
#property (nonatomic, weak) id <LNTouchDelegate> _Nullable locationNodeTouchDelegate;
- (nonnull instancetype)init;
- (nonnull instancetype)initWithFrame:(CGRect)frame options:(NSDictionary<NSString *, id> * _Nullable)options OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
- (void)layoutSubviews;
- (nonnull instancetype)initWithFrame:(CGRect)frame SWIFT_UNAVAILABLE;
#end
I am unable to see the method/variable to set myVar to true from Objective C even tough I've added the #objc and public modifiers and there is no Bool in the setMyVarTrue() method's signature.
This is probably caused by the difference between Swift's Bool and Objective C's BOOL.
Other class methods/variables are visible, just this particular one isn’t.
How is is possible to set Swift's Bool from Objective C?
Swift code:
public class MyViewController : UIViewController {
public var myVar:Bool = false
#objc public func setMyVarTrue() {
self.myVar = true
}
}
Objective C code:
MyViewController* myViewController = [MyViewController new];
myViewController.myVar = true // Variable not found
myViewController.setMyVarTrue() // Method not found
[self presentViewController:myViewController animated:NO completion:nil];
You should do
add #objc to declaration of your class
add a file named "yourName-swift.h", which should containt #class yourClass;
import "yourName-swift.h" in Objective C file, where you want to call
your swift class
The solution was to clean and rebuild the project. Xcode generates the swift bridging header automatically and in my case it was stopping the build process with a (variable/method not found) error prior to regenerating the bridging header.
SWIFT_CLASS("_TtC11MyProject25MyViewController")
#interface MyViewController : UIViewController
#property (nonatomic, strong) MBProgressHUD * _Nonnull progressIndicator;
- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
- (void)viewDidLoad;
- (void)viewWillAppear:(BOOL)animated;
- (void)submitProgressHandler:(NSNotification * _Nonnull)notification;
- (void)submitSuccessHandler;
- (void)submitFailureHandler:(NSNotification * _Nonnull)notification;
- (void)subscribe;
- (void)unsubscribe;
#end
Now it works fine:
SWIFT_CLASS("_TtC11MyProject25MyViewController")
#interface MyViewController : UIViewController
#property (nonatomic, strong) MBProgressHUD * _Nonnull progressIndicator;
#property (nonatomic) BOOL closing;
- (nonnull instancetype)initWithNibName:(NSString * _Nullable)nibNameOrNil bundle:(NSBundle * _Nullable)nibBundleOrNil OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
- (void)viewDidLoad;
- (void)viewWillAppear:(BOOL)animated;
- (void)setClosingTrue;
- (void)submitProgressHandler:(NSNotification * _Nonnull)notification;
- (void)submitSuccessHandler;
- (void)submitFailureHandler:(NSNotification * _Nonnull)notification;
- (void)subscribe;
- (void)unsubscribe;
#end
I'm binding a iOS SDK. But the Sharpie confused about this
#interface ALBBQuPaiService : NSObject<ALBBQuPaiService>
The last ALBBQuPaiService is #protocol ALBBQuPaiService
I have tried to change ApiDefinition code like this:
[Protocol(Name = "ALBBQuPaiService"), Model]
interface ALBBQuPaiServiceProtocol
{
...
}
[BaseType (typeof(NSObject), Name = "ALBBQuPaiService")]
interface ALBBQuPaiService : ALBBQuPaiServiceProtocol
{
// +(instancetype)sharedService;
[Static]
[Export ("sharedService")]
ALBBQuPaiService SharedService ();
// #property (nonatomic, weak) id<QupaiSDKDelegate> _Nullable delegte;
[NullAllowed, Export ("delegte", ArgumentSemantic.Weak)]
QupaiSDKDelegate Delegte { get; set; }
}
Finally, I got runtime time exception: unrecognized selector sent to instance 0x7c73f740
Any body can help me? Thanks in advance.
My SDK link
------------------- Update 1: add header file code -------------------------
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger,QupaiSDKWatermarkPosition){
QupaiSDKWatermarkPositionTopRight,
QupaiSDKWatermarkPositionBottomRight,
};
typedef NS_ENUM(NSInteger,QupaiSDKCameraPosition){
QupaiSDKCameraPositionBack,
QupaiSDKCameraPositionFront,
};
#protocol QupaiSDKDelegate;
#protocol ALBBQuPaiService
-(NSString *) getSdkConfigVersion:(NSString *) platformName
sdkVersion:(NSString *) sdkVersion;
-(void) getSdkConfigVersion:(NSString *) platformName
sdkVersion:(NSString *) sdkVersion
success:(void (^)(NSString *rpcResult))success
failure:(void (^)(NSError *rpcError))failure;
#property (nonatomic, weak) id<QupaiSDKDelegate> delegte;
#property (nonatomic, assign) BOOL enableBeauty;
#property (nonatomic, assign) BOOL enableImport;
#property (nonatomic, assign) BOOL enableMoreMusic;
#property (nonatomic, assign) BOOL enableVideoEffect;
#property (nonatomic, assign) BOOL enableWatermark;
#property (nonatomic, assign) CGFloat thumbnailCompressionQuality;
#property (nonatomic, strong) UIColor *tintColor;
#property (nonatomic, strong) UIImage *watermarkImage;
#property (nonatomic, assign) QupaiSDKWatermarkPosition watermarkPosition;
#property (nonatomic, assign) QupaiSDKCameraPosition cameraPosition;
- (UIViewController *)createRecordViewControllerWithMinDuration: (CGFloat)minDuration
maxDuration:(CGFloat)maxDuration
bitRate:(CGFloat)bitRate;
- (UIViewController *)createRecordViewController;
- (void)updateMoreMusic;
#end
#protocol QupaiSDKDelegate <NSObject>
- (void)qupaiSDK:(id<ALBBQuPaiService>)sdk compeleteVideoPath:(NSString *)videoPath thumbnailPath:(NSString *)thumbnailPath;
#optional
- (NSArray *)qupaiSDKMusics:(id<ALBBQuPaiService>)sdk;
- (void)qupaiSDKShowMoreMusicView:(id<ALBBQuPaiService>)sdk viewController:(UIViewController *)viewController;
#end
#interface ALBBQuPaiService : NSObject<ALBBQuPaiService>
+(instancetype)sharedService;
#property (nonatomic, weak) id<QupaiSDKDelegate> delegte;
#end
Remember that all the obj-c protocol act as a abstract class I recommend to put "protocol, model and set base type as nsobject, another thing all the methods or properties maked as a "required" you need to specify it as Abstract.
[Protocol, Model]
[BaseType (typeof(NSObject))]
interface myAwesomeDelegate
{
[Abstract]
[Export(...)]
void myRequiredMethod(uint param1)
[Export(...)]
void anotherMethod()
}
I recommend to use the objective sharpie tool it support .framework files using version 3.X with the command framework bind -f myFramework.framework
for more info about it check https://developer.xamarin.com/guides/cross-platform/macios/binding/objective-sharpie/tools/ or also you can check in the xamarin Github bindings https://github.com/mono/monotouch-bindings, if you have any specific question about bindings please let me know
What's wrong with the following code? Xcode 4 is saying that the two method declarations with "Question" don't compile due to an '"expected ")" before "Question"; message, as indicated in the comments in the code below. The Question class compiles and this code has been working previously. I made some changes to Questions, but backed them out to try to figure out this compile time error.
#import <Foundation/Foundation.h>
#import "Question.h"
#interface AppState : NSObject {
int chosenAnswer;
int correctAnswers;
int currentQuestionNumber;
// this will contain the hash table of question objects
NSMutableDictionary *questionHash;
}
#property (nonatomic) int chosenAnswer;
#property (nonatomic) int correctAnswers;
#property (nonatomic) int currentQuestionNumber;
#property (nonatomic, retain) NSDictionary *questionHash;
- (void) printQuestions;
- (void) printDescription;
- (void) addQuestion: (Question *) question; // <==== error
- (int) numberOfQuestions;
- (void) saveState;
- (void) resetState;
- (Question *) currentQuestion; // <===== error
#end
Here's Question.h:
#import <Foundation/Foundation.h>
#import "AppState.h"
#interface Question : NSObject {
NSString *questionTxt;
int correctAnswer;
int number;
// this will contain the hash table of questions_answer objects
NSMutableDictionary *answerHash;
}
#property (nonatomic, retain) NSString * questionTxt;
#property (nonatomic) int correctAnswer;
#property (nonatomic) int number;
#property (nonatomic, retain) NSMutableDictionary *answerHash;
-(void) addAnswer: (NSString *) answer;
- (NSMutableArray *) answerArray;
- (void) printDescription;
- (void) printAnswers;
- (NSString *) correctAnswerText;
- (Question *) currentQuestion;
#end
Circular dependency? AppState is importing Question and Question is importing AppState.
Forward-declare one of them to break the cycle, e.g. use #class Question before your AppState #interface statement, like this
#class Question;
#interface AppState : NSObject {
int chosenAnswer;
int correctAnswers;
int currentQuestionNumber;
// this will contain the hash table of question objects
NSMutableDictionary *questionHash;
}
...
Related question: #class vs. #import
When you #import "AppState.h" in Question you make a cyclic dependency.
It would be best to move #import "AppState.h" and #import "Question.h" to implementation part. In the header just leave
#class Question;
and
#class AppState;
before interface declaration.