NSCollectionView header display - objective-c

I have an NSCollectionView that has 3 sections which contains colors from a color palette. I want each section to have a header view with the name of the section. At first glance, it appears to work. On launch, it looks like this:
However, as soon as I resize the window, the header text ends up drawing outside the headers (and also inside it, somehow!):
In order to have headers in the collection view, I have a header view class named CollectionHeaderView. I register this class as a supplemental view:
[_collection registerClass:[CollectionHeaderView class]
forSupplementaryViewOfKind:#"UICollectionElementKindSectionHeader"
withIdentifier:kSupplementalView];
In the collection view's delegate, I implement the method to return the view for the supplemental element:
- (NSView *)collectionView:(NSCollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
atIndexPath:(NSIndexPath *)indexPath {
NSView* result = [collectionView makeSupplementaryViewOfKind:kind
withIdentifier:kSupplementalView
forIndexPath:indexPath];
if ([kind isEqualToString:#"UICollectionElementKindSectionHeader"]) {
NSTextField* textView = ((CollectionHeaderView*)result).textField;
switch (indexPath.section) {
case 0:
[textView setStringValue:#"Bright Colors"];
break;
case 1:
[textView setStringValue:#"Pastel Colors"];
break;
case 2:
[textView setStringValue:#"Designer Colors"];
break;
}
return textView;
}
return nil;
}
Furthermore, if I resize the window, the header views do not move. The collection elements seem to flow around the headers, leaving things listed under the wrong section. And, as you can see in the second picture above, widening the window ends up leaving a gap between the right edge of the header and the right edge of the collection view.
The CollectionHeaderView class is very simple. It just creates a text field and draws the background and the text field:
#implementation CollectionHeaderView
- (instancetype)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self != nil) {
NSRect textFrame = frameRect;
_textField = [[NSTextField alloc] initWithFrame:textFrame];
_textField.editable = NO;
_textField.bordered = NO;
_textField.font = [NSFont fontWithName:#"Helvetica-Bold" size:14.0];
_textField.backgroundColor = [NSColor colorWithSRGBRed:0.0 green:0.0 blue:0.0 alpha:0.0];
[self addSubview:_textField];
self.identifier = kSupplementalView;
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
NSBezierPath* fillPath = [NSBezierPath bezierPath];
[fillPath appendBezierPathWithRect:dirtyRect];
[[NSColor lightGrayColor] setFill];
[fillPath fill];
[_textField drawRect:dirtyRect];
}
#end
Have I implemented any of the above methods incorrectly? Is there any method I need to implement that I haven't?

The return value of collectionView:viewForSupplementaryElementOfKind:atIndexPath: is the supplementary view result.
- (NSView *)collectionView:(NSCollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSCollectionViewSupplementaryElementKind)kind
atIndexPath:(NSIndexPath *)indexPath {
NSView* result = [collectionView makeSupplementaryViewOfKind:kind
withIdentifier:kSupplementalView
forIndexPath:indexPath];
if ([kind isEqual:NSCollectionElementKindSectionHeader]) {
NSTextField* textView = ((CollectionHeaderView*)result).textField;
switch (indexPath.section) {
case 0:
[textView setStringValue:#"Bright Colors"];
break;
case 1:
[textView setStringValue:#"Pastel Colors"];
break;
case 2:
[textView setStringValue:#"Designer Colors"];
break;
}
return result;
}
return nil;
}

Related

Avoiding UICollectionViewCell re-selection during reuse (from cell's prepareForResue) 'apparently' deselects the original cell as well

In my collection view when (custom) cells are reused they, again, get the highlight I have set in didSelectItemAtIndexPath for the original selection. To prevent this, I am using the custom cell's prepareForReuse method, and post calling [super], I check to see if its the selected cell.
If it is I am change the highlight to default else I restore to the original selection highlight when the cell in question is brought back in scroll view's visible area.
Here's the code...
- (void)prepareForReuse
{
[super prepareForReuse];
if (!self.isSelected) {
[self setBackgroundColor:[UIColor systemBackgroundColor]];
[_tagImageView setTintColor:[UIColor systemBlueColor]];
}
else if (self.isSelected)
{
[self setBackgroundColor:[UIColor systemBlueColor]];
[_tagImageView setTintColor:[UIColor systemBackgroundColor]];
}
}
But I notice that the second if block is never executed even when I bring back the original cell in view. This is where I need help. How do I ensure re-highlighting or the original cell/item?
Note, if I try and save the original cell- even though not highlighted, remains the one selected and the corresponding value is saved.
So, this is just about the re-highlight.
Also, here is the selection code...* didSelectItemAtIndexPath*
- (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (selectedIndexPath!=nil) {
if (indexPath.row==selectedIndexPath.row)
{
[tagCollectionView deselectItemAtIndexPath:indexPath animated:YES];
TagCollectionViewCell *selectedCell = (TagCollectionViewCell *)[tagCollectionView cellForItemAtIndexPath:selectedIndexPath];
selectedCell.backgroundColor = [UIColor clearColor];
selectedCell.tagImageView.tintColor = [UIColor systemBlueColor];
selectedIndexPath=nil;
[newDictionary setValue:[NSNull null] forKey:#"type"];
}
else
{
[tagCollectionView deselectItemAtIndexPath:indexPath animated:YES];
TagCollectionViewCell *previousSelectedCell = (TagCollectionViewCell *)[tagCollectionView cellForItemAtIndexPath:selectedIndexPath];
previousSelectedCell.backgroundColor = [UIColor systemBackgroundColor];
previousSelectedCell.tagImageView.tintColor = [UIColor systemBlueColor];
selectedIndexPath = indexPath;
TagCollectionViewCell *selectedCell = (TagCollectionViewCell *)[tagCollectionView cellForItemAtIndexPath:selectedIndexPath];
selectedCell.backgroundColor = [UIColor systemBlueColor];
selectedCell.tagImageView.tintColor = [UIColor systemBackgroundColor];
dictionaryType = _typesArray[selectedIndexPath.row];
[newDictionary setValue:dictionaryType forKey:#"type"];
}
}
else if (selectedIndexPath==nil)
{
selectedIndexPath = indexPath;
TagCollectionViewCell *selectedCell = (TagCollectionViewCell *)[tagCollectionView cellForItemAtIndexPath:selectedIndexPath];
selectedCell.backgroundColor = [UIColor systemBlueColor];
selectedCell.tagImageView.tintColor = [UIColor systemBackgroundColor];
dictionaryType = _typesArray[selectedIndexPath.row];
[newDictionary setValue:dictionaryType forKey:#"type"];
}
}
Any help? Thanks.
Edit:
This is the part of the code that doesn't get called.
else if (self.isSelected)
{
[self setBackgroundColor:[UIColor systemBlueColor]];
[_tagImageView setTintColor:[UIColor systemBackgroundColor]];
}
I think you are way over-complicating things.
A UICollectionView keeps track of its own "selected" cell(s), and calls setSelected on each cell when it is displayed.
You can put all of your "selected" appearance code inside your cell class:
- (void)setSelected:(BOOL)selected {
// change our color properties based on selected BOOL value
self.tagImageView.tintColor = selected ? UIColor.systemBackgroundColor : UIColor.systemBlueColor;
self.backgroundColor = selected ? UIColor.systemBlueColor : UIColor.systemBackgroundColor;
}
Now you don't need to do anything in didSelectItemAt.
Here's a quick example...
SampleCollectionViewCell.h
#interface SampleCollectionViewCell : UICollectionViewCell
- (void)fillData:(NSInteger)n;
#end
SampleCollectionViewCell.m
#import "SampleCollectionViewCell.h"
#interface SampleCollectionViewCell ()
{
UIImageView *theImageView;
UILabel *theLabel;
}
#end
#implementation SampleCollectionViewCell
- (instancetype)init
{
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
// add an image view and a label
theImageView = [UIImageView new];
theImageView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:theImageView];
theLabel = [UILabel new];
theLabel.textAlignment = NSTextAlignmentCenter;
theLabel.font = [UIFont systemFontOfSize:20.0 weight:UIFontWeightBold];
theLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:theLabel];
[NSLayoutConstraint activateConstraints:#[
[theImageView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0.0],
[theImageView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:0.0],
[theImageView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:0.0],
[theImageView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:0.0],
[theLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:0.0],
[theLabel.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:0.0],
[theLabel.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-4.0],
]];
// image would probably be set by the data source, but
// for this example we'll use the same system image in every cell
UIImage *img = [UIImage systemImageNamed:#"person.fill"];
if (img) {
theImageView.image = img;
}
// let's give the content view rounded corners and a border
self.contentView.layer.cornerRadius = 8.0;
self.contentView.layer.borderWidth = 2.0;
self.contentView.layer.borderColor = UIColor.systemGreenColor.CGColor;
// default (not-selected) colors
theImageView.tintColor = UIColor.cyanColor;
theLabel.textColor = UIColor.blackColor;
self.contentView.backgroundColor = UIColor.systemBackgroundColor;
}
- (void)fillData:(NSInteger)n {
theLabel.text = [NSString stringWithFormat:#"%ld", (long)n];
}
- (void)setSelected:(BOOL)selected {
// change our color properties based on selected BOOL value
theImageView.tintColor = selected ? UIColor.redColor : UIColor.cyanColor;
theLabel.textColor = selected ? UIColor.yellowColor : UIColor.blackColor;
self.contentView.backgroundColor = selected ? UIColor.systemBlueColor : UIColor.systemBackgroundColor;
}
#end
SampleViewController.h
#interface SampleViewController : UIViewController <UICollectionViewDelegate, UICollectionViewDataSource>
#end
SampleViewController.m
#import "SampleViewController.h"
#import "SampleCollectionViewCell.h"
#interface SampleViewController ()
{
UICollectionView *collectionView;
}
#end
#implementation SampleViewController
- (void)viewDidLoad {
[super viewDidLoad];
UICollectionViewFlowLayout *fl = [UICollectionViewFlowLayout new];
fl.scrollDirection = UICollectionViewScrollDirectionVertical;
fl.itemSize = CGSizeMake(60, 60);
fl.minimumLineSpacing = 8;
fl.minimumInteritemSpacing = 8;
collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:fl];
collectionView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:collectionView];
UILayoutGuide *g = [self.view safeAreaLayoutGuide];
[NSLayoutConstraint activateConstraints:#[
// constrain collection view 40-points from all 4 sides
[collectionView.topAnchor constraintEqualToAnchor:g.topAnchor constant:40.0],
[collectionView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:40.0],
[collectionView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-40.0],
[collectionView.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:-40.0],
]];
[collectionView registerClass:SampleCollectionViewCell.class forCellWithReuseIdentifier:#"c"];
collectionView.dataSource = self;
collectionView.delegate = self;
// let's give the collection view a very light gray background
// so we can see its frame
collectionView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 50;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
SampleCollectionViewCell *c = (SampleCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"c" forIndexPath:indexPath];
[c fillData:indexPath.item];
return c;
}
#end
Based on the code you posted, it looks like you want to be able to de-select an already selected cell. If so, add this to the controller:
// this allows us to de-select an already selected cell
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// get array of already selected index paths
NSArray *a = [collectionView indexPathsForSelectedItems];
// if that array contains indexPath, that means
// it is already selected, so
if ([a containsObject:indexPath]) {
// deselect it
[collectionView deselectItemAtIndexPath:indexPath animated:NO];
return NO;
}
// no indexPaths (cells) were selected
return YES;
}
When run, it starts like this:
Tapping cell "1" selects it:
Tapping cell "7" automatically de-selects cell "1" and selects cell "7":
We can scroll up and down and the selected cell will automatically maintain its "selected appearance":
Edit
To explain why your prepareForReuse wasn't doing what you expected...
The collection view does not set the selected property of the cell until it is going to be displayed.
So, in:
- (void)prepareForReuse
{
[super prepareForReuse];
if (!self.isSelected) {
[self setBackgroundColor:[UIColor systemBackgroundColor]];
[_tagImageView setTintColor:[UIColor systemBlueColor]];
}
else if (self.isSelected)
{
[self setBackgroundColor:[UIColor systemBlueColor]];
[_tagImageView setTintColor:[UIColor systemBackgroundColor]];
}
}
self.isSelected will never be true.
If you want to stick with changing the cell UI properties (colors, tint, etc) in didSelectItemAt, you need to update your cell appearance in cellForItemAt:
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TagCollectionViewCell *c = (TagCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"c" forIndexPath:indexPath];
// whatever you are currently doing, such as
//c.tagImageView.image = ...;
if (selectedIndexPath != indexPath) {
[c setBackgroundColor:[UIColor systemBackgroundColor]];
[c.tagImageView setTintColor:[UIColor systemBlueColor]];
}
else
{
[c setBackgroundColor:[UIColor systemBlueColor]];
[c.tagImageView setTintColor:[UIColor systemBackgroundColor]];
}
return c;
}

Change the font, font color and background color of an NSTableView at runtime using NSFontPanel?

I'd like to enable the user to change the font of an view-based NSTableView. I'm using Cocoa bindings and Core Data. In my test code, I do have a changeFont: method that does get called as soon as I press a font-related key combination, like cmd-I or cmd-B, but I've had no luck so far in changing the actual font of the table view:
- (void)changeFont:(id)sender
{
NSFont *oldFont = [self.airportTableView font];
NSFont *newFont = [sender convertFont:oldFont];
NSLog(#"sender: %# oldfont: %#, newFont: %# fontmanager selected: %#, font panel selected: %#",
sender, oldFont, newFont, [sender selectedFont], [sender convertFont:[sender selectedFont]]);
[self.airportTableView setFont:newFont];
}
produces the following output:
sender: <NSFontManager: 0x6080000b4580> oldfont: (null), newFont: (null) fontmanager selected: (null), font panel selected: (null)
Even this trivial code:
font = [NSFont boldSystemFontOfSize:12];
[self.airportTableView setFont:font];
NSFont *oldFont = [self.airportTableView font];
NSLog(#"oldfont: %#",oldFont);
only results in:
oldfont: (null)
Can any kind soul provide some code that allows the user to change the font of an NSTableView?
You have to set the font of the cell. Not the tableview. Use the following delegate method:
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSTextFieldCell *cell = [tableColumn dataCell];
[cell setFont:[NSFont systemFontOfSize:11]];
[cell setTextColor: [NSColor lightGrayColor]];
return cell;
}
Using the power of the internets, I was able to put together the following code fragment which responds to the NSFontPanel actions for changing font type, font color and background color of an NSTableView:
#interface AppDelegate
{
NSFont *_font;
NSColor *_fontColor;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[[NSFontManager sharedFontManager] setTarget:self];
_font = [NSFont systemFontOfSize:0];
_fontColor = [NSColor blackColor];
}
- (void)changeFont:(id)sender
{
_font = [sender convertFont:_font];
[self.airportTableView reloadData];
}
- (void)setColor:(NSColor *)col forAttribute:(NSString *)attr {
if ([attr isEqualToString:#"NSDocumentBackgroundColor"]) {
self.airportTableView.backgroundColor = col;
} else if ([attr isEqualToString:#"NSColor"]) {
_fontColor = col;
[self.airportTableView reloadData];
}
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSTableCellView *cellView = [tableView makeViewWithIdentifier:[tableColumn identifier] owner:self];
NSTextField *textField = [cellView textField];
textField.font = _font;
textField.textColor = _fontColor;
return cellView;
}
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
return _font.boundingRectForFont.size.height + 2.0f;
}
Note the explicit calls to reloadData, otherwise the visible part of the table view won't update. Let me know if there are better solutions.
Also note that -setColor:forAttribute: is undocumented. Apparently, if your class responds to it, -changeAttributes: will not get called.

How to set background color of a UIImageView from a UICollectionView cell

I have not used UICollectionView much so this may not be possible, but never hurts to ask :)
Each cell is set up as a different color.
What I want to do is tap on a cell and push to another UIViewController that will contain a UIImageView of the same color that was selected.
Right now I can change the color of the second UIViewController's View, but not of the UIImageView within it.
Here's some of my code:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
ImageViewController * imageVC = [[ImageViewController alloc] initWithNibName:#"ImageViewController" bundle:nil];
self.flatColor = [self colorForRow:indexPath.row];
[self.navigationController pushViewController:imageVC animated:YES];
imageVC.colorImageView.backgroundColor = _flatColor;
}
- (UIColor *)colorForRow:(NSInteger)row
{
UIColor *color;
switch (row)
{
case 0:
color = [UIColor redColor];
break;
case 2:
color = [UIColor greenColor];
break;
case 4:
color = [UIColor blueColor];
break;
default:
color = [UIColor yellowColor];
break;
}
return color;
}
EDIT:
Fixed the issue.
I had to rearrange some of the code. The new viewController needs to be completely loaded first and then change the backgroundColor of the UIImageView
Try following code.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
ImageViewController * imageVC = [[ImageViewController alloc] initWithNibName:#"ImageViewController" bundle:nil];
self.flatColor = [self colorForRow:indexPath.row];
// This does not work
[imageVC.colorImageView setBackgroundColor:_flatColor];
//imageVC.colorImageView.backgroundColor = _flatColor;
// This works
//imageVC.view.backgroundColor = _flatColor;
[self.navigationController pushViewController:imageVC animated:YES];
}

How to set footer in one section of TableView manually (iOS)?

I would like to implement some code, which changes footer text in one section of the tableView (in viewDidAppear or viewWillAppear method). But how can I do it?
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
doesn't fit my requirements (It changes only once, during load of the tableView, but I need to change the footer's text after text in tableView cell is changed.
-(CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return 120;
}
-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
return #"Things We'll Learn";
} else {
return #"Things Already Covered";
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[tableView reloadData];
}
Implement viewForFooterInSection and add your textField there. Also make that textField a property.
When you have finished editing you tableViewCells, implement the textFieldDidEndEditing method and assign necessary value to the textField of your footerView.
Once your textField is set, use [tableView reloadData] to implement the viewForFooterInSection again and it should work now.
Edit:
If you want to change the title of the Footer section after editing the UITableViewCell,
Set a global variable or use NSUserDefaults to indicate that tableViewCell has been edited.
self.tableView reloadData right after edit.
In the method titleForFooterInSection check for that variable (this would mean that tableView has been edited) and set the title accordingly.
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
if(section == 1)
{
// For Lable
UIView *view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 40)] autorelease];
tableView.sectionHeaderHeight = view.frame.size.height;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, view.frame.size.width - 20, 44)];
label.text = [self tableView:tableView titleForHeaderInSection:section];
label.font = [UIFont boldSystemFontOfSize:16.0];
label.shadowOffset = CGSizeMake(0, 1);
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.adjustsFontSizeToFitWidth = YES;
[label setLineBreakMode:NSLineBreakByTruncatingTail];
[label setNumberOfLines:0];
label.text = #“Your Text Here…..your Text Here”;
[view addSubview:label];
[label release];
return view;
}
return nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if(section == 1)
{
return 60.0;
}
return 0;
}

