protocol extension doesn't work with RCT_EXPORT_VIEW_PROPERTY?
The problem is that Objective-C knows nothing of protocol extensions while in the same time React-Native is using Objective-C's messaging mechanism(objc_msgSend).
You cannot use a protocol extensions to inject a method so that it will be visible to the Objective-C's messaging mechanism.
Instead of protocol you can create a subclass of UIView and declare setData method there.
How to delegate third-party components in react-native ios
1) If FooChart & BarChart is a subclass of UIView, then you can initialize FooChart & BarChart, set delegate and return it directly
- (UIView *)view {
FooChart *chart = [FooChart new];
chart.delegate = self;
return chart;
}
2) You can share common settings and template code using inheritance
3) You can either duplicate exports or create some macros that will combine common exports.
Components actually do not inherit exports. All components have RCTViewManager exports + own exports, but its done without using inheritance.
Dynamic dispatching protocol extension doesn't work multiple targets
Your Project
module declares MyClass
's conformance to ProtocolA
.
Swift implements that conformance using a data structure called a “protocol witness table”. For each method declared by the protocol, the witness table contains a function that calls the actual implementation of the method for the conforming type.
To be concrete, there is a witness table for the conformance of MyClass
to ProtocolA
. That witness table contains a function for the dontCrash
method declared by ProtocolA
. That function in the witness table calls the MyClass
dontCrash
method.
You can see the function from the protocol witness table in the stack trace when your test case hits fatalError
:
#8 0x00000001003ab9d9 in _assertionFailure(_:_:file:line:flags:) ()
#9 0x00000001000016fc in ProtocolA.dontCrash() at /Users/rmayoff/TestProjects/Project/Project/AppDelegate.swift:11
#10 0x0000000100001868 in protocol witness for ProtocolA.dontCrash() in conformance MyClass ()
#11 0x000000010000171e in ProtocolA.tryCrash() at /Users/rmayoff/TestProjects/Project/Project/AppDelegate.swift:15
#12 0x00000001030f1987 in ProjectTests.testExample() at /Users/rmayoff/TestProjects/Project/ProjectTests/ProjectTests.swift:12
#13 0x00000001030f19c4 in @objc ProjectTests.testExample() ()
Frame #10 is the call from tryCrash
to the function in the protocol witness table. Frame #9 is the call from the protocol witness table function to the actual implementation of dontCrash
.
Swift emits the protocol witness table in the module that declares the conformance. So, in your case, the witness table is part of the Project
module.
Your override of dontCrash
in your test bundle cannot change the contents of the witness table. It's too late for that. The witness table was fully defined when Swift generated the Project
module.
Here's why it has to be this way:
Suppose I'm the author of the Project
module and you're just a user of it. When I wrote the Project
module, I knew calling MyClass().dontCrash()
would call fatalError
, and I relied on this behavior. In many places inside Project
, I called MyClass().dontCrash()
specifically because I knew it would call fatalError
. You, as a user of Project
, don't know how much Project
depends on that behavior.
Now you use the Project
module in your app, but you retroactively change MyClass().dontCrash()
to not call fatalError
. Now all those places where Project
calls MyClass().dontCrash()
don't behave in the way that I expected when I wrote the Project
module. You have broken the Project
module, even though you didn't change the source code of the Project
module or any of the modules that Project
imports.
It's critical to the correct operation of the Project
module that this not happen. So the only way to change what MyClass().dontCrash()
means (when called from inside the Project
module) is to change the source code of the Project
module itself (or change the source code of something that Project
imports).
protocol extension, does not conform to protocol
The problem is that your extension
isn't public – therefore it's not visible outside the module it's defined in, in this case MyFramework
.
This means that your view controller only knows about the LoginProtocol
definition (as this is public), but not the default implementation. Therefore the compiler complains about the protocol methods not being implemented.
The solution therefore is to simply make the extension public:
public extension LoginProtocol {
func appBannerImage() -> UIImage? {
return (UIImage(named: "login_new_top"))
}
func appLogoImage() -> UIImage? {
return (UIImage(named: "appLogo"))
}
}
Swift protocol extension not being called
You are trying to make a Swift protocol extension on an Objective-C protocol. That's never going to work, because Objective-C cannot see a Swift protocol extension, so Cocoa (which is Objective-C) will never know about your implementation and will never call it.
Swift protocol extension where Self: Equatable doesn't work
Let's start with your CustomEquatable
protocol, without the extension:
protocol CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool
}
Let's define some types to use for experiments:
struct A: Equatable {
let name: String
}
struct B: Equatable {
let id: Int
}
Suppose we then want A
and B
to conform to CustomEquatable
. Then we have four cases to consider:
- What does
a1.isEqualTo(a2)
mean (wherea1
anda2
are both of typeA
)? - What does
b1.isEqualTo(b2)
mean (whereb1
andb2
are both of typeB
)? - What does
a.isEqualTo(b)
mean (wherea
is anA
andb
is aB
)? - What does
b.isEqualTo(a)
mean (whereb
is aB
anda
is anA
)?
For the first two cases, possible answers are that a1.isEqualTo(a2)
if and only if a1 == a2
and b1.isEqualTo(b2)
if and only if b1 == b2
.
For the second two cases, we have to decide if there's a way for an A
to equal a B
. The simplest solution (I think) is that an A
can never equal a B
.
So we can write the conformances like this:
extension A: CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? A) == self
}
}
extension B: CustomEquatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? B) == self
}
}
The only difference in these two conformances is the cast-to type (on the right side of as?
). So we can factor out the conformances into a protocol extension like this:
extension CustomEquatable where Self: Equatable {
func isEqualTo(_ other: CustomEquatable) -> Bool {
return (other as? Self) == self
}
}
With this protocol extension, we can make A
and B
conform to CustomEquatable
without implementing isEqualTo
for each:
extension A: CustomEquatable { }
extension B: CustomEquatable { }
To test the code:
let a1 = A(name: "a1")
let a2 = A(name: "a2")
let b1 = B(id: 1)
let b2 = B(id: 2)
a1.isEqualTo(a1) // true
a1.isEqualTo(a2) // false
b1.isEqualTo(b1) // true
b1.isEqualTo(b2) // false
a1.isEqualTo(b1) // false
b1.isEqualTo(a1) // false
Swift Protocol Extension - Can't Access Func
extension Customer where Self:Vegan, Self:Vegetarian {
extends Customer in the case where the adopter or Customer also both adopts Vegan and Vegetarian. Your aCustomer
(a struct type starting with a small letter?? the horror, the horror) does not do that, so the extension doesn't apply to it.
If the goal is to inject the same code either when the adopter adopts Vegan or when the adopter adopts Vegetarian, use two extensions, or, if you don't like the repetition, have them both adopt some "higher" protocol that is extended with the desired code to be injected.
Class does not conform to protocol with protocol extension
It is because your protocol has no parameters and its implementation has.
Protocol:
handleLogin()
Implementation:
handleLogin(withWindow window: UIWindow?)
If you remove the parameter from extension or add the parameter in the protocol it will work.
swift 2.0 - UITextFieldDelegate protocol extension not working
I can't be 100% positive, but here's what I believe is happening:
Protocol extensions aren't accessible from ObjC
. Since UITextFieldDelegate
is an ObjC
protocol, its reliant on ObjC
dispatching. As far as the compiler is concerned, the methods in your default implementation are inaccessible, even though they do exist.
To clarify, we can extend these protocols if its truly an extension and adds behavior. This behavior will only be accessible in Swift and shouldn't be problematic in any way.
The problem is default implementations not being ObjC
accessible.
Here's a quick example of a custom version:
@objc protocol Test : class {
func someFunc() -> String
}
extension Test {
func someFunc() -> String {
return ""
}
}
// Fails here 'candidate is not @objc but protocol requires it`
class Hi : NSObject, Test {
}
Xcode suggests appending @objc
but it will keep suggesting this over and over again until you get @objc @objc @objc Hi : ...
Based on our conversation below, I made this which seems to be working. I can't fully explain why yet:
@objc public protocol Toto: UITextFieldDelegate {
optional func randomInt() -> Int
}
extension Toto {
func randomInt() -> Int {
return 0
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
return false
}
}
class Tata: NSObject, Toto {
}
Ok, I realize that I'm considering a different problem, and while this compiles, it won't work, and the issue is dynamic dispatch. If you try to append your method w/ @objc
, or dynamic
, the compiler will warn you that you can't dispatch this way, except on classes. Since a protocol exception doesn't conform to this, when ObjC dispatches the message send, it can't find the implementation in your extension.
Since Swift is constantly updating, here's when this answer was applicable:
Swift 2.0 Xcode 7 GM
Related Topics
Swift Pattern Match on Array<Any>
Swift: Gradient Splits on Rotation
How to Pass Data Backwards to a View Controller After Passing Forward
Sandbox Entitlement to Script Itunes via Nsapplescript
Pass Data from Tableviewcontroller to Another Tableviewcontroller in Swift
Swift Displaying The Time or Date Based on Timestamp
How to Get Alphabetic Tableview Sections from an Object
Must Call a Designated Initializer of The Superclass 'Day' Error
Swiftui Sheet Shows Sheet with Wrong Data
Get Out of Navigation Controller and Go Back to Tab Bar View
How to Programmatically Scroll iOS Wkwebview, Swift 4
How to Properly Map JSON Properties to Model Properties in Realm.Create
iOS 10. Coredata Insert New Object Sig Abrt
It Is Posible to Load Customise HTML View into Webview in Swift
How to Constrain Second Nsviewcontroller Minimum Size in Os X App
How to Make an Ellipse/Circular UIimage with Transparent Background
Swift - Rotate Gesture and Rotation Increments of 90 Degrees