In Objective-C / Swift, come sottoclassare più elementiUIVview con metodi comuni? Ad esempio, la sottoclasse di UILabel e UITextView in cui il metodo setText è comune. Non voglio duplicare il codice per due classi separate che ereditano rispettivamente da UILabel e UITextView. Voglio una singola classe che usa il metodo setText in modo indipendente se "self" è un UILabel o UITextView. Inoltre vorrei essere in grado di impostare questa classe in Storyboard per UILabels e UITextViews.
Grazie,
risposte:
0 per risposta № 1Non puoi, almeno non facilmente. In Swift, puoi dichiarare un protocollo che ha un setText()
metodo e quindi sottoclasse UILabel
e UITextView
con versioni che implementano quel protocollo. Ma perché entrambi sono UIView
sottoclassi, e quindi compatibile con Objective-C, è probabilmente una migliore idea usare il metodo Objective-C [NSObject respondsToSelector:]
e passare @selector(setText:)
per determinare se gli oggetti sono conformi a quel metodo e, in tal caso, chiamare setText:
su di essi.
0 per risposta № 2
In goal-c puoi definire un protocollo che dichiara il sottoinsieme comune di metodi o proprietà esistenti
@protocol TextViewType <NSObject>
@property(nonatomic, strong) NSString *text;
@end
Ora puoi dichiarare la conformità a questo protocollo per le classi esistenti usando categorie vuote su quelle classi
@interface UILabel (Text) <TextViewType>
@end
@interface UITextView (Text)<TextViewType>
@end
@interface UITextField (Text)<TextViewType>
@end
Questo è tutto. Ora puoi usarlo come
@property (weak, nonatomic) IBOutlet id<TextViewType> label;
@property (weak, nonatomic) IBOutlet id<TextViewType> textView;
e
[self.label setText:@"Title"];
[self.textView setText:@"Lorem Ipsum"];
In Swift questo può essere fatto in modo simile:
import UIKit
protocol TextViewType {
var text: String? { set get }
}
extension UILabel: TextViewType {}
extension UITextField : TextViewType {}
Ma non funzionerà
extension UITextView : TextViewType {}
Ciò è dovuto a diversi optional:
UILabel
e UITextField
possedere questa proprietà:
var text: String?
mentre UITextView
possiede questo:
var text: String!
Qui puoi usare l'ereditarietà del protocollo e le estensioni del protocollo:
protocol TextViewType {
var theText: String? { set get }
}
Questo definisce l'interfaccia che vogliamo usare in seguito
protocol OptionalTextViewType: TextViewType {
var text: String? { set get }
}
Questa specializzazione di TextViewType
definisce la variabile di supporto var text: String?
protocol ImplicitUnwrappedOptionalTextViewType: TextViewType {
var text: String! { set get }
}
Questa specializzazione di TextViewType
definisce la variabile di supporto var text: String!
Ora possiamo aggiungere estensioni di protocollo alle specializzazioni:
extension OptionalTextViewType {
var theText: String? {
set {
self.text = newValue
}
get {
return self.text
}
}
}
extension ImplicitUnwrappedOptionalTextViewType {
var theText: String? {
set {
self.text = newValue ?? ""
}
get {
return self.text ?? ""
}
}
}
Ora dobbiamo definire la conformità ai protocolli più specifici:
extension UILabel: OptionalTextViewType { }
extension UITextField: OptionalTextViewType {}
extension UITextView : ImplicitUnwrappedOptionalTextViewType {}
e possiamo usarlo come:
var label: TextViewType = UILabel(frame: CGRect(x: 0, y: 0, width: 120, height: 20))
label.theText = "Label"
var textView: TextViewType = UITextView(frame: CGRect(x: 0, y: 0, width: 120, height: 20))
textView.theText = "TextView"
var textField: TextViewType = UITextField(frame: CGRect(x: 0, y: 0, width: 120, height: 20))
textField.theText = "TextField"
come label
, textView
e textField
sono digitati come TextViewType
, solo var theText: String?
è esposto.