2017-02-24 57 views
1

我有一个部分碱基类RNChartBaseView(协议和延伸),和亚类等RNLineChartView,RNBarChartView等协议扩展不适用于RCT_EXPORT_VIEW_PROPERTY?

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

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

@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 setData:]: unrecognized selector sent to instance 0x7fdf60e04510'

,如果我从扩展RNLineChartView.swift复制使用setData,每一件事工作正常。

问题在哪里?

更新

看起来基类是必要的。

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

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

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; 

     } 
} 

更新

最后,我用的延伸和子类的组合。

模板代码是扩展名。而在RNChartBaseViewClass

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

回答

1

的问题是,Objective-C的同时,在同一时间做出反应,本地使用Objective-C的消息机制(objc_msgSend)一无所知协议扩展。 您不能使用协议扩展来注入方法,以便它对Objective-C的消息传递机制可见。

代替协议,您可以创建UIView的子类并在那里声明setData方法。

+0

UIView的子类带来了一个新问题。 如果我创建UIView的子类并在那里声明setData方法。在setData中,有'chart.data = chartData',但图表是通用类型, 我只能在具体的RNLineChartView/RNBarChartView中初始化'chart', 如何解决这个问题? –

+0

如果我正确理解你,你可以在父类中声明setData,并在具有类型的子类中覆盖方法。 –

+0

我更新了一些问题,在那里添加我的基类。我对这个基础班不太满意,你能帮我改进吗? –