2009-04-25 6 views
18

J'ai un UIPickerView sur mon UIView avec un UITextField. Je laisse l'utilisateur sélectionner une valeur dans le sélecteur ou entrer une valeur personnalisée dans le champ de texte.UIPickerView - 1ère sélection de ligne ne pas appeler didSelectRow

Lorsque l'utilisateur sélectionne une option du sélecteur, les valeurs des variables sont modifiées avec précision (dans la méthode pickerView:didSelectRow:inComponent:). Mais si l'utilisateur ne sélectionne aucune valeur sur le sélecteur (car ils veulent sélectionner la première option qui est déjà sélectionnée), cette méthode n'est pas appelée et la sélection n'est pas reflétée dans la variable.

J'ai essayé de définir la valeur par défaut de la variable sur la première option du sélecteur. Mais dans ce cas, lorsque l'utilisateur édite le champ de texte, la variable aura le texte du champ de texte. Maintenant, si l'utilisateur décide de reprendre la première valeur, la nouvelle valeur n'est pas reflétée dans la variable.

Comment puis-je surmonter cela? Merci.

Voici le code correspondant

Dans mon viewDidLoad j'ai cette déclaration pour définir la selectText à première option du sélecteur par défaut

[self setSelectText:[myArray objectAtIndex:0]]; 

textFieldShouldReturn

- (BOOL)textFieldShouldReturn:(UITextField *)txtField{ 
    [txtField resignFirstResponder]; 
    [self setSelectText:txtField.text]; 
    return YES; 
} 

PickerViewDelegate de didSelectRow

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 
{ 
    // report the selection to the UI label 
    [self setSelectText:[myArray objectAtIndex:[pickerView selectedRowInComponent:0]]]; 
} 

Le problème se pose lorsque l'utilisateur modifie le texte, puis décide qu'il veut après tout utiliser la première valeur du sélecteur. Dans ce cas, ils vont rejeter le clavier et cliquer sur la 1ère option du sélecteur (qui est déjà sélectionné). Cette action n'appelle pas didSelectRow et la valeur de selectText n'est donc pas modifiée.

Pour que l'utilisateur puisse modifier la valeur de selectText, il doit d'abord sélectionner une autre valeur dans le sélecteur, puis sélectionner la première ligne.

+0

Si vous le pouvez, veuillez poster une partie de votre code en ce qui concerne ce problème. Cela aidera avec le dépannage. –

Répondre

25

Au lieu de « pousser » la valeur du sélecteur chaque fois que vous faites une sélection avec ce code:

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 

vous devez « tirer » lorsque l'utilisateur clique sur le bouton (ou un autre événement que vous utilisez) en utilisant quelque chose de similaire à:

- (void)myAction:(id)sender 
{ 

    NSInteger row = [myPicker selectedRowInComponent:0]; 
    selectedText = [myArray objectAtIndex:(NSUInteger)row]; 


} 

pour effacer le texte: la classe UITextField fournit un bouton intégré pour effacer le texte actuel. Donc, si l'utilisateur ne veut pas ce texte, il peut le jeter.

myTextField.clearButtonMode = UITextFieldViewModeAlways; 

Ainsi, dans le script, allez-vous vérifier si le TextField a une valeur, si elle a une valeur u utiliser le champ de texte, si elle n'a pas de valeur, vous tirez les informations du Picker.

+0

Merci. Mais le problème ici est que l'utilisateur a la possibilité de spécifier une valeur personnalisée dans un champ de texte. Il y a donc une possibilité que l'utilisateur entre du texte. Maintenant, si je fais ce que vous avez suggéré, toute valeur entrée par l'utilisateur sera ignorée. – lostInTransit

+1

La classe UITextField fournit également un bouton intégré pour effacer le texte actuel. Donc, si l'utilisateur ne veut pas ce texte, il peut le jeter. myTextField.clearButtonMode = UITextFieldViewModeAlways; –

+0

J'ai mis à jour la réponse. –

2

Pouvez-vous sélectionner par programme une ligne juste après l'instanciation de l'UIPickerView?

int firstRow = 0; 
int firstOptionIndex = 0; 
[myPickerView selectRow:firstRow inComponent:firstOptionIndex animated:NO]; 

Cette dernière ligne déclenchera votre méthode pickerView:didSelectRow:inComponent délégué. En d'autres termes, cela devrait définir la valeur de la variable, quel que soit l'endroit où vous la stockez (NSArray? Pas clair).

