1

I'm converting this Objective-C project (TSCurrencyTextField) to Swift. It's a UITextField subclass formatted to accept currency values. This is the .m file I'm trying to convert.

In it, the UITextField's method shouldChangeCharactersInRange is overridden with a parameter of type TSCurrencyTextField. Like so (look at the very last method),

@interface TSCurrencyTextFieldDelegate : NSObject <UITextFieldDelegate>
@property (weak, nonatomic) id<UITextFieldDelegate> delegate;
@end

@implementation TSCurrencyTextField
{
    TSCurrencyTextFieldDelegate* _currencyTextFieldDelegate;
}

- (id) initWithFrame: (CGRect) frame
{
    self = [super initWithFrame: frame];
    if ( self )
    {
        [self TSCurrencyTextField_commonInit];
    }
    return self;
}

- (void) TSCurrencyTextField_commonInit
{
    // ...

    _currencyTextFieldDelegate = [TSCurrencyTextFieldDelegate new];
    [super setDelegate: _currencyTextFieldDelegate];
}

- (void) setDelegate:(id<UITextFieldDelegate>)delegate
{
    _currencyTextFieldDelegate.delegate = delegate;
}

- (id<UITextFieldDelegate>) delegate
{
    return _currencyTextFieldDelegate.delegate;
}

@end


@implementation TSCurrencyTextFieldDelegate

- (BOOL) textField: (TSCurrencyTextField *) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString *) string
{
    // ...
}

@end

Here's my Swift transalation.

protocol CurrencyTextFieldDelegate: NSObjectProtocol, UITextFieldDelegate {
    weak var delegate: UITextFieldDelegate? { get set }
}

public class CurrencyTextField: UITextField {

    override public var delegate: UITextFieldDelegate? {
        get {
            return self.delegate as? CurrencyTextFieldDelegate
        }
        set {
            self.delegate = newValue
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    private func commonInit() {

    }
}

// MARK: - CurrencyTextFieldDelegate
extension CurrencyTextField: CurrencyTextFieldDelegate {
    public func textField(textField: CurrencyTextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        return false
    }
}

But I get the following error.

Objective-C method 'textField:shouldChangeCharactersInRange:replacementString:' provided by method 'textField(:shouldChangeCharactersInRange:replacementString:)' conflicts with optional requirement method 'textField(:shouldChangeCharactersInRange:replacementString:)' in protocol 'UITextFieldDelegate'

How do I fix this error?

Isuru
  • 30,617
  • 60
  • 187
  • 303

2 Answers2

2

For what you're trying to accomplish you don't need to subclass UITextFieldDelegate.

Instead in your init method, add a target to self with the appropriate function.

override init(frame: CGRect) {
    super.init(frame: frame)
    self.addTarget(self, action: "formatText", for: .editingChanged)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.addTarget(self, action: "formatText", for: .editingChanged)
}

func formatText() {
   // Edit self.text here
}
Gaston Gonzalez
  • 427
  • 3
  • 6
0

Obj-c is much more free and easy with types and compilation checks where Swift isn't. In swift you should implement the delegate function as it is declared and not try to change any types. You can then, inside the implementation, verify the type (using if let).

Wain
  • 118,658
  • 15
  • 128
  • 151