使用常用方法对多个UIVIew类型进行子类化

时间:2017-05-24 00:05:23

标签: objective-c swift

在Objective-C / Swift中,如何使用常用方法子类化多个UIViews? 例如,子类化UILabel和UITextView,其中setText方法很常见。我不想复制分别继承自UILabel和UITextView的两个单独类的代码。如果“self”是UILabel或UITextView,我想要一个单独使用setText方法的类。此外,我希望能够在故事板中为UILabels和UITextViews设置此类。

谢谢,

2 个答案:

答案 0 :(得分:0)

你不能,至少不容易。在Swift中,您可以声明一个具有setText()方法的协议,然后使用实现该协议的版本将UILabelUITextView子类化。但由于这两者都是UIView子类,因而与Objective-C兼容,因此使用Objective-C方法[NSObject respondsToSelector:]并传入@selector(setText:)来确定对象是否更好一点符合该方法,如果是,请在其上调用setText:

答案 1 :(得分:0)

在objective-c中,您可以定义一个声明现有方法或属性的公共子集的协议

@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 {}

这是因为不同的选项:

UILabelUITextField拥有此属性:

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"

labeltextViewtextField的输入为TextViewType,只有var theText: String?被曝光。