1

How can I pass the textview value to the alertController textFields block?

I have the textview component call "myTextView"

@property (weak, nonatomic) IBOutlet UITextView *myTextView

I set the alertcontroller below:

myAlertController = [UIAlertController alertControllerWithTitle:@"title" message:@"pass the value in alertcontroller" preferredStyle: UIAlertControllerStyleAlert];
myAlertControllerOKAction = [UIAlertAction actionWithTitle:@"sure" style:UIAlertActionStyleDefault
                                                    handler:nil];
[myAlertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
    textField.keyboardType = UIKeyboardTypeDefault;
    textField.text = [self.myTextView.text stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
}];
[myAlertController addAction: myAlertControllerOKAction];

But I set the myTextView.text in the myAlertController block,

textField.text = [self.myTextView.text stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];

}];

It will show

Capturing 'self' strongly in this block is likely to lead to a retain cycle

How can I get the textview value in the alert controller block for textfield use?

Pang
  • 9,564
  • 146
  • 81
  • 122
dickfala
  • 3,246
  • 3
  • 31
  • 52

4 Answers4

0

Create a weak variable of your "self" like this outside the block:

Swift 3:

weak var w_self = self

Objective-C:

__weak MyObject *weakSelf = self;

Then use this one inside the block instead of the "self".

Pochi
  • 13,391
  • 3
  • 64
  • 104
0

You will want to create a weak reference to self before accessing myTextView inside your block:

...
__weak __typeof(self) weakSelf = self;
[myAlertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {

    textField.keyboardType = UIKeyboardTypeDefault;
    textField.text = [weakSelf.myTextView.text stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];

}];
...
Sebastian
  • 6,154
  • 5
  • 33
  • 51
  • I try to add the weakSelf, I found I can't got the textview text content in the addTextFieldWithConfigurationHandler block. Did you known how to resolve? thanks. – dickfala May 12 '17 at 02:34
  • I trace the weakSelf.myTextView.text in the addTextFieldWithConfigurationHandler block, It will get the nil value. – dickfala May 12 '17 at 02:35
  • I changed "typeof" to "__typeof" it probably fix. http://stackoverflow.com/questions/14877415/difference-between-typeof-typeof-and-typeof-objective-c – Sebastian May 12 '17 at 14:44
0

Use weak self in block:

__weak typeof(self) weakSelf = self;

[myAlertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
    textField.keyboardType = UIKeyboardTypeDefault;
    textField.text = [weakSelf.myTextView.text stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
}];

If you use strong self in a block, it may cause self not be released.

Always pass weak reference of self into block in ARC?

Community
  • 1
  • 1
tomfriwel
  • 2,575
  • 3
  • 20
  • 47
  • I trace the weakSelf.myTextView.text in the block, it will show nil. did you known why? – dickfala May 12 '17 at 02:39
  • @dickfala Do you initialize `myTextView ` or assign value to it? – tomfriwel May 12 '17 at 02:46
  • Hi, myTextView is from IBOutlet UITextView *myTextView, I had key some words, then click button show the myAlertController, I need pass the myTextView content to the myAlertController addTextFieldWithConfigurationHandler block. But I can't get the value using the __weak typeof(self) weakSelf = self; – dickfala May 12 '17 at 02:51
  • I don't known why I key the some words in the textview, the textview(call myTextView) is IBOutlet in header property. Then I click a button to show the alert, the alert have textfield, I want to show the myTextView content on the alert textfield. But I don't known why I got the nil in the addTextFieldWithConfigurationHandler block about alert controller. – dickfala May 12 '17 at 03:07
  • @dickfala I create a project [Github TestAlertController](https://github.com/tomfriwel/TestAlertController) and it works fine for me. You can download it to see what difference to your. – tomfriwel May 12 '17 at 03:12
  • thank you very much, I found the problem, the problem is I declare the myAlertController in the viewdidload, and the addTextFieldWithConfigurationHandler is in the viewdidload, So I present the alertcontroller , it always get the nil contents. thank you very much, tom. – dickfala May 12 '17 at 04:01
0

Like the others have pointed out, in Swift or ObjC you can create a weak reference to an object to avoid a strong retain cycle inside the closure.

ObjC:

__weak typeof(self) weakSelf = self;
[myAlertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
    textField.keyboardType = UIKeyboardTypeDefault;
    textField.text = [weakSelf.myTextView.text stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
}];

Swift weak:

myAlertController.addTextField(configurationHandler: { [weak self] (textField : UITextField!) -> Void in
    // Notice the guard to make sure myTextView is unwrapped
    guard let weakTextView = weak.myTextView,
        let weakText = weakTextView.text,
        weakText.characters.count > 0 else {
        return
    }
    textField.keyboardType .default
    textField.text = weakText.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
})

Swift unowned:

myAlertController.addTextField(configurationHandler: { [unowned self] (textField : UITextField!) -> Void in
    // Notice the use of unowned, unlike weak, unowned does not have to be unwrapped to avoid nil

    textField.keyboardType .default
    textField.text = unowned.weakTextView.text.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
})

In the example with unowned, noticed how I do not unwrap my unowned reference like I do with the weak one. This is because unowned is not an optional and we do not run the risk of running into nil when using unowned. I personally like using unowned better.

AgnosticDev
  • 1,843
  • 2
  • 20
  • 36