Handeling single uitextfield within UITableView

I have a single textField in the cell allocation section and after this section I try to provide give the text field various arguments.
Works fine no problem till here, the problem lies how to handle which textField is returning in the delegate method.
My Earlier approach was to simply allocate different text fields for different user input, simple but produces UI glitch when there are many textField(s), hence want avoid it.
for better understanding here is sample code for table delegate method cellAtIndexRow
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellTableIdentifier = #"CellTableIdentifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellTableIdentifier];
if (cell == nil) {
// Create a new cell. CGRectZero allows the cell to determine the appropriate size.
CGRect cellFrame = CGRectMake(0,0,300,65);
cell = [[[UITableViewCell alloc] initWithFrame:cellFrame reuseIdentifier:CellTableIdentifier] autorelease];
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(8,4,284,25)];
textField.delegate = self;
textField.returnKeyType = UIReturnKeyDone;
textField.tag = kTagAddContactTextField;
textField.backgroundColor = [UIColor orangeColor];
[cell.contentView addSubview:textField];
[textField release];
}
UITextField *textField = (UITextField*)[cell.contentView viewWithTag:kTagAddContactTextField];
switch (indexPath.row) {
case 0:
[textField setPlaceholder:#"First Name"];
break;
case 1:
[textField setPlaceholder:#"Last Name"];
break;
case 2:
[textField setPlaceholder:#"Email"];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.keyboardType = UIKeyboardTypeEmailAddress;
break;
}
//cell.textLabel.text = #"Test";
return cell;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
//here is the place where I wann to handle various text fields and store there values.
return YES;
}
Try pulling
textField.tag = kTagAddContactTextField;
out of the table cell creation code, and assign a different tag value for each row in your UITable.
switch (indexPath.row) {
case 0:
textField.tag = kFirstNameField;
[textField setPlaceholder:#"First Name"];
break;
case 1:
textField.tag = kLastNameField;
[textField setPlaceholder:#"Last Name"];
break;
case 2:
textField.tag = kEmail;
[textField setPlaceholder:#"Email"];
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.keyboardType = UIKeyboardTypeEmailAddress;
break;
}
Then you can distinguish which text field you're getting by the tag returned.
you can use "tag" property of UIView (which UITextField inherits).
e.g.
switch (indexPath.row) {
case 0:
[textField setPlaceholder:#"First Name"];
textField.tag=1;//Name
break;
case 1:
[textField setPlaceholder:#"Last Name"];
textField.tag=2;//Surname
break;
case 2:
[textField setPlaceholder:#"Email"];
textField.tag=3;//Email
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.keyboardType = UIKeyboardTypeEmailAddress;
break;
}
and in your callback:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
//here is the place where I wann to handle various text fields and store there values.
switch(textField.tag)
{
case 1://Name
// do stuff;
break;
case 2://Surname
// do stufff;
break;
case 3://Email
//do stuff;
break;
}
return YES;
}
Several ways of varying ickiness:
Use different reuse identifiers and tags for each kind of cell, and switch on the tag. This means cells aren't reused as they might otherwise be, but this is not the end of the world.
Follow UIView.superview until you find a subclass of UITableViewCell (textField.superview.superview should work, but this may change in future versions of iPhone OS), and then use [tableView indexPathForRow:cell].
Use different reuse identifiers (but the same tag), follow the superview chain until you find a UITableViewCell and look at its reuse identifier.
Use a custom UITableViewCell subclass that stores a NSString* or NSInteger key so you know what kind of cell it is (optionally, make the cell the text field's delegate and have the cell notify the view controller of the change).
Switch on the placeholder text (very icky when it comes to i18n)
Whenever the user chose a textfield for editing didSelectRowAtIndexPath should get called. There you can switch the value an int property currentEdited from which value you can detect what the user was changing.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
switch(indexPath.row)
{
case 0:currentEditing = kEditingFirstName;
break;
case 1:....
...
}
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
switch(currentEditing)
{
case kEditingFirstName:
//store first name
break;
....
}
return YES;
}
The tagging thing used in the other answers could lead to problems because of the re-use of the textfield.