协议扩展不适用于 RCT_EXPORT_VIEW_PROPERTY?
protocol extension doesn't work with RCT_EXPORT_VIEW_PROPERTY?
我有部分基础 class RNChartBaseView(协议和扩展),以及一堆子class,如 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;
}
}
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'
如果我将 setData 从扩展复制到 RNLineChartView.swift,一切正常。
问题出在哪里?
更新
看来需要一个基础class。
但是下面的代码并不优雅,如何写才合适呢?
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;
}
}
更新
最后,我使用了扩展和子的组合class。
模板代码在扩展中。在 RNChartBaseViewClass
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 方法,而不是协议。
我有部分基础 class RNChartBaseView(协议和扩展),以及一堆子class,如 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;
}
}
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'
如果我将 setData 从扩展复制到 RNLineChartView.swift,一切正常。
问题出在哪里?
更新
看来需要一个基础class。
但是下面的代码并不优雅,如何写才合适呢?
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;
}
}
更新
最后,我使用了扩展和子的组合class。
模板代码在扩展中。在 RNChartBaseViewClass
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 方法,而不是协议。