6

So, I have a textfield where I setup its delegate. Most of the time it would work as expected, shouldChangeCharacters is called but very few times shouldChangeCharacters is not called.

Now, I thought this could just be a race condition but it only happens on some clean & build runs. And when it does happen, it is very consistent, even if the instance is recreated it still happens consistently. That's why I've ruled it out as a race issue, and think of it as an undefined behavior during compile/machine code creation.

So, my question is do I violate Objc and Swift runtime with how my extensions and protocol conformations are setup? If so, how to resolve?

class LabelAndTextFieldView: UIView{
   let textField: UITextField
   var delegate: LabelAndTextFieldViewDelegate?{ //strong so it would not dealloc
      didSet{
          textField.delegate = delegate
      }
   }
}


extension LabelAndTextFieldView{
   class LabelAndTextFieldViewDelegate: NSObject{
      //some methods unrelated to uitextfieldDelegate
   }  


   class AmountFormattingTextFieldDelegate: LabelAndTextFieldViewDelegate{
      func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
         //disallow if not numeric
      }

   }


}

extension LabelAndTextFieldView.LabelAndTextFieldViewDelegate: UITextFieldDelegate{
  //other uitextfield delegate methods EXCEPT shouldChangeCharactersInRange
}





//code assignment

class SomeVC{
   @IBOutlet weak var labelTextFieldView: LabelAndTextFieldView!


   override func viewDidLoad(){
      super.viewDidLoad()
      labelTextFieldView.delegate = AmountFormattingTextFieldDelegate() //this will not dealloc because intended strong on delegate

   }
}

  • `didSet` does not have access to `newValue`. Are you using `willSet` instead or are you using `delegate` inside `didSet`? – Malik May 07 '19 at 05:21
  • Ah will edit code sample, wasn't accessing via `newValue` but via `delegate` – Joshua Francis Roman May 07 '19 at 05:22
  • 1
    From the looks of it, there seems to be a type issue. `textField.delegate` expects a delegate of type `UITextFieldDelegate`. However, in your `didSet`, you're assigning it `delegate` which is of type `XYZDelegate` which in turn inherits from both `NSObject` and `UITextFieldDelegate`. I'd have to see the code where you are assigning value to `delegate` as it will accept values of both `XYZDelegate` and `UITextFieldDelegate` types. – Malik May 07 '19 at 05:29
  • @Malik but doesn't `XYZDelegate` conform to `UITextFieldDelegate` so there shouldn't be an issue? And if its a type issue it should consistently not work and show a warning. – Joshua Francis Roman May 07 '19 at 05:31
  • Agreed. But the code you have shown is not bound by any business logic thereby making it difficult to pinpoint the issue. Having a look at more code (especially the assignment of `delegate` property) will establish the logical requirements which might shed a bit more light on what the cause of the problem is. – Malik May 07 '19 at 05:35
  • Okay, will edit the snippet to show business logic – Joshua Francis Roman May 07 '19 at 05:36
  • Can you specify which class in there actually inherit from `NSObject`. Does `XYZ`? Did you try prefixing `UITextFieldDelegate` methods in both places with `@objc`? Are `UITextFieldDelegate` methods other than `shouldChangeCharactersInRange ` properly called every time? – amadour May 07 '19 at 05:39
  • @amadour class definition is as:is with my code. Nope, did not prefix `@objc` and haven't had the chance to check if other delegate methods are properly called since it is hard to reproduce – Joshua Francis Roman May 07 '19 at 05:43
  • Ah, and why did you not declare `class AmountFormattingTextFieldDelegate: LabelAndTextFieldViewDelegate` to also conform to `UITextFieldDelegate`, since it does implement part of the protocol? Maybe that's what confuses the compiler somehow? – amadour May 07 '19 at 05:50
  • @amadour do I have to explicitly state that `AmountFormattingTextFieldDelegate` conforms to `UITextFieldDelegate`? Shouldn't it already be inherited from superclass? Wouldn't doing so be redundant and show a compiler warning? – Joshua Francis Roman May 07 '19 at 06:14
  • Something wrong with your code snippet. You can't use LabelAndTextFieldView as `@IBOutlet` because it must conform to NSObject and have `@objc` attribute. Could you show how you use LabelAndTextFieldView at storyboard or xib? Or maybe you can provide some worked sample project? So it would be easier to reproduce the issue. – Anton Vlasov May 09 '19 at 12:20
  • I tried to run your code. The 1st problem I found is that `textField` in `LabelAndTextFieldView` is declared but not initialized. I assume this should read `@IBOutlet weak var textField: UITextField!`. The 2nd problem is that the compiler complains about `labelTextFieldView.delegate = AmountFormattingTextFieldDelegate(): Use of unresolved identifier 'AmountFormattingTextFieldDelegate‘`. It had to be replaced by `labelTextFieldView.delegate = LabelAndTextFieldView.AmountFormattingTextFieldDelegate()`. With these modifications, it does always call shouldChangeCharactersIn as far as I tested it. – Reinhard Männer May 15 '19 at 09:46
  • @ReinhardMänner how did you test it? Multiple runs or a single run and re-test? It is only reproducible on different runs, and still rarely. Your point #1 and #2 are correct – Joshua Francis Roman May 15 '19 at 09:50
  • Sorry, I missed that. I tested only a single run. Does it happen on a simulator or/and on a device? – Reinhard Männer May 15 '19 at 09:54
  • @ReinhardMänner reproduced on simulator, haven't tried in an actual device. From what I've noticed, it happens in 1/20 runs – Joshua Francis Roman May 15 '19 at 09:56
  • I tried it maybe 30 times but could not reproduce your issue. What happens, if shouldChangeCharactersIn is not called? Is the typed character just accepted, as if this function had returned `true`? – Reinhard Männer May 15 '19 at 10:13
  • Yes, treated as yes. hmm. could be something in my project. Will close the question as something not reproducible – Joshua Francis Roman May 16 '19 at 01:08

0 Answers0