В Objective-C / Swift, как да подклас множествоUIViews с общи методи? Например, подкласиране на UILabel и UITextView, където често е използван методът setText. Не искам да дублирам кода за два отделни класа, наследяващи съответно от UILabel и UITextView.Искам един клас, който използва метода setText независимо дали "self" е UILabel или UITextView.Бих искал също така да задам този клас в Storyboard за UILabels и UITextViews.
Благодаря,
Отговори:
0 за отговор № 1Не можете, поне не лесно. В Swift можете да декларирате протокол, който има a setText()
метод и след това подклас UILabel
и UITextView
с версии, които изпълняват този протокол. Но тъй като и двете са UIView
подкласове и по този начин съвместими с Цел-С, вероятно е по-добра идея да използвате метода на Целка-С [NSObject respondsToSelector:]
и влизай @selector(setText:)
за да определите дали предметите съответстват на този метод и ако е така, обадете се setText:
на тях.
0 за отговор № 2
В цел-в можете да определите протокол, който декларира общата подмножество на съществуващите методи или свойства
@protocol TextViewType <NSObject>
@property(nonatomic, strong) NSString *text;
@end
Сега можете да декларирате съответствие с този протокол за съществуващи класове, като използвате празни категории в тези класове
@interface UILabel (Text) <TextViewType>
@end
@interface UITextView (Text)<TextViewType>
@end
@interface UITextField (Text)<TextViewType>
@end
Това е. Сега можете да го използвате като
@property (weak, nonatomic) IBOutlet id<TextViewType> label;
@property (weak, nonatomic) IBOutlet id<TextViewType> textView;
и
[self.label setText:@"Title"];
[self.textView setText:@"Lorem Ipsum"];
В Swift това може да стане подобно:
import UIKit
protocol TextViewType {
var text: String? { set get }
}
extension UILabel: TextViewType {}
extension UITextField : TextViewType {}
Но за него няма да работи
extension UITextView : TextViewType {}
Това се дължи на различни опции:
UILabel
и UITextField
притежавате тази собственост:
var text: String?
докато UITextView
притежава това:
var text: String!
Тук можете да използвате протокола наследство и разширения на протокола:
protocol TextViewType {
var theText: String? { set get }
}
Това определя интерфейса, който искаме да използваме по-късно
protocol OptionalTextViewType: TextViewType {
var text: String? { set get }
}
Тази специализация на TextViewType
дефинира подкрепящата променлива var text: String?
protocol ImplicitUnwrappedOptionalTextViewType: TextViewType {
var text: String! { set get }
}
Тази специализация на TextViewType
дефинира подкрепящата променлива var text: String!
Сега можем да добавим разширения на протокола към специализациите:
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 ?? ""
}
}
}
Сега трябва да определим съответствието с по-специфичните протоколи:
extension UILabel: OptionalTextViewType { }
extension UITextField: OptionalTextViewType {}
extension UITextView : ImplicitUnwrappedOptionalTextViewType {}
и можем да го използваме като:
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"
като label
, textView
и textField
са написани като TextViewType
, само var theText: String?
е изложена.