+0

Cela ferait l'affaire. Mais supposons que l'utilisateur décide d'entrer une valeur personnalisée dans le champ de texte. Et décide alors qu'il veut après tout utiliser la 1ère valeur dans le sélecteur. Alors maintenant, selectText a la valeur qui a été entrée dans le champ de texte. Et l'utilisateur clique simplement sur la 1ère ligne en pensant qu'il remplacera la valeur entrée dans le champ de texte. Mais cela ne se produirait pas car le programme ne connaîtrait pas l'utilisateur engagé sur la 1ère option. – lostInTransit

+0

Le fait de toucher la 1ère ligne d'une vue de sélecteur ne génère pas l'événement de sélection car vous pourriez simplement être un "défaut" avec la conception de UIPickerView telle que vous en avez besoin, mais ce n'est pas nécessairement un problème avec UITextField. Vous pourriez envisager de déposer une amélioration de fonctionnalité à UIPickerView dans http://bugreporter.apple.com. –

+0

Je vois un comportement différent. La méthode de mon délégué ne se déclenche pas lorsque je déplace le sélecteur par programme, comme vous le décrivez. Il se déclenche comme prévu si je déplace réellement le sélecteur en utilisant l'interface utilisateur. Il me semble que le délégué ne tirerait pas. Comme je déplace le sélecteur par programme, je sais qu'il a été déplacé pour pouvoir gérer les mises à jour requises. – Scooter

2
-(void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    // Only for the text field with the picker 
    if (textField == self.yourTextField && [textField length]!=0) 
    { 
     // Select the first row programmatically 
     [self.categoriesPicker selectRow:0 inComponent:0 animated:YES]; 
     // The delegate method isn't called if the row is selected programmatically 
     [self pickerView:self.categoriesPicker didSelectRow:0 inComponent:0]; 
    } 



} 

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 
{ 
    //Do all the stuff to populate the TextField 
} 
+0

l'appel forcé au délégué a fait le travail –

0

Pour surmonter le didSelectRow pas appelé dans le UIPickerView lorsque l'utilisateur a sélectionné le premier élément dans la liste, vous pouvez utiliser UITapGestureRecognizer. (Par exemple le code à Swift)

self.txtTransType = self.makeTextField(self.transType, placeHolder: "Check-in or Check-out") 
self.txtTransType?.addTarget(self, action: "txtTransTypeEditing:", forControlEvents: UIControlEvents.EditingDidBegin) 

func makeTextField(text: String?, placeHolder: String) -> UITextField { 
    var textField = UITextField(frame: CGRect(x: 140, y: 0, width: 220.00, height: 40.00)); 
    textField.placeholder = placeHolder 
    textField.text = text 
    textField.borderStyle = UITextBorderStyle.Line 
    textField.secureTextEntry = false; 
    textField.delegate = self 
    return textField 
} 

func txtTransTypeEditing(sender: UITextField) { 
    var ttPickerView:UIPickerView = UIPickerView() 
    ttPickerView.dataSource = self 
    ttPickerView.delegate = self 
    sender.inputView = ttPickerView 

    let recognizer = UITapGestureRecognizer(target: self, action:Selector("handleTransTypePickerTap:")) 
    recognizer.delegate = self 
    ttPickerView.addGestureRecognizer(recognizer) 
} 

func handleTransTypePickerTap(recognizer: UITapGestureRecognizer) { 
    let ttPickerView = recognizer.view as! UIPickerView 
    let row = ttPickerView.selectedRowInComponent(0) 
    self.txtTransType!.text = self.transTypeData[row] 
} 

Utilisez le lien ci-dessous UIGestureRecognizer Tutorial: Getting Started pour obtenir robinet de reconnaissance au travail (besoin d'ajouter UIGestureRecognizerDelegate) et le code suivant

class TransactionViewController: UIViewController, UITextFieldDelegate,UIPickerViewDataSource,UIPickerViewDelegate, UIGestureRecognizerDelegate { } 

func gestureRecognizer(UIGestureRecognizer, 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool { 
     return true 
} 
2

Vous pouvez appeler directement la méthode du délégué comme

picker.delegate?.pickerView?(picker, didSelectRow: 0, inComponent: 0) 
Questions connexes