Similar Questions has already been asked at SO. My case is little different so I am posting as a new Question.
I have got a scrollView as a main view for controller. It contains two subviews:
Scrollview having a UIView as child.
Tableview containing some numeric Textfields.
I have attached a UITapGestureRecognizer to child scrollview, so that user can dismiss keyboard from any textfield.
UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tableTouched:)];
[topScrollview addGestureRecognizer:tap1];
tap1.delegate = self;
-(void) tableTouched:(UITapGestureRecognizer *)gesture
{
[portTable endEditing:YES];
portTable.scrollEnabled = YES;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
}
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.font = myFont;
cell.textLabel.textColor = [UIColor whiteColor];
switch (indexPath.row) {
case 0:
{
UILabel *tradeLabel = [[UILabel alloc] initWithFrame:CGRectMake(9, 5, 60, 40)];
tradeLabel.text = #"Trade";
tradeLabel.font = myFont;
tradeLabel.textColor = [ColorCodes sharedManager].orangeTextColor;
tradeLabel.backgroundColor = [UIColor clearColor];
[cell.contentView insertSubview:tradeLabel aboveSubview:cell.textLabel];
break;
}
//similar cases
}
return cell;
}
Now if I keep scrolling tableview for sometime, I get crash with the message mentioned in title. Stack trace using instruments is as follows:
I can't understand the reason for negative reference count my controller. I haven't set any scrollview delegate, then why reference count becomes -1?
I have already tried attaching gesture to main scrollview, tableview itself and to the child UIView, but still getting the same crash. Please someone point me in right direction.. Thanks.
EDIT
Another stack trace I just got:
I successfully found the bug. It was because of a custom control in a cell. It was retaining and releasing explicitly being non-ARC (but included in ARC project). Gesture was causing no problem. Removing those lines solved my problem.
Related
I got a table view with two sections, no crazy code, just my delegate methods.
It works pretty fine, like i want it to work. It should just look like on this screenshot:
Now the problem is: Sometimes while scrolling or flicking the scoll view to the bounds, this happens (if you can't see it: There is 1 or 1/2 pixel in gray on the top of the second section header, what is not intended to be so):
So, is this a iOS 7.1 or 7.x bug? I'm not using a custom view for the header. Does anyone know how to fix this?
Feedback really is appreciated.
I had this same problem that I battled for a few weeks, and the way I solved it was to set the tableView's separatorStyle to UITableViewCellSeparatorStyleNone, and add a custom subview that is a line to the cell's contentView.
Then in your cellForRowAtIndexPath method, hide the line subview of the last cell in the section:
- (UIView *)lineView
{
// Your frame will vary.
UIView *colorLineView = [[UIView alloc]initWithFrame:CGRectMake(82, 67.5, 238, 0.5)];
colorLineView.backgroundColor = [UIColor blackColor];
return colorLineView;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
static NSString *identifier = #"cellIdentifier";
UIView *lineView = [self lineView];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
[cell.contentView addSubview:lineView];
}
if (indexPath.section == 0)
{
if (indexPath.row == keys.count -1)
{
lineView.hidden = YES;
}
}
return cell;
}
It may be recycling one of the cell views with the separator from the scroll. This is a long shot, but what if you were to try tweaking the footer view for the section by returning an empty view?
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] init];
}
It's also a good trick for removing empty cells from the table when you have only a couple rows.
I tried it with multiple different things and the cleanest approach i found is this.
I created a custom view for the header, but wanted it to look the same as the original not modified header:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 34)];
[headerView setBackgroundColor:[UIColor groupTableViewBackgroundColor]];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, tableView.frame.size.width, 34)];
[label setFont:[UIFont boldSystemFontOfSize:14]];
if (section == 0) {
NSMutableArray *difficultyArray = [dictionary objectForKey:#"Difficulty"];
NSString *difficulty = [difficultyArray objectAtIndex:0];
[label setText:[NSString stringWithFormat:#"Time Challenge (%#)", difficulty]];
} else {
[label setText:#"Freeplay (5x5 board)"];
}
[headerView addSubview:label];
return headerView;
}
Now we got the sections as they would appear without custom header views, but the bug still exists. I made it simple and clean:
UIView *lineFix = [[UIView alloc] initWithFrame:CGRectMake(0, 77.5, self.tableView.frame.size.width, 0.5)];
lineFix.backgroundColor = [UIColor groupTableViewBackgroundColor];
[self.tableView addSubview:lineFix];
Now we set a view over the buggy seperator with a height of 0.5 pixel, the seperator isn't visible anymore. Between the two section headers now is a 0.5 height view what shouldn't be there, but since i set it the same color as the section background color it isn't noticeable. The view moves, because it is a subview of the tableview, the same direction like the tableview.
If you have questions, just add a comment.
When I tap on a cell, didSelectRowAtIndexPath isn't getting called. When I press and hold on a cell, it'll highlight the cell, but as soon as I take my finger off, the highlight will disappear. And when I tap with two fingers - one finger on one cell, one finger on another cell - THEN didSelectRowAtIndexPath finally gets called and the one cell remains highlighted.
I stripped out all my custom table view cell code and turned it into a completely generic table with a stock UITableViewCell. Still the same problem.
Yes, the data source and delegate are set. No, there aren't any weird delegate methods that are calling deselectRowAtIndexPath.
Here's the code for the table view.
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 75.0f, self.view.frame.size.width, self.view.frame.size.height - 75.0f) style:UITableViewStylePlain];
[self.view addSubview:self.tableView];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
self.tableView.allowsSelection = YES;
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.backgroundColor = _backgroundColor;
And here's the code I stripped the cell down to.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = #"Hello!";
return cell;
I've been through all the didSelectRowAtIndexPath discussions on here and tried all the recommended solutions. And I can't find anyone mentioning the problem I'm seeing here, where didSelectRowAtIndexPath DOES get called, it's just very intermittent or you have to use two fingers at once.
Make sure the method is
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
In the view controller in .h
#interface YourViewController : UIViewController<UITableViewDelegate>
I'm trying to to something like apple's alarm clock, when tap the edit button, a custom view cover the custom UITableViewCell.
The code above:
// CGRect frame = [tableView rectForRowAtIndexPath:indexPath];
// CGPoint yOffset = self.tableViewBlock.contentOffset;
// CGRect newFrame = CGRectMake(frame.origin.x, (frame.origin.y - yOffset.y + 45), frame.size.width, frame.size.height);
CallBlock_Date_EditMode *viewController = [[CallBlock_Date_EditMode alloc] initWithNibName:#"CallBlock_Date_EditMode" bundle:nil];
// self.view.frame = newFrame;
// [self.view addSubview:viewController.view];
// [self addChildViewController:viewController];
UITableViewCell *cell = (UITableViewCell*)[self.tableViewBlock cellForRowAtIndexPath:indexPath];
[cell.contentView addSubview:viewController.view];
Cover the specific cell when I put in under:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Just to make sure the size is ok (although when I tap a button in that xib the app crash without even a single error).
But I want to do like apple's alarm clock (actually, mimic it), tap my edit button and my custom UITableViewCell will get cover with this xib as a view.
Maybe there is a better approach to do it?
EDIT:
My updated code is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CallBlock_TableCell *cell = (CallBlock_TableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[CallBlock_TableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(CallBlock_TableCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
cell.accessoryType = self.isEditing ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
CallBlock_ByDate *callBlock = (CallBlock_ByDate*)[fetchedObjects objectAtIndex:indexPath.row];
cell.labelTime.text = callBlock.startDate;
cell.labelRepeat.text = callBlock.repeat;
cell.labelTextLabel.text = callBlock.label;
cell.switchCallBlock.on = YES;
cell.switchCallBlock.tag = (NSInteger)indexPath.row +1;
[cell.switchCallBlock addTarget:self action:#selector(handleSwitch:) forControlEvents:UIControlEventValueChanged];
cell.switchCallBlock.hidden = self.isEditing ? YES : NO;
if (self.isEditing)
{
cell.switchCallBlock.hidden = YES;
UIButton *btnArrow = [[UIButton alloc] init];
btnArrow.frame = CGRectMake(282.0, 31.0, 18.0, 21.0);
[btnArrow setBackgroundImage:[UIImage imageNamed:#"arrow_FWR_off"] forState:UIControlStateNormal];
[btnArrow setBackgroundImage:[UIImage imageNamed:#"arrow_FWR_on"] forState:UIControlStateHighlighted];
btnArrow = [UIButton buttonWithType:UIButtonTypeCustom];
[btnArrow addTarget:self action:#selector(handleTapToEdit:) forControlEvents:UIControlEventTouchUpInside];
btnArrow.tag = indexPath.row + 1;
[cell.contentView addSubview:btnArrow];
[cell.contentView bringSubviewToFront:btnArrow];
}
}
But I cannot get the btnArrow appear on the UTableView.
The reason you are getting a crash is because nothing is retaining your CallBlock_Date_EditMode view controller. You add its view to your cell as a subview, but nothing maintains a reference to the view controller, so it is deallocated and then, when pressing a button that is supposed to pass a message to your view controller, it is sent to a deallocated object and you get a crash.
There are two possible solutions to this. First, you could store that view controller in one of your properties to maintain a reference to it so that it does not deallocated. This is, for the most part, probably not what you want.
Instead, what I would suggest doing is do not make your CallBlock_Date_EditMode a UIViewController, but instead make it a UIView. You may be wondering "But how can I use a xib without a UIViewController?". I would do something like the following:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
UIView *view = [[[NSBundle mainBundle] loadNibNamed:#"CallBlock_Date_EditMode" owner:self options:nil] objectAtIndex:0];
self.myEditButton = (UIButton *)[view viewWithTag:2];
[self addSubview:view];
}
return self;
}
This would be code inside your custom UIView that would load in a xib file and add it as a subview. In order to get access to your subviews, you have to use tags inside interface builder, so you do lose the convenience of drawing/connecting IBOutlets... But in the end, it is much better than allocating/storing a bunch of unnecessary UIViewControllers.
If I understand you right and you want to mimic the functionality of the alarm clock that comes pre-installed from Apple, your solution is much simpler than creating a custom view. It looks like all they do is set the On-Off switches to hidden and add a disclosure indicator to the cell. This is what I would do...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
bool hide = (tableView.editingStyle == UITableViewCellEditingStyleDelete); // set to true or false depending on if the table is in editing mode
for (UIView *sv in [cell subviews] ) {
if([sv isKindOfClass:[UISwitch class]]) { // find the on-off switch
[sv setHidden:hide]; // hide the switch depending on the t/f value of hide
break;
}
}
if(hide) { // adds the arrow like in apple's alarm clock table if the cell is in edit mode
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
}
I don't see why this would matter, but I'm having some trouble getting it to work.
Disclaimer: This is my first iOS app (or ANY Apple development for that matter, and the app needs to be done yesterday, so excuse any rushed-looking code please).
I'm using the SWRevealViewController library to create a Facebook-esque "side view" when a button on the home view navigation controller is clicked. It works great, love it. This view holds a UITableView with only two static cells, and I just received a request to add a cell to the very bottom of the view.
It didn't seem obvious to try to get that third cell "in" the UITableView, so in my xib I just created a UITableViewCell outside of the UITableView, and put it at the bottom of the view. It then hooked it up to my controller using the standard IBOutlet workflow.
Back in my viewDidLoad I skinned the rogue cell to look like the rest of the tablecells, added some wording, added a handler to make it open up my company's website when clicked, and all of that works fine. I did all of this stuff for the "regular" table cells in my tableView:cellForRowAtIndexPath function.
BUT for some reason when I click on the cell, it's not being highlighted like my other regular cells when I click on it! Why!
CODE:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
} else {
[[cell.contentView viewWithTag:1] removeFromSuperview];
}
UILabel *lblView = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 3.0, 187.0, cell.frame.size.height)];
[lblView setFont:[UIFont fontWithName:#"FuturaStd-Bold" size:12]];
lblView.textColor = [UIColor colorWithRed:(255/255.f) green:(241/255.f) blue:(204/255.f) alpha:1.0];
lblView.tag = 1;
if (indexPath.row == 0){
[lblView setText:#"SCHEDULE"];
} else if (indexPath.row == 1){
[lblView setText:#"SPEAKERS"];
}
lblView.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:lblView];
UIImageView *av = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 277, 58)];
av.backgroundColor = [UIColor clearColor];
av.opaque = NO;
av.image = [UIImage imageNamed:#"blackBar.png"];
cell.backgroundView = av;
UIView *bgColorView = [[UIView alloc] init];
[bgColorView setBackgroundColor:[UIColor colorWithRed:(240/255.f) green:(145/255.f) blue:(62/255.f) alpha:1.0]];
[cell setSelectedBackgroundView:bgColorView];
return cell;
}
The above code works fine for my "regular cells". That last bit before I return the cell is what sets the background highlight a weird orange color when it's "being clicked".
The code below is the SAME THING but in my viewDidLoad, and it's not setting the background highlight color when being clicked.
- (void)viewDidLoad
{
[super viewDidLoad];
//... stuff
UILabel *lblView = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 3.0, 187.0, _roguecell.frame.size.height)];
[lblView setFont:[UIFont fontWithName:#"FuturaStd-Bold" size:12]];
lblView.textColor = [UIColor colorWithRed:(255/255.f) green:(241/255.f) blue:(204/255.f) alpha:1.0];
[lblView setText:#"IT'S A SECRET LOL"];
lblView.backgroundColor=[UIColor clearColor];
[_roguecell.contentView addSubview:lblView];
UIImageView *av = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 277, 58)];
av.backgroundColor = [UIColor clearColor];
av.opaque = NO;
av.image = [UIImage imageNamed:#"blackBar.png"];
_roguecell.backgroundView = av;
UIView *bgColorView = [[UIView alloc] init];
[bgColorView setBackgroundColor:[UIColor colorWithRed:(240/255.f) green:(145/255.f) blue:(62/255.f) alpha:1.0]];
[_roguecell setSelectedBackgroundView:bgColorView];
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[_roguecell addGestureRecognizer:singleFingerTap];
}
Maybe it has something to do with my xib file I have the UITableView extending down the entire view, and the rogue UITableViewCell "on top" of it (but not in it obviously). I tried messing around with the locations of the table and the cell, but that didn't do anything.
Thanks for reading.
I ended up removing my rogue UITableViewCell, and upping the total number of cells in my UITableView from 2 to 4. The 3rd cell I removed my custom background from, didn't add any text to, disabled user interaction from, and set the height using the - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath method to fill up the rest of the table leaving only enough room at the bottom for my "footer" cell.
So I'm trying to figure out ideas for my registration page in xCode -- something like this: http://weswilliams.me/wp-content/uploads/2011/06/IMG_2525-e1307910945329.png
At any rate, I can't figure out what objects they are using to achieve this display. It looks like a TextField on top of a Button? If it is, I can never get the Text Field to sit on top, it always falls behind the button, thus making it invisible.
Any tips or suggestions?
This is not a textfield on the button. Actually it is text box inside a table view. You have to do the following :
Take a table view on the nib.
Create the outlet and set the delegate and datasource.
Then add the following code to your .m file.
try this one
before this set the number of rows the table view has.
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:#"Cell"];
if( cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"] autorelease];
cell.textLabel.text = [[NSArray arrayWithObjects:#"First",#"Second",#"Third",#"Forth",#"Fifth",#"Sixth",#"Seventh",#"Eighth",#"Nineth",#"Tenth",nil]
objectAtIndex:indexPath.row];
if (indexPath.row % 2) {
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 200, 21)];
textField.placeholder = #"Enter Text";
textField.text = [inputTexts objectAtIndex:indexPath.row/2];
textField.tag = indexPath.row/2;
textField.delegate = self;
cell.accessoryView = textField;
[textField release];
} else
cell.accessoryView = nil;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Or you can see this link See this answer on SO
Thats a basic grouped UITableView. Read up on Apple docs. There are a ton of tutorials on that too.