Protocol Extension Doesn't Work with Rct_Export_View_Property

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 (where a1 and a2 are both of type A)?
  • What does b1.isEqualTo(b2) mean (where b1 and b2 are both of type B)?
  • What does a.isEqualTo(b) mean (where a is an A and b is a B)?
  • What does b.isEqualTo(a) mean (where b is a B and a is an A)?

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



Leave a reply



Submit