I am inexperienced with Objective-C and this is my first attempt at anything Swift. I Can't get Xcode to compile. ( I may also be missing a necessary line or two, but if I get it to compile, I can usually figure out the rest )
I've been all over docs and getting started, I don't know enough to know the answer if it's there:
http://bustoutsolutions.github.io/siesta/guide/objc/
https://bustoutsolutions.github.io/siesta/api/
My Code:
// MyAPI.swift
import Siesta
import SwiftyJSON
#objc class MyAPI: Service {
internal static let instance = MyAPI(baseURL:"https://api.example.com")
}
// ViewController.mm
#import "ViewController.h"
#import "PlateScanner.h"
#import "Plate.h"
#import "MyProject-swift.h"
...
- (IBAction)callAPI:(id)sender
{
[[MyAPI.instance resource:#"/profile/"] child:#"123"];
}
-(void)resourceChanged: (BOSResource*) resource event: (NSString*) event {
if([event hasPrefix:#"NewData"]) {
NSLog(#"%#",[resource text]);
}
}
...
I get the following 2 errors from ViewController.mm:
1. line starting "[[MyAPI": No visible #interface for 'MyAPI' declares the selector 'resource:'
2. line starting "-(void)reso": Expected a type
From this I understand that my ViewController is not understanding the necessary BOSResource type, but I don't know how to get the swift library imported properly?
Xcode generated code:
//MyProject-swift.h
...
SWIFT_CLASS("_TtC10MyProject5MyAPI")
#interface MyAPI : BOSService
+ (MyAPI * _Nonnull)instance;
#end
...
With Error in line starting "#interf...": Cannot find interface declaration for 'BOSService', superclass of 'MyAPI'
Any help is greatly appreciated!
Related
As soon as I added RCT_REMAP_METHOD(findEvents2, resolver:(RCTPromiseResolveBlock)resolve rejector:(RCTPromiseRejectBlock)reject) to .m file inside of the interface, Xcode started complaining about missing #end.
I am trying Callback and Promise examples from https://facebook.github.io/react-native/docs/native-modules-ios.html while also bridging from Objective C to Swift. findEvents1 with callback works for me, but I can't get findEvents2 with Promise to work.
I added method definition with macro in my .m file:
#import "RCTBridgeModule.h"
#interface RCT_EXTERN_MODULE(EventManager, NSObject)
RCT_EXTERN_METHOD(findEvents1: (RCTResponseSenderBlock)callback)
RCT_REMAP_METHOD(findEvents2, resolver:(RCTPromiseResolveBlock)resolve rejector:(RCTPromiseRejectBlock)reject)
#end
Then I implemented the method in .swift file:
#objc(EventManager)
class EventManager: NSObject {
func findEvents1(callback: (NSObject) -> () ) -> Void {
EventRequest(completion: EventRequest.CompletionHandler (
success: { (events) in
callback([events])
}, failure: { (error) in
callback([(error?.localizedDescription)!])
}, cancel: nil)
).dispatch()
}
func findEvent2....
}
I don't fully understand how RCT_REMAP_METHOD macro works, I don't see why findEvent1 works but findEvent2 doesn't. Could someone suggest how to bridge this method?
I'm currently working on some Swift classes in my ObjC project.
The problem I have is the following:
I have this protocol declared in ClassA.h:
#protocol MyProtocol <NSObject>
- (void)complexMethodWithArg1:(id)arg1 arg2:(id)arg2 arg3:(id)arg3;
- (Folder *)currentDestinationFolder;
- (Flow)currentFlow;
#end
Pretty standard stuff.
Now my goal is to have a swift class with a property that is an object implementing this protocol.
So naturally, I add my class to the swift bridging header:
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "ClassA.h"
and declare my property in my swift file under ClassB which is a UIViewController that implement ANOTHER protocol
class ClassB : UIViewController, AnotherProtocol {
var delegate:MyProtocol?
}
Problem here is: I want to call a bunch of my delegate methods in viewDidLoad. It's working for all of them except ONE method that gets not autocompletion and errors the compilation if entered manually:
override func viewDidLoad() {
self.delegate?.currentDestinationFolder() // works great, no problem
self.delegate?.currentFlow() // works great, no problem
self.delegate?.complexMethodWithArg1(arg1: arg1, arg2: arg2, arg3: arg3) // PROBLEM : no autocompletion, error if entered manually !
super.viewDidLoad()
}
I have no idea what's going on, it's not related to optional or required protocol methods, not related to the fact that my delegate property is optional (tried unwrapped).
Has anybody face some similar issue? seems like some kind of bug?
I went ahead and tried to reproduce the problem on an empty project.
MyProtocol.h (taking the declaration from your question and comments)
#import Foundation;
#import UIKit;
#class CAPNavigationBar;
#protocol MyProtocol <NSObject>
- (void)setupNavigationItemInNavigationBar:(CAPNavigationBar *)navigationBar
navigationItem:(UINavigationItem *)navigationItem
inViewController:(UIViewController *)viewController;
#end
CAPNavigationBar.h (just a mock)
#import Foundation;
#interface CAPNavigationBar : NSObject
#end
ViewController.swift
import UIKit
class ViewController: UIViewController {
var delegate: MyProtocol?
override func viewDidLoad() {
super.viewDidLoad()
let capNavigationBar = CAPNavigationBar()
self.delegate?.setupNavigationItemInNavigationBar(capNavigationBar, navigationItem: nil, inViewController: self)
}
}
Bridging header
#import "MyProtocol.h"
#import "CAPNavigationBar.h"
Summary
Everything is working as expected.
You have either a simple typo somewhere or you are not importing correctly all the types into Swift. Especially make sure that you are not importing types only as forward declarations.
I've got a dylib framework with some UIView subclasses made in swift which I've done to use the new #IBDesignable and #IBInspectable stuff.
So lets say I've got a UITextField subclass in there named MyTextField.swift like this:
MyTextField.swift
#IBDesignable class MyTextField: UITextField {
// some properties etc.
// content is irrelevant
}
Now it compiles and works well in InterfaceBuilder so far so good. But what I need to do is import this special subclass into my Objective C implementation of the controller to set a property in code at runtime.
The framework (named myViews) has a header called myViews.h which I am able to import into the controllers header like this:
MyViewController.h:
#import myViews;
#import <UIKit/UIKit.h>
#import "myViews.h"
#interface MyViewController : UIViewController
#property(weak, nonatomic) IBOutlet MyTextField *txtName; // <-- This is the problem!
#end
This is where I'm stuck! So the class MyTextField is unknown from the imported headers. The myViews.h was automatically generated. I've tried to import the bridging-headers in there without success.
myViews.h:
#import <UIKit/UIKit.h>
//! Project version number for myViews.
FOUNDATION_EXPORT double myViewsVersionNumber;
//! Project version string for myViews.
FOUNDATION_EXPORT const unsigned char myViewsVersionString[];
// In this header, you should import all the public headers of your framework
// using statements like #import <myViews/PublicHeader.h>
#import <myViews/MyTextField-Swift.h> // <-- This is what I've tried to import here which doesn't work as well.
Hope anybody may help me out. Thanks in advance.
In your objective-c class, try importing your swift module like this:
#import "<ModuleName>-Swift.h"
Where ModuleName is the name of the module containing the swift code
i'm trying to get the Objection Framework working with Swift (XCode 6.4).
Everything works pretty well beside the macros required for register/inject objects e.g. objection_register
I followed the approach from "Bridging Cocoalumerjack with Swift" to get the macros working with Swift but XCode always complain: Use of undeclared identifier 'initialize' when implementing objectionRegister function in ObjectionSwift.m. Since i'm not to familiar with objective-c i got stuck when looking at the Objection.h initializer methods and trying to figure out whats wrong
Thx for your help!
ObjectionSwift.h
#import <Foundation/Foundation.h>
#interface ObjectionSwift : NSObject
+ (void) objectionRegister(NSString *) name;
#endif
ObjectionSwift.m
#import "ObjectionSwift.h"
#import "Objection.h"
#implementation ObjectionSwift
+ (void) objectionRegister:(NSString *) name {
objection_register_singleton(name)
}
#end
UPDATE
I switched to Typhoon as DI Framework which provides Swift support an works pretty well.
You can use class variable:
class ListingsViewController: UIViewController
{
class var initialize: Bool
{
JSObjection.registerClass(ListingsViewController.self, scope: JSObjectionScopeNormal)
return true
}
}
I'm trying to continue with Swift in an existing project I had started in Objective-C. I followed the Apple documentation and I managed to access a Swift class from an Objective-C file, via including the "ProductModuleName-Swift.h" header in my Obj-C file.
At this point here's my code:
#include "Pianoconcert_App-Swift.h"
#interface ModelsVC ()
#end
#implementation ModelsVC
// And all that kind of stuff
// ...
-(IBAction)comanda:(UIButton *)sender {
ComandaTableVC *controller = (ComandaTableVC *)self.tabBarController.viewControllers[2];
// Here goes the problematic code
[self.tabBarController setSelectedIndex:2];
}
This piece of code has no problems. But now I just want to set one of the variables in the Swift class like this: controller.selectedModel = sender.tag, but Xcode just tells me the variable does not exist.
Here's an extract of my Swift class:
import UIKit
class ComandaTableVC: UITableViewController, UIPickerViewDataSource, UIPickerViewDelegate {
// Declaration of some constants and variables
// And here goes the one
var selectedModel: Int = 0
// And a bunch more of variables and functions
// ...
}
I don't know what I'm doing wrong. The class seems fully included and, actually, I can access that variable and all the others if I use the class from another Swift file, like this:
var controller: ComandaTableVC = self.tabBarController.viewControllers[2] as ComandaTableVC
controller.selectedModel = 2
It's been resolved finally, but I can't explain how.
Suddenly the compiler threw a build error telling me that the file Pianoconcert_App-Swift.h could not be found.
I changed it for PianoconcertApp-Swift.h, deleting the underscore that replaced the blank space, and now I can access all the variables and constants correctly.