I have a number of text fields that offer a selection of pre defined values in the form of a picker view. Occasionally, usually after a lot of text boxes have been filled in, the picker goes black, then the app crashes.
I cant seem to reproduce the problem, it just happens occasionally...reported by some users. As ive picked up this code form someone else maybe I have missed something?
Here is the code for the custom class for the text box/pickers
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.touchEnabled = YES;
self.textField = nil;
self.editableTextField = nil;
__selectedValue = #"";
self.pickerView = nil;
self.button = nil;
self.textValue = nil;
self.otherSelected = NO;
self.backgroundColor = [UIColor clearColor];
self.userInteractionEnabled = YES;
self.values = [NSArray arrayWithObjects:#"Value1", #"Value2", #"Other", nil];
}
return self;
}
- (void)layoutSubviews
{
if (self.textField == nil) {
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, 31.0f)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.font = [UIFont systemFontOfSize:12.0f];
UIPickerView *pickerView = [[UIPickerView alloc] init];
[pickerView sizeToFit];
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.showsSelectionIndicator = YES;
if (self.textValue != nil && ![self.textValue isEqualToString:#""]) {
textField.text = self.textValue;
int matchedIndex = -1;
int otherIndex = -1;
for (int i = 0; i < self.values.count; i++) {
NSString *value = [self.values objectAtIndex:i];
if ([value isEqualToString:#"Other"]) {
otherIndex = i;
}
if ([self.textValue isEqualToString:[self.values objectAtIndex:i]]) {
matchedIndex = i;
}
}
if (matchedIndex > -1) {
[pickerView selectRow:matchedIndex inComponent:0 animated:NO];
} else if (otherIndex > -1) {
[pickerView selectRow:otherIndex inComponent:0 animated:NO];
}
}
textField.inputView = pickerView;
self.pickerView = pickerView;
UIToolbar *accessoryView = [[UIToolbar alloc] init];
[accessoryView sizeToFit];
accessoryView.barStyle = UIBarStyleBlackOpaque;
accessoryView.tintColor = [UIColor grayColor];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(pickerDone:)];
self.doneButton = doneButton;
accessoryView.items = [NSArray arrayWithObjects:spacer, doneButton, nil];
textField.inputAccessoryView = accessoryView;
[self addSubview:textField];
self.textField = textField;
}
if (self.button == nil) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor clearColor];
button.frame = self.bounds;
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
self.button = button;
}
}
- (void)buttonPressed:(id)sender
{
if (self.fieldDelegate != nil) {
[self.fieldDelegate performSelector:#selector(fieldBeganEditing:) withObject:self];
}
if (self.otherSelected) {
self.doneButton.action = #selector(textFieldDone:);
self.textField.inputView = nil;
} else {
self.doneButton.action = #selector(pickerDone:);
self.textField.inputView = self.pickerView;
}
[self.textField becomeFirstResponder];
}
- (void)textFieldDone:(id)sender
{
LogCmd();
[self.textField resignFirstResponder];
self.textField.inputView = self.pickerView;
self.doneButton.action = #selector(pickerDone:);
[self.textField becomeFirstResponder];
}
- (void)pickerDone:(id)sender
{
LogCmd();
NSString *value = [self.values objectAtIndex:[self.pickerView selectedRowInComponent:0]];
if (!self.otherSelected) {
self.textField.text = value;
__selectedValue = value;
}
[self.textField resignFirstResponder];
}
/*- (void)setValues:(NSArray *)values
{
_values = values;
[self.pickerView reloadAllComponents];
}*/
#pragma mark - UITextFieldDelegate
- (void)textFieldDidEndEditing:(UITextField *)textField
{
LogCmd();
}
#pragma mark - UIPickerViewDelegate
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent: (NSInteger)component
{
NSString *value = [self.values objectAtIndex:row];
if ([value isEqualToString:#"Other"]) {
self.otherSelected = YES;
self.textField.text = #"";
__selectedValue = #"";
[self.doneButton setAction:#selector(textFieldDone:)];
self.textField.inputView = nil;
[self.textField resignFirstResponder];
[self.textField becomeFirstResponder];
//[self.textField performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.2];
} else {
self.otherSelected = NO;
self.textField.text = value;
__selectedValue = value;
}
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent: (NSInteger)component
{
return [self.values objectAtIndex:row];
}
#pragma mark - UIPickerViewDataSource
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return self.values.count;
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
Related
I have 5 tables, and I have to make an UIPickerView for each one.
I created one, like this
How can I do with the 4 others table ? I have to make 4 copy of this code ?
I do not know if I'm the right way to create my UIPickerView , I would like confirmation (or not).
This is what I did (I took the code from my colleague, who is also a beginner)
This is the right way to do ?
How to adapt it if I UIPickerViews 5 ?
#property (nonatomic, strong) UITextField *pickerViewDossier;
- (void)viewDidLoad {
[super viewDidLoad];
self.pickerViewDossier = [[UITextField alloc] initWithFrame:CGRectZero];
[self.view addSubview:self.pickerViewDossier];
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
self.pickerViewDossier.inputView = pickerView;
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Valider" style:UIBarButtonItemStyleDone target:self action:#selector(doneTouched:)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:#"Annuler" style:UIBarButtonItemStyleDone target:self action:#selector(cancelTouched:)];
[toolBar setItems:[NSArray arrayWithObjects:cancelButton, [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], doneButton, nil]];
self.pickerViewDossier.inputAccessoryView = toolBar;
self.listeSuiviDossier = [NSArray arrayWithObjects:#"Vous-même", #"Un confrère",nil];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return listeSuiviDossier.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSString *titrePickerview = listeSuiviDossier[row];
return titrePickerview;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSString *titrePickerview = listeSuiviDossier[row];
[suiviDossierBouton setTitle:titrePickerview forState:UIControlStateNormal];
}
- (IBAction)suiviDossierAction:(id)sender {
[self.pickerViewDossier becomeFirstResponder];
}
- (void)cancelTouched:(UIBarButtonItem *)sender
{
[self.pickerViewDossier resignFirstResponder];
[suiviDossierBouton setTitle:#"Sélectionnez" forState:UIControlStateNormal];
}
- (void)doneTouched:(UIBarButtonItem *)sender
{
[self.pickerViewDossier resignFirstResponder];
}
Use tag for picker so that you can select what to do for each picker.
For example:
Where you are Declaring your pickers:
picker1.tag = 1
picker2.tag = 2
and for each method:
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger) {
if(pickerView.tag == 1) // you can also use a switch
{
// picker 1
}
else if(pickerView.tag == 2)
{
// picker 2
}
else if(pickerView.tag == 3)
{
// picker 3
}
else if(pickerView.tag == 4)
{
// picker 4
}
}
#import "ViewController.h"
#interface ViewController ()<UIPickerViewDelegate,UIPickerViewDataSource>
{
int selectedTextfieldValue;
NSArray *namesArray , *genderArray, *ageArray;
UIToolbar *pickerToolbar;
}
#end
#implementation ViewController
#synthesize myPickerView;
-(void)viewDidLoad
{
[super viewDidLoad];
namesArray=[[NSArray alloc]initWithObjects:#"a",#"b", nil];
genderArray=[[NSArray alloc]initWithObjects:#"M",#"F", nil];
ageArray=[[NSArray alloc]initWithObjects:#"26",#"25", nil];
selectedTextfieldValue=0;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[self.view endEditing:YES];
if (textField==_text1)
{
_text1.delegate=self;
}
else
if(textField==_text2)
{
_text2.delegate=self;
}
else
{
_text3.delegate=self;
}
NSLog(#"%d",textField.tag);
selectedTextfieldValue=(int)textField.tag;
NSLog(#"%d",selectedTextfieldValue);
// call picker here according to textfield tag you can set text to textfiled
[self popoverWithInformation];
}
-(void)popoverWithInformation
{
pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 220, 44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(pickerCancel:)];
[barItems addObject:cancelBtn];
/* UIBarButtonItem flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
[barItems addObject:flexSpace];/
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDone:)];
[barItems addObject:doneBtn];
[pickerToolbar setItems:barItems animated:YES];
myPickerView = [[UIPickerView alloc] init];
myPickerView.showsSelectionIndicator = YES;
CGRect pickerRect = myPickerView.bounds;
myPickerView.bounds = pickerRect;
myPickerView.frame = CGRectMake(0, 44, 320, 216);
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 300)];
popoverView.backgroundColor = [UIColor whiteColor];
[popoverView addSubview:myPickerView];
[popoverView addSubview:pickerToolbar];
[self.view addSubview:popoverView];
}
// tell the picker how many rows are available for a given component
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component
{
int count = 0;
switch (selectedTextfieldValue)
{
case 1:
count =namesArray.count;
NSLog(#"%d",count);
break;
case 2:
count =genderArray.count;
NSLog(#"%d",count);
break;
case 3:
count =ageArray.count;
NSLog(#"%d",count);
break;
default:
NSLog(#"default in count");
break;
}
return count;
}
// tell the picker how many components it will have
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
// tell the picker the title for a given component
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *title;
switch (selectedTextfieldValue) {
case 1:
title =namesArray[row];
break;
case 2:
title =genderArray[row];
break;
case 3:
title =ageArray[row];
break;
default:
NSLog(#"default");
break;
}
return title;
}
// tell the picker the width of each row for a given component
-(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
int sectionWidth = 300;
return sectionWidth;
}
-(void)pickerDone:(id)sender
{
NSLog(#"Done Clicked");
NSLog(#"Done Clicked%d",selectedTextfieldValue);
myPickerView.hidden=YES;
pickerToolbar.hidden=YES;
}
-(void)pickerCancel:(id)sender
{
NSLog(#"cancel");
myPickerView.hidden=YES;
pickerToolbar.hidden=YES;
}
#end
I want to display the values of array in picker view and for that I take 3 arrays and 3 textfield but picker view not showing the data.
any help would be highly appreciated.
In this you don't need to make PickerView every time. Make first time pickerview and reload components every time
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[self.view endEditing:YES];
if (textField==_text1)
{
_text1.delegate=self;
} else if(textField==_text2) {
_text2.delegate=self;
} else {
_text3.delegate=self;
}
selectedTextfieldValue=(int)textField.tag;
[myPickerView reloadAllComponents];
}
May be it's help full other wise visit here UIPickerView programatic & UIPickerView Tutorial
My below code working fine in below iOS 7
I am trying to add picker view in alert that works fine in below ios7 version But in ios 7 it show white alert without picker view.
-(void)showPinPickerAlert
{
numberarr = [[NSMutableArray alloc]initWithObjects:#"0",#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9", nil];
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:#"Enter Pin To Change Track me Option" message:#"\n\n\n\n\n\n\n" delegate:self cancelButtonTitle:#"Verify" otherButtonTitles:nil];
UIPickerView *picker=[[UIPickerView alloc]initWithFrame:CGRectMake(25, 30, 230, 60) ];
picker.dataSource=self;
picker.delegate=self;
// picker.backgroundColor=[UIColor blueColor];
picker.showsSelectionIndicator = YES;
// picker.autoresizingMask = UIViewAutoresizingFlexibleHeight;
picker.transform = CGAffineTransformMakeScale(0.6, 0.6);
alert.tag=100;
// picker.transform = CGAffineTransformMakeScale(1, 0.2);
[alert addSubview:picker];
[alert show];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
{
return 4;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
strPin=[[NSString stringWithFormat:#"%i%i%i%i",[pickerView selectedRowInComponent:0],[pickerView selectedRowInComponent:1],[pickerView selectedRowInComponent:2],[pickerView selectedRowInComponent:3]]mutableCopy];
NSLog(#"strPin=%#",strPin);
// mlabel.text= [arrayNo objectAtIndex:row];
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
{
return [numberarr count];
}
**//code try to change color of picker text and background thats work fine in below ios7 but in iOS 7 still shows white screen**
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = (UILabel*) view;
if (label == nil)
{
label = [[UILabel alloc] init];
}
//[label setText:#"Whatever"];
// This part just colorizes everything, since you asked about that.
[label setTextColor:[UIColor whiteColor]];
[label setBackgroundColor:[UIColor blackColor]];
CGSize rowSize = [pickerView rowSizeForComponent:component];
CGRect labelRect = CGRectMake (0, 0, rowSize.width, rowSize.height);
[label setFrame:labelRect];
return label;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
{
pickerView.backgroundColor=[UIColor blackColor];
return [numberarr objectAtIndex:row];
}
OutPut in below
Output in IOS 7
How to fix it?
Adding subviews to a UIAlertView is not supported anymore, starting in iOS7.
You should implement your own view and try to do it similar to the alert view, or like other person said, use a 3rd party alert view like this one:
https://github.com/wimagguc/ios-custom-alertview
Most of the following code is from pre ios7 stack overflow answers.
PickerPrompt.h
#import <UIKit/UIKit.h>
#interface PickerPrompt : UIAlertView <UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate>
{
UIPickerView *_pickerView;
NSMutableArray *_options;
}
#property (readonly) NSString *enteredText;
- (id)initWithTitle:(NSString *)title message:(NSString *)message options:(NSMutableArray*)options delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle okButtonTitle:(NSString *)okButtonTitle;
#end
pickerPrompt.m
#import "PickerPrompt.h"
#implementation PickerPrompt
#define VIEW_TAG 49
#define SUB_LABEL_TAG 52
#define LABEL_TAG 53
#define COMPONENT_WIDTH 250
#define LABEL_WIDTH 10
#synthesize enteredText;
- (id)initWithTitle:(NSString *)title message:(NSString *)message options:(NSMutableArray*)options delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle okButtonTitle:(NSString *)okayButtonTitle
{
if (self = [super initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:okayButtonTitle, nil])
{
_options = options;
_pickerView = [[UIPickerView alloc] init];
[_pickerView sizeToFit];
[_pickerView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[_pickerView setDelegate:self];
[_pickerView setDataSource:self];
[_pickerView setShowsSelectionIndicator:TRUE];
// Change from pre iOS 7
[self setAlertViewStyle:UIAlertViewStylePlainTextInput];
[[self textFieldAtIndex:0] setDelegate:self];
[[self textFieldAtIndex:0] setInputView:_pickerView];
[[self textFieldAtIndex:0] becomeFirstResponder];
}
return self;
}
#pragma mark -
#pragma mark Picker delegate
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (pickerView == _pickerView) {
return [_options count];
}
return [_options count];
}
- (UIView *)labelCellWithWidth:(CGFloat)width rightOffset:(CGFloat)offset {
// Create a new view that contains a label offset from the right.
CGRect frame = CGRectMake(0.0, 0.0, width, 32.0);
UIView *view = [[[UIView alloc] initWithFrame:frame] autorelease];
view.tag = VIEW_TAG;
frame.size.width = width - offset;
UILabel *subLabel = [[UILabel alloc] initWithFrame:frame];
subLabel.textAlignment = UITextAlignmentRight;
subLabel.backgroundColor = [UIColor clearColor];
subLabel.font = [UIFont systemFontOfSize:24.0];
subLabel.userInteractionEnabled = NO;
subLabel.tag = SUB_LABEL_TAG;
[view addSubview:subLabel];
[subLabel release];
return view;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *fullString = [[textField text] stringByAppendingString:string];
for (NSString* object in _options) {
if ([object isEqualToString:fullString]) {
return YES;
}
}
return NO;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UIView *returnView = nil;
if ((view.tag == VIEW_TAG) || (view.tag == LABEL_TAG)) {
returnView = view;
}
else {
returnView = [self labelCellWithWidth:COMPONENT_WIDTH rightOffset:LABEL_WIDTH];
}
// The text shown in the component is just the number of the component.
NSString *text = [_options objectAtIndex:row];
// Where to set the text in depends on what sort of view it is.
UILabel *theLabel = nil;
if (returnView.tag == VIEW_TAG) {
theLabel = (UILabel *)[returnView viewWithTag:SUB_LABEL_TAG];
}
else {
theLabel = (UILabel *)returnView;
}
theLabel.text = text;
return returnView;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return COMPONENT_WIDTH;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
[[self textFieldAtIndex:0] setText:[_options objectAtIndex:row]];
}
- (NSString *)enteredText
{
return [[self textFieldAtIndex:0] text];
}
#end
How to use (called from an alert view delegate):
PickerPrompt *prompt = [PickerPrompt alloc];
NSMutableArray *options = [[NSMutableArray alloc] initWithObjects:#"option 1", #"option 2", nil];
prompt = [prompt initWithTitle:#"Select Option" message:#"Select Option" options:options delegate:self cancelButtonTitle:#"Cancel" okButtonTitle:#"Okay"];
[prompt show];
[prompt release];
I've got 3 table cells and somehow it displays the two last contents in the last cell. I did something wrong somewhere in my code, but I don't know where since I just follow a tutorial and try to do the same like in the tutorial, but instead of 2 cells I want 3 editable cells.
the full code:
#import "LocationAddViewController.h"
#import "Location.h"
#interface LocationAddViewController ()
- (void)prepareCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath;
- (UIBarButtonItem *)newCancelButton;
- (UIBarButtonItem *)newSaveButton;
- (UITextField *)newTextField;
#end
#implementation LocationAddViewController
#synthesize location;
#synthesize titleField;
#synthesize authorField;
#synthesize atextField;
#synthesize delegate;
- (void)dealloc {
[location release];
[titleField release];
[authorField release];
[atextField release];
[super dealloc];
}
- (id)initWithLocation:(Location *)aLocation andDelegate:(id)aDelegate {
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
self.location = aLocation;
self.delegate = aDelegate;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.allowsSelection = NO;
titleField = [self newTextField];
titleField.keyboardType = UIKeyboardTypeASCIICapable;
[titleField becomeFirstResponder];
authorField = [self newTextField];
authorField.keyboardType = UIKeyboardTypeASCIICapable;
atextField = [self newTextField];
atextField.keyboardType = UIKeyboardTypeASCIICapable;
if (location.onelocationId) {
titleField.text = location.title;
authorField.text = location.author;
atextField.text = location.text;
} else {
titleField.placeholder = #"Title";
authorField.placeholder = #"Author";
atextField.placeholder = #"Text";
}
UIBarButtonItem *cancelButton = [self newCancelButton];
self.navigationItem.leftBarButtonItem = cancelButton;
[cancelButton release];
UIBarButtonItem *saveButton = [self newSaveButton];
self.navigationItem.rightBarButtonItem = saveButton;
saveButton.enabled = NO;
[saveButton release];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (location.onelocationId) {
self.title = #"Edit Location";
} else {
self.title = #"Add Location";
}
}
-(IBAction)cancel {
[self.navigationController popViewControllerAnimated:YES];
}
-(IBAction)save {
location.title = titleField.text;
location.author = authorField.text;
location.text = atextField.text;
[self.delegate didChangeLocation:location];
[self.navigationController popViewControllerAnimated:YES];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)aTableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:nil] autorelease];
[self prepareCell:cell forIndexPath:indexPath];
return cell;
}
- (void)prepareCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
[cell.contentView addSubview:titleField];
} else {
[cell.contentView addSubview:authorField];
[cell.contentView addSubview:atextField];
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
if (textField == titleField) {
[authorField becomeFirstResponder];
}
if (titleField == authorField) {
[self save];
}
return YES;
}
- (IBAction)textFieldChanged:(id)sender {
BOOL enableSaveButton =
([self.titleField.text length] > 0) && ([self.authorField.text length] > 0) && ([self.atextField.text length] > 0);
[self.navigationItem.rightBarButtonItem setEnabled:enableSaveButton];
}
- (UIBarButtonItem *)newCancelButton {
return [[UIBarButtonItem alloc]
initWithTitle:#"Cancel"
//auch im Original gelb
style:UIBarButtonSystemItemCancel
target:self
action:#selector(cancel)];
}
- (UIBarButtonItem *)newSaveButton {
return [[UIBarButtonItem alloc]
initWithTitle:#"Save"
//auch im Original gelb
style:UIBarButtonSystemItemSave
target:self
action:#selector(save)];
}
- (UITextField *)newTextField {
UITextField *textField =
[[UITextField alloc] initWithFrame:CGRectMake(10, 10, 285, 25)];
textField.font = [UIFont systemFontOfSize:16];
textField.delegate = self;
textField.returnKeyType = UIReturnKeyDone;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
[textField addTarget:self
action:#selector(textFieldChanged:)
forControlEvents:UIControlEventEditingChanged];
return textField;
}
#end
I suppose the problem is here:
- (void)prepareCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
[cell.contentView addSubview:titleField];
} else {
[cell.contentView addSubview:authorField];
[cell.contentView addSubview:atextField];
}
}
I'm not too much into the whole programming, but I guess I have to write 3 if-clauses? (Something like if (...) elsif (...) else (...)) Does anybody know it better than me?
In your prepareCell:forIndexPath, you are adding both subviews into the last cell. You can use an elseif just as your described so your method looks something like this
if (indexPath.row == 0) {
[cell.contentView addSubview:titleField];
} else if (indexPath.row == 1) {
[cell.contentView addSubview:authorField];
} else {
[cell.contentView addSubview:atextField];
}
You can add any amount of else ifs after the if.
You're right about the source of the error. You're adding authorField & atextField at the same coordinates. The correct way to include 3 causes for ifs is:
if (/* condition 1 */) {
}
else if ( /* condition 2 */) {
}
else if ( /* condition 3 */) {
}
Do this:
- (void)prepareCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
[cell.contentView addSubview:titleField];
} else if(indexPath.row == 1) {
[cell.contentView addSubview:authorField];
}else if(indexPath.row == 2) {
[cell.contentView addSubview:atextField];
}
}
if (indexPath.row == 0) {
[cell.contentView addSubview:titleField];
} else if(indexPath.row == 1) {
[cell.contentView addSubview:authorField];
}else if(indexPath.row == 2) {
[cell.contentView addSubview:atextField];
}
I am trying to explore some codes in Objective-C. I came across an open source program - batch renamer. I was looking at its code and adding my own implementation. There is one thing in this code that I could not understand - I was hoping someone would be able to help me out.
The problem is that there is a renamer delegate "- (void)renamed" and I have no idea how it is called. So, I was wondering how does the program know when to call/use this delegate.
The code is as follows:
#import "ControllerMain.h"
static NSString *addFilesIdentifier = #"addFiles_item";
static NSString *removeFilesIdentifier = #"removeFiles_item";
static NSString *cleanAllIdentifier = #"cleanAll_item";
static NSString *updateUrl = #"http://www.hardboiled.it/software/update.xml";
#implementation ControllerMain
- (id)init
{
self = [super init];
//init some object
tableSource = [[NSMutableArray alloc] init];
updater = [[STUpdateChecker alloc] init];
renamer = [[STRenamer alloc] init];
//set some variables
withExt = NO;//for include the extension in the renaming, default NO
renamed = NO;//is YES after renaming preview
insoverappPosition = 0;
//set the notification for NSControlTextDidChangeNotification
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(textDidEndEditing:) name:#"NSControlTextDidChangeNotification" object:nil];
return self;
}
-(void)awakeFromNib
{
//set the delegates
[tabella setDelegate:self];
[tableSource setDelegate:self];
[renamer setDelegate:self];
[updater setDelegate:self];
//check if the software is updated
[updater checkUpdateWithUrl:[NSURL URLWithString:updateUrl]];
//drag' drop - set the dragged types
[tabella registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
//toolbar configuration
toolbar = [[NSToolbar alloc] initWithIdentifier:#"toolbar"];
[toolbar setDelegate:self];
//mainWindows properties
[mainWindow center];
[mainWindow setTitle:#"macXrenamer"];
[mainWindow setToolbar:toolbar];
//set the extension checkbox
[extSwitch setState:0];
//Set the custom cell imageAndTextCell
ImageAndTextCell *imageAndTextCell = nil;
NSTableColumn *tableColumn = nil;
tableColumn = [tabella tableColumnWithIdentifier:#"original_name"];
imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease];
[imageAndTextCell setEditable: NO];
[tableColumn setDataCell:imageAndTextCell];
//
//initialize the window for empty table
[self tableSourceIsEmpty];
//release the toolbar
[toolbar release];
}
- (void)dealloc
{
//release all
[tabella unregisterDraggedTypes];
[tableSource release];
[renamer release];
[super dealloc];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
//close the application
return YES;
}
/* ################### tableSource delegates #################################*/
- (void)tableSourceIsEmpty
{
if (KDEBUG)
NSLog(#"tablesource is empty");
[upper_lower setEnabled:NO];
[from setEditable:NO];
[to setEditable:NO];
[insertText setEditable:NO];
[insertAtPosition setEditable:NO];
[insertAtPosition setIntValue:0];
[renameButton setEnabled:NO];
[annullButton setEnabled:NO];
[searchField setEditable:NO];
[replaceField setEditable:NO];
}
- (void)tableSourceIsNotEmpty
{
if (KDEBUG)
NSLog(#"tablesource is not empty");
[upper_lower setEnabled:YES];
[from setEditable:YES];
[to setEditable:YES];
[insertText setEditable:YES];
[insertAtPosition setEditable:YES];
[searchField setEditable:YES];
[replaceField setEditable:YES];
}
-(void)tableSourceDidChange
{
NSString *countString = [NSString stringWithFormat:#"%d files",[tableSource count]];
[number_of_files setStringValue:countString];
}
/*####################end tableSource delegates###############################*/
/*######################renamer delegates#####################################*/
- (void)renamed
{
NSLog(#"renaming preview ok");
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor blackColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor blackColor]];
[to setTextColor:[NSColor blackColor]];
}
renamed = YES;
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
}
- (void)notRenamed
{
renamed = NO;
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor redColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor redColor]];
[to setTextColor:[NSColor redColor]];
}
NSLog(#"exception in preview delegate");
[renameButton setEnabled:NO];
}
/* ###################end renamer delegates ##################################*/
//make the file extension editable
-(IBAction)makeExtEditable:(id)sender
{
if (KDEBUG)
NSLog(#"makeExtEditable action");
if ([sender state] == 0) {
withExt = NO;
}else if ([sender state] == 1) {
withExt = YES;
}
}
//add files to the table
-(IBAction)addFiles:(id)sender
{
//start the progression bar
[progBar startAnimation:self];
int result;
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
[oPanel setCanChooseFiles:YES];
[oPanel setAllowsMultipleSelection:YES];
[oPanel setResolvesAliases:NO];
result = [oPanel runModalForTypes:nil];
if (result == NSOKButton) {
NSArray *filesToOpen = [oPanel filenames];
[tableSource add:filesToOpen];
[tabella reloadData];
}
//stop the progression bar
[progBar stopAnimation:self];
}
//remove files from the table
-(IBAction)removeFiles:(id)sender
{
if(KDEBUG)
NSLog(#"remove the selected file from the table");
[progBar startAnimation:self];
NSIndexSet *selected = [tabella selectedRowIndexes];
[tableSource removeAtIndexes:selected];
[tabella reloadData];
[progBar stopAnimation:self];
}
//remove all files from the table
-(IBAction)clearTable:(id)sender
{
if(KDEBUG)
NSLog(#"clear all table");
[progBar startAnimation:self];
[tableSource cleanAll];
[tabella reloadData];
[progBar stopAnimation:self];
}
//annull
-(IBAction)annulRenaming:(id)sender
{
[tableSource annull];
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor blackColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor blackColor]];
[to setTextColor:[NSColor blackColor]];
}
renamed = NO;
[renameButton setEnabled:NO];
[tabella reloadData];
}
/*###########################log section######################################*/
-(IBAction)showLogWindows:(id)sender{
if ([logWindow isVisible]) {
[logWindow setIsVisible:FALSE];
}else {
[logWindow setIsVisible:TRUE];
}
}
-(void)addToLog:(NSString *)text
{
NSString *textLog = [text stringByAppendingString:#"\n\r"];
NSRange endRange;
endRange.location = [[logField textStorage] length];
endRange.length = 0;
[logField replaceCharactersInRange:endRange withString:textLog];
endRange.length = [textLog length];
[logField scrollRangeToVisible:endRange];
}
/*#######################end log section######################################*/
/*######################editing actions#######################################*/
-(IBAction)finalRenaming:(id)sender
{
if(KDEBUG)
NSLog(#"renaming button pressed");
//start the progression bar
[progBar startAnimation:self];
//count of the files really renamed
int countRenamed = 0;
//count of the renaming error
int errRenamed = 0;
//the result of rename()
int renameResult;
//the enumerator and the obj
NSEnumerator *en = [tableSource objectEnumerator];
id row;
if(renamed)
{
while(row = [en nextObject])
{
renameResult = rename([[row objectAtIndex:0] fileSystemRepresentation], [[row objectAtIndex:1] fileSystemRepresentation]);
if(renameResult == 0){
NSString *textLog = [NSString stringWithFormat:#"%# renamed with\n %#", [row objectAtIndex:0],[row objectAtIndex:1]];
NSLog(textLog);
[self addToLog:textLog];
countRenamed++;
}else {
NSString *textLog =[NSString stringWithFormat: #"Error in file renaming %#", [row objectAtIndex:0]];
NSLog(textLog);
[self addToLog:textLog];
errRenamed++;
}
}
if(errRenamed >0){
//open the panel alert
int result;
result = NSRunAlertPanel(#"Renaming error. Please check the log", #"Error!", #"Ok", NULL, NULL);
}
//print the result of renaming
[notiField setStringValue:[NSString stringWithFormat:#"renamed %d/%d files, %d errors", countRenamed,[tableSource count],errRenamed]];
//
[tableSource reinitialize];
[tabella reloadData];
[renameButton setEnabled:NO];
[annullButton setEnabled:NO];
[progBar stopAnimation:self];
}
}
- (void)textDidEndEditing:(NSNotification *)aNotification
{
[progBar startAnimation:self];
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
if(KDEBUG)
NSLog(#"insert selected");
if(insoverappPosition == 1)
{
if(KDEBUG)
NSLog(#"overwrite selected");
tableSource = [renamer overwriteChar:tableSource insertText:[insertText stringValue] position:[insertAtPosition intValue] withExt:withExt];
}else if(insoverappPosition == 0){
if(KDEBUG)
NSLog(#"insert selected");
tableSource = [renamer insertChar:tableSource insertText:[insertText stringValue] position:[insertAtPosition intValue] withExt:withExt];
}else if(insoverappPosition == 2){
if(KDEBUG)
NSLog(#"append selected");
tableSource = [renamer appendChar:tableSource appendText:[insertText stringValue] withExt:withExt];
}
}else if ([tabViewId isEqual:#"remove"]) {
if(KDEBUG)
NSLog(#"remove selected");
tableSource = [renamer removeChar:tableSource from:[from intValue] to:[to intValue] withExt:withExt];
}else if([tabViewId isEqual:#"search"]){
if(KDEBUG)
NSLog(#"search selected");
tableSource = [renamer searchAndReplace:tableSource string:[searchField stringValue] withString:[replaceField stringValue] withExt:withExt];
}
[progBar stopAnimation:self];
}
-(IBAction)upLowerCellClicked:(id)sender
{
NSCell* cell;
cell = [upper_lower selectedCell];
int tag = [cell tag];
if (tag == 0) {
if(KDEBUG)
NSLog(#"lowercase selected");
tableSource = [renamer makeLowerCase:tableSource withExt:withExt];
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
[tabella reloadData];
}
else if(tag == 1){
if(KDEBUG)
NSLog(#"uppercase selected");
tableSource = [renamer makeUpperCase:tableSource withExt:withExt];
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
[tabella reloadData];
}
}
-(IBAction)insertOverwriteClicked:(id)sender
{
if(KDEBUG)
NSLog(#"insertOverwriteClicked");
NSCell* cell;
cell = [insert_overwrite selectedCell];
int tag = [cell tag];
if(tag == 0)
{
if(KDEBUG)
NSLog(#"insert");
[insertAtPosition setEnabled:YES];
insoverappPosition = 0;
}else if(tag==1){
if(KDEBUG)
NSLog(#"overwrite");
[insertAtPosition setEnabled:YES];
insoverappPosition = 1;
}else if (tag==2) {
if(KDEBUG)
NSLog(#"append");
[insertAtPosition setEnabled:NO];
insoverappPosition = 2;
}
}
/*################end editing actions#########################################*/
-(void)newUpdateIsOnline
{
NSLog(#"newUpdateIsOnline");
BOOL retval;
retval = (NSAlertDefaultReturn == NSRunAlertPanel(#"Update Available", #"Update now or later", #"Update", #"Cancel", nil, nil));
if(retval){
if(KDEBUG)
NSLog(#"update now");
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:#"http://www.hardboiled.it/software/rinominatore-upgrade.zip"]];
//to edit
//[[NSNotificationCenter defaultCenter] postNotificationName:#"openSheetNotification" object:self userInfo:nil];
}else {
if(KDEBUG)
NSLog(#"cancel the update");
}
//release the updater. now is useless
[updater release];
}
/*################nstableview delegates#######################################*/
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [tableSource count];
}
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if ([[aTableColumn identifier] isEqualToString: #"original_name"]) {
id obj = [tableSource objectAtRow:rowIndex atIndex:0] ;
return [obj lastPathComponent];
//return theIcon;
}else if([[aTableColumn identifier] isEqualToString: #"new_name"]){
id obj = [tableSource objectAtRow:rowIndex atIndex:1] ;
return [obj lastPathComponent];
}
return nil;
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if(cell_with_icon)
{
if ( [[aTableColumn identifier] isEqualToString:#"original_name"] ){
[((ImageAndTextCell*) cell) setImage:[tableSource objectAtRow:rowIndex atIndex:2]];
}
}
}
/* ###############end nstableview delegates #################################*/
/*############### nstoolbar delegates #######################################*/
- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
{
return [NSArray arrayWithObjects:addFilesIdentifier,
removeFilesIdentifier,cleanAllIdentifier,
NSToolbarFlexibleSpaceItemIdentifier,
NSToolbarSpaceItemIdentifier,
NSToolbarSeparatorItemIdentifier, nil];;
}
- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
{
return [NSArray arrayWithObjects:addFilesIdentifier,
removeFilesIdentifier,NSToolbarFlexibleSpaceItemIdentifier,cleanAllIdentifier, nil];
}
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
NSToolbarItem *toolbarItem = nil;
if ([itemIdentifier isEqualTo:addFilesIdentifier]) {//button addfiles
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Add"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Add"];
[toolbarItem setImage:[NSImage imageNamed:#"add.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(addFiles:)];
}else if ([itemIdentifier isEqualTo:removeFilesIdentifier]) {//button remove files
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Remove"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Remove"];
[toolbarItem setImage:[NSImage imageNamed:#"remove.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(removeFiles:)];
}else if ([itemIdentifier isEqualTo:cleanAllIdentifier]) {//button clean
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Clean All"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Clean the table"];
[toolbarItem setImage:[NSImage imageNamed:#"cleanAll.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(clearTable:)];
}
return [toolbarItem autorelease];
}
/*###############end nstoolbar delegates #####################################*/
/*################drag'n drop delegates #####################################*/
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard {
// Drag and drop support
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:self];
[pboard setData:data forType:NSFilenamesPboardType];
return YES;
}
- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
{
// Add code here to validate the drop
if (KDEBUG)
NSLog(#"validate Drop");
return NSDragOperationEvery;
}
- (BOOL)tableView:(NSTableView*)tv acceptDrop:(id )info row:(int)row dropOperation:(NSTableViewDropOperation)op
{
if (KDEBUG)
NSLog(#"acceptDrop");
NSPasteboard *pboard = [info draggingPasteboard];
if ( [[pboard types] containsObject:NSFilenamesPboardType] ) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
[tableSource add:files];
}
[tabella reloadData];
return YES;
}
/*################end drag'n drop delegates ##################################*/
#end
The delegate is the object, not the method. The ControllerMain object is set as some other object's delegate. When that other object sees the condition that tells it renaming has occurred (whatever that means), it executes something along the lines of [[self delegate] renamed], which calls the ControllerMain method.