协议扩展不适用于 RCT_EXPORT_VIEW_PROPERTY? [英] protocol extension doesn't work with RCT_EXPORT_VIEW_PROPERTY?

查看:20
本文介绍了协议扩展不适用于 RCT_EXPORT_VIEW_PROPERTY?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个部分基类 RNChartBaseView(协议和扩展),以及一堆子类,如 RNLineChartView、RNBarChartView 等.

I have a partial base class RNChartBaseView (protocol and extension), and bunch of subclass like RNLineChartView, RNBarChartView etc.

RNChartBaseView.swift

RNChartBaseView.swift

 protocol RNChartBaseView {
      associatedtype T: ChartViewBase;
      associatedtype U: ChartDataEntryBase;

      var chart: T { get }

      func createEntries(_ data: NSDictionary) -> [U];

      func setData(_ data: NSDictionary);

 }

 extension RNChartBaseView  {
       func setData(_ data: NSDictionary) {
           
           let chartData = createEntries(data);

           chart.data = chartData;
       }
 }

RNLineChartView.swift

RNLineChartView.swift

 class RNLineChartView : UIView, RNChartBaseView{

      let _chart:LineChartView;
     
      var chart: LineChartView {
         return _chart
      }

      override init(frame: CGRect) {
         self._chart = LineChartView(frame: frame);

         super.init(frame: frame);

         self.addSubview(_chart);
      }

      func createEntries(_ data: NSDictionary) -> [LineDataEntry] {

        // ....... convert to LineDataEntry array.
        return entries;

      }

 }

RNLineChartViewManagerSwift.swift

RNLineChartViewManagerSwift.swift

 @objc(RNLineChartViewManagerSwift)
 class RNLineChartViewManagerSwift: RCTViewManager {
   override func view() -> UIView! {
     let ins = RNLineChartView()
     return ins;
   }       
 }

RNLineChartViewManager.m

RNLineChartViewManager.m

 #import "React/RCTViewManager.h"

 @interface RCT_EXTERN_MODULE(RNLineChartViewManagerSwift, RCTViewManager)

 RCT_EXPORT_VIEW_PROPERTY(data, NSDictionary)

 @end

但我明白

[reactNativeCharts.RNLineChartView setData:]:无法识别的选择器发送到实例 0x7fdf60e04510'

如果我将 setData 从扩展复制到 RNLineChartView.swift,则一切正常.

if I copy setData from extension to RNLineChartView.swift, every thing works fine.

问题出在哪里?

似乎需要一个基类.

但是下面的代码不够优雅,怎么写才合适?

But following code is not elegant, How to write it in a proper way?

RNChartBaseViewClass

RNChartBaseViewClass

class RNChartBaseViewClass: UIView, RNChartBaseView {
    
    var chart: ChartViewBase {
        fatalError("subclass should override this function.")
    };

    
    override init(frame: CGRect) {
        fatalError("subclass should override this function.")
    }

    func createEntries(_ data: NSDictionary) -> [BaseChartDataEntry] {
        fatalError("subclass should override this function.") 
    }



    func setData(_ data: NSDictionary) {
        let chartData = createEntries(data);

        chart.data = chartData;
    }
}

RNLineChartView.swift

RNLineChartView.swift

class RNLineChartView : RNChartBaseViewClass{
      var _chart : LineChartView;
      override var chart: LineChartView {
         return _chart
      }

      override init(frame: CGRect) {
         self._chart = LineChartView(frame: frame);

         super.init(frame: frame);

         self.addSubview(_chart);
      }

      override func createEntries(_ data: NSDictionary) -> [BaseChartDataEntry] { 
           // I have to use [BaseChartDataEntry] here as return type to pass compile,
           //  although it actually is [LineDataEntry],  it may cause further problems, e.g. 
        // ....... convert to LineDataEntry array.
        return entries;

      }
 }

更新

最后,我使用了扩展和子类的组合.

Update

At last , I use a combination of extension and subclass.

模板代码在扩展中.并在 RNChartBaseViewClass

the template code is in extension. and In the RNChartBaseViewClass

class RNChartViewBaseClass: UIView, RNChartViewBase {
      ......
      func setData(_ data: NSDictionary) {
          (self as RNChartViewBase).setData(data)
      }
}

推荐答案

问题在于,Objective-C 对协议扩展一无所知,同时 React-Native 正在使用 Objective-C 的消息传递机制(objc_msgSend).您不能使用协议扩展来注入方法,以便它对 Objective-C 的消息传递机制可见.

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.

您可以创建 UIView 的子类并在那里声明 setData 方法,而不是协议.

Instead of protocol you can create a subclass of UIView and declare setData method there.

这篇关于协议扩展不适用于 RCT_EXPORT_VIEW_PROPERTY?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