Swift 协议扩展不';无法使用RCT\u导出\u视图\u属性?

Swift 协议扩展不';无法使用RCT\u导出\u视图\u属性?,swift,react-native,react-native-ios,Swift,React Native,React Native Ios,我有一个部分基类RNChartBaseView(协议和扩展),还有一堆子类,如RNLineChartView、RNBarChartView等 RNChartBaseView.swift protocol RNChartBaseView { associatedtype T: ChartViewBase; associatedtype U: ChartDataEntryBase; var chart: T { get } func create

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

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;
       }
 }
 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;

      }

 }
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;

      }
 }
RNLineChartView.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;
       }
 }
 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;

      }

 }
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;

      }
 }
RNLineChartViewManagerSwift.swift

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

 #import "React/RCTViewManager.h"

 @interface RCT_EXTERN_MODULE(RNLineChartViewManagerSwift, RCTViewManager)

 RCT_EXPORT_VIEW_PROPERTY(data, NSDictionary)

 @end
但我明白了

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

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

问题在哪里

更新 看来基类是必要的

但下面的代码并不优雅,如何以正确的方式编写

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;
    }
}
class RNChartViewBaseClass: UIView, RNChartViewBase {
      ......
      func setData(_ data: NSDictionary) {
          (self as RNChartViewBase).setData(data)
      }
}
RNLineChartView.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;
       }
 }
 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;

      }

 }
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;

      }
 }
更新 最后,我使用了扩展和子类的组合

模板代码在扩展名中。在RNChartBaseView类中

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;
    }
}
class RNChartViewBaseClass: UIView, RNChartViewBase {
      ......
      func setData(_ data: NSDictionary) {
          (self as RNChartViewBase).setData(data)
      }
}

问题是Objective-C对协议扩展一无所知,而React Native同时使用Objective-C的消息传递机制(objc_msgSend)。 您不能使用协议扩展来注入方法,以便Objective-C的消息传递机制可以看到该方法


您可以创建UIView的子类并在其中声明setData方法,而不是protocol。

UIView的子类带来了一个新问题。如果我创建UIView的子类并在其中声明setData方法。在setData中,有
chart.data=chartData
,但chart是泛型类型,我只能在具体的RNLineChartView/RNBarChartView中初始化
chart
,如何解决这个问题?如果我理解正确,你可以在父类中声明setData,在子类中用具体类型重写方法。我稍微更新了这个问题,在那里添加了我的基类。我对那个基类不太满意,你能帮我改进一下吗?我认为你的解决方案对当前的需求来说很好-你使用的是模板方法模式,现在它解决了你的问题。我最后使用了一个奇怪的扩展和子类的组合,已经附加到问题后面了。谢谢你的帮助。