2017-02-24 5 views
1

Ich habe eine Teilbasisklasse RNChartBaseView (Protokoll und Erweiterung), und Bündel Subklasse wie RNLineChartView, RNBarChartView usw.Protokollerweiterung funktioniert nicht mit 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 .Schalt

@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 

Aber ich

bekommen

[reactNativeCharts.RNLineChartView setData:]: unrecognized selector sent to instance 0x7fdf60e04510'

wenn ich setData von Erweiterung RNLineChartView.swift kopieren, funktioniert alles gut.

wo ist das Problem?

Aktualisieren

Es scheint eine Basisklasse erforderlich ist.

Aber folgender Code ist nicht elegant, Wie man es richtig schreibt?

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; 

     } 
} 

aktualisieren

Endlich, verwende ich eine Kombination aus Erweiterung und Unterklasse.

Der Vorlagencode ist in Erweiterung. und in den RNChartBaseViewClass

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

Antwort

1

Das Problem ist, dass Objective-C weiß nichts von Protokollerweiterungen, während in der gleichen Zeit React-Mutter ist Objective-C Messaging-Mechanismus (objc_msgSend) verwendet wird. Sie können keine Protokollerweiterungen verwenden, um eine Methode zu injizieren, damit sie für den Nachrichtenmechanismus von Objective-C sichtbar ist.

Anstelle des Protokolls können Sie eine Unterklasse von UIView erstellen und dort die setData-Methode deklarieren.

+0

Unterklasse von UIView bringt ein neues Problem. Wenn ich eine Unterklasse von UIView erstellen und dort die Methode setData deklariere. In setData gibt es 'chart.data = chartData', aber das Diagramm ist ein generischer Typ, Ich kann' chart' nur in RNLineChartView/RNBarChartView, initialisieren, wie man dieses Problem löst? –

+0

Wenn ich Sie richtig verstehe, können Sie setData in Elternklasse deklarieren und Methode in untergeordneten Klassen mit konkreten Typen überschreiben. –

+0

Ich aktualisiere die Frage etwas, füge dort meine Basisklasse hinzu. Ich bin mit dieser Basisklasse nicht ganz zufrieden, kannst du mir helfen, sie zu verbessern? –

Verwandte Themen