Importing a Swift protocol in Objective-C class
You need to add the @objc
attribute to your Swift protocol like so:
@objc protocol AnalyticProtocol {
}
swift, objective-c protocol implementation
The answer is:
func webSocket(webSocket: SRWebSocket!, didReceiveMessage message: AnyObject!)
see
Functions in Swift Reference Book
Method name in Obj-C webSocket:didReceiveMessage
is translated such as the first part is the method name, the other parts are the external parameter names (didReceiveMessage
). Also note that id
becomes AnyObject
and Obj-C references are translated with !
as implicitly unwrapped optionals (this is no longer true, implicitly unwrapped optionals are now rare thanks to attributes added to Obj-C declarations).
Implementing Objective-C protocol in Swift class
Generally, in Swift you have to implement ALL methods of a protocol. (See this question about optional protocol methods: How to define optional methods in Swift protocol?)
But as you said, the framework is written in Objective-C. Objective-C supports optional methods in protocols.
@protocol ProtocolName
@required
// list of required methods
@optional
// list of optional methods
@end
Source
That's why you don't necessarily need to implement all methods declared in a protocol. Usually, only the most important methods are marked with @required
, because when calling an optional method, you should always check, if the delegate implemented it.
Implement Objective c protocol in Swift
There are two errors in the delegate method
func uploadProgressPercentage(percentage:Int?){
println(percentage)
}
The parameter must not be an optional, and the C type int
is mapped to Swift
as CInt
(an alias for Int32
):
func uploadProgressPercentage(percentage:CInt){
println(percentage)
}
Alternatively, you could use NSInteger
in the Objective-C protocol, which is
mapped to Int
in Swift. This would be a 32-bit or 64-bit integer, depending
on the architecture, whereas int
/CInt
is always 32-bit.
How to implement objective C protocol in swift class?
Add this line in the bridging header
#import "BDViewController.h"
maybe it will solve your problem. Let me know if it is helpful.
Swift protocol extension in Objective-C class
Objective-C protocols cannot have default implementations.
Objective-C protocols can have real optional methods/properties, unlike Swift protocols, which only have required methods/properties. The workaround for this in Swift is the use of a default implementation, however, sadly those cannot be seen in Objective-C.
I would suggest creating a pure Swift protocol and for all Objective-C classes that want to extend this, write the conformance in Swift, then create @objc
wrapper functions in Swift that call the default protocol implementations - if it needs to be called, if it doesn't need to be called, simply ignore it.
Something along the lines of:
protocol SwiftProtocol {
func requiredFunc()
func optionalFunc()
}
extension SwiftProtocol {
func optionalFunc() {}
}
@objc extension ObjcClass: SwiftProtocol {
@objc func requiredFunc() {
print("do something")
}
// This will call the default implementation - can be omitted if you don't need to call the default implementation from Objective-C
@objc func objc_optionalFunc() {
optionalFunc()
}
}
Using an implementation of a Swift protocol within Obj-C
In Objective-C, a protocol is not a type. You should declare your protocol-conforming class like so:
id<TheProtocol> p = [[ObjCClass alloc] init];
The reason why your forward declaration compiled is because that's what forward declarations do - they announce to the compiler that a class exists and that the linker will fill it in later in the build process.
(That's why changing to id p =...
works too.)
In Swift, we declare classes with something like:
class MyClass : Superclass, Protocol, AnotherProtocol { ... }
In Objective-C we use this:
@class MyClass : SuperClass <Protocol, AnotherProtocol>
// ...
@end
See the difference? In Swift, protocols and the superclass are mixed into the inheritance declaration, whereas Objective-C treats them very differently.
Protocols and Classes are treated slightly different across the two languages, thus used differently.
id
in ObjectiveC is analogous to AnyObject?
in Swift. An object which conforms to SomeProtocol
is obviously AnyObject
or id
in Objective-C.
Implement protocol partially in Objective C and partially in Swift
When building a project that has mixed Swift+Objective-C code, this is a brief summary of what happens:
- the bridging header is processed
- the Swift files are compiled
- the Objective-C files are compiled
The error you see occurs at step #2, at this point the compiler sees that the Objective-C class conforms to UITableViewDataSource
, thus it assumes that the Objective-C code implements the tableView(_:numberOfRowsInSection:)
method, thus it sees a conflict since the Swift code also implements the method.
The source of the problem is the fact that you are trying to implement some of the protocol methods in Objective-C, and some in Swift, and this is not possible, you need to either implement all the non-optional methods of the protocol either in Swift, or Objective-C.
If you really want to go this road, a possible solution would be to move the protocol conformance on the Swift side, and declare all the other methods in the Objective-C header as public methods of that class. But this might cause other problems along the way.
Swift protocol in Objective-C class
There are two common reasons for this occuring:
- Getting the module name wrong, see my answer.
- Having a circular reference - see mitrenegades answer below.
1. Get the module name right:
If both the swift protocol and and Objective C are in the same project then according to apple you should just need to make sure you get the correct module name.
For Xcode6 beta 5 you can find it under BuildSettings->Packaging->Product Module Name
A common mistake would be to think that each swift file/class gets its own file, but instead they are all put into one big one that is the name of the project.
A further mistakes are if the module name has spaces, these should be replaced with underscores.
Edit:
With your protocol I created a test project called 'Test' which compiles perfectly and it has the files:
TestObjClass.h
#import <Foundation/Foundation.h>
#import "Test-Swift.h"
@interface TestObjCClass : NSObject <SearcherProtocol>
@end
TestObjClass.m
#import "TestObjCClass.h"
@implementation TestObjCClass
@end
TestProtocol.swift
import Foundation
@objc protocol SearcherProtocol
{
var searchNotificationTarget: SearchCompletedProtocol? { get }
var lastSearchResults: [AnyObject] { get set }
func search(searchParam: String, error: NSErrorPointer) -> Bool
}
@objc protocol SearchCompletedProtocol
{
func searchCompletedNotification(sender: AnyObject!)
}
2. Avoid circular reference:
Mitrenegades answer explains this, but if your project needs to use the explicit objc class that uses the swift protocol, (rather than just using the protocol) then you will have circularity issues. The reason is that the swift protocol is defined to the swift-objc header, then to your obj-c class definition, which then goes again to the swift-objc header.
Mitrenegades solution is to use an objective-c protocol, is one way, but if you want a swift protocol, then the other would be to refactor the code so as to not use the objective-c class directly, but instead use the protocol (e.g. some protocol based factory pattern). Either way may be appropriate for your purposes.
Add Swift protocol conformance to Objective-C header and make it public
In pure objective-c, you cannot make a class conform to a protocol without importing it in the header. To make the use of a protocol private, the conformance shouldn't be declared in the header. It remains possible to call such a method using a cast however, but it should be done with caution because it's a little bit unsafe :
if ([anInstance respondToSelector:@selector(myProtocolMethod)])
[(id<MyProtocol>)anInstance myProtocolMethod];
I'm not familiar with Swift, but I think you can do the same this way (or something close to it) :
if let conformingInstance = anInstance as? MyProtocol
conformingInstance.myProtocolMethod
EDIT : To complete my first assertion, forward declarations can still be used in the header when you need to declare a method receiving or returning an instance conforming to that protocol :
@SomeProtocol;
// This is not possible
@interface MyClass : NSObject <SomeProtocol>
// But this is possible
@property (nonatomic) id<SomeProtocol> someProperty;
-(void) someMethod:(id<SomeProtocol>)object;
@end
In this document Apple clearly said that :
Forward declarations of Swift classes and protocols can be used only
as types for method and property declarations.
So it seems that the rule is the same whatever the protocol is an Objective-c protocol or a Swift protocol.
Related Topics
Get All Ranges of a Substring in a String in Swift
How to Send Push Notification to Apns from iOS Device
Cocoapods Page Redirecting to Github
How to Rotate a UIview Without The Black Bars
View Height Problems (Continued)
Play Keyboard Click Sound in a Collection View Controller
How to Install Self-Signed Certificates in iOS 11
Track Touch Points in Multitouch
Uiactivityviewcontroller => Launchservices: Invalidationhandler Called
Ld: Library Not Found for -Ldoubleconversion React Native 0.59
Screenshot on Swift Programmatically
Swift Unrecognized Selector Sent to Instance - What Am I Missing
Fixing Low Fps in Swift Playground
Can't Use @Observedobject on Real iPhone
Determine The Maximum Number of Characters a UIlabel Can Take
How to Access All Images in a .Xcassets at Once