I swipe on a table view cell to reveal the delete-confirmation button. But once I lift my finger, showingDeleteConfirmation gives NO even if the button is still there. (It does give YES when the button is showing up, I mean, before I lift my finger.) Am I missing something, or it's a real bug in iOS?
Following is my test code. (Copy&paste it into ViewController.m of a single-view project and run it in the simulator, and shift+command+M to trigger the NSLog.)
#import "ViewController.h"
#interface ViewController () <UITableViewDataSource, UITableViewDelegate>
#end
#implementation ViewController {
UITableViewCell *_myCell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 100, 320, 200)];
myTableView.dataSource = self;
myTableView.delegate = self;
[self.view addSubview:myTableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
_myCell = [[UITableViewCell alloc] init];
_myCell.contentView.backgroundColor = [UIColor greenColor];
return _myCell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
NSLog(#"_myCell.showingDeleteConfirmation = %#", _myCell.showingDeleteConfirmation ? #"YES" : #"NO");
}
#end
According to documentation:
Returns whether the cell is currently showing the delete-confirmation button. (read-only)
...
When users tap the deletion control (the red circle to the left of the cell), the cell displays a "Delete" button on the right side of the cell
So first you need to make grid editable
[myTableView setEditing:YES];
then user taps circle to delete (they not able to swipe left in this mode), and voilĂ :
_myCell.showingDeleteConfirmation = YES
While you can expect to use it as you described in your question, they don't promise it.
Related
Case is following: I want to create UITableView from separate class.
Currently I have following:
// Menu.h
#interface Menu : UITableViewController <UITableViewDelegate, UIAlertViewDelegate> {
UITableView *tableView;
}
#property (nonatomic,retain) NSMutableArray *navigationItems;
- (void)initMenu:(UIView *)view;
#end;
Then
// Menu.m
#import <Foundation/Foundation.h>
#import "Menu.h"
#implementation Menu
- (void) initMenu:(UIView *)view {
self.navigationItems = [[NSMutableArray alloc] initWithObjects:#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine",#"Ten",nil];
UIView *mainmenu=[[UIView alloc]initWithFrame:CGRectMake(0, 50, 320, 420)];
[mainmenu setBackgroundColor:[UIColor yellowColor]];
[view addSubview:mainmenu];
UITableView *menutableView = [[UITableView alloc] initWithFrame:view.bounds style:UITableViewStylePlain];
menutableView.backgroundColor = [UIColor whiteColor];
menutableView.delegate = self;
menutableView.dataSource = self;
[mainmenu addSubview:menutableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableViewi cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableViewi dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [self.navigationItems objectAtIndex:indexPath.row];
return cell;
}
#end
And in different .m file I call method:
...
#import "Menu.h"
...
- (void)viewDidLoad
{
[super viewDidLoad];
...
Menu *menu = [[Menu alloc] init];
[menu initMenu: self.view];
}
Running this will crash application and Xcode won't give any detailed report. However, if I combine Menu.m to the .m file where I'm calling "initMenu" it won't crash.
Also if I comment out menutableView.dataSource = self; it will run with our crash (no rows in table of course...).
Passing a view into an init method and then creating/adding subviews in said init method is an odd design pattern. Change your Menu class to a viewcontroller, then move your UIView and UITableView declarations to the viewDidLoad method. The crash is likely happening because the tableview is trying to display data before its parent view has finished loading.
My app has a home screen where I show user posts loaded from the server. My problem is that I use UIView for each post, but it takes up a lot of space (also the user keeps on scrolling making it more memory consuming). Ex:
UIView* box=[[UIView alloc]initWithFrame:CGRectMake(0, postY, maxWidth, 500)];
[box setTag:(NSInteger)[post_id[i] integerValue]];
[box setBackgroundColor:[UIColor whiteColor]];
//Profile pic+++
UIImageView* profile_img=[[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
profile_img.layer.cornerRadius=profile_img.frame.size.width/2; //Make it round
profile_img.layer.masksToBounds=YES; //Make it round
profile_img.layer.borderWidth=0.5;
profile_img.layer.borderColor=[rgb(214, 222, 231) CGColor];
[box addSubview:profile_img];
And so on...
Does anyone know a better way of doing this? I tough of UITableCellView but it seems to be odd doing this task this way
I recommend you use a UITableViewController and then subclass UITableViewCell to create a custom cell for you to display the data. A UITableViewController instance contains a UITableView and you display the data by setting it in your custom UITableViewCell subclass. So basically, a UITableView contains various UITableViewCell and use the delegate methods to respond to events and actions on your table.
// YourCustomTableViewCell.h
#import <UIKit/UIKit.h>
#interface YourCustomTableViewCell : UITableViewCell
// Setup the properties for the cell, e.g
#property (strong, nonatomic) IBOutlet UIImageView *profileImageView; // Connect to outlet in storyboard file
#end
// YourCustomTableViewCell.m
#import "YourCustomTableViewCell.h"
#implementation YourCustomTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.profileImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
}
return self;
}
- (void)awakeFromNib
{
// Use this method to setup frames and sizes of your properties
self.profileImageView.layer.cornerRadius = profileImageView.frame.size.width/2; //Make it round
self.profileImageView.layer.masksToBounds = YES; //Make it round
self.profileImageView.layer.borderWidth=0.5;
self.profileImageView.layer.borderColor = [rgb(214, 222, 231) CGColor];
}
#end
// YourTableViewController.h
#import <UIKit/UIKit.h>
#interface YourTableViewController : UITableViewController
#end
// YourTableViewController.m
#import "YourTableViewController.h"
#import "YourCustomTableViewCell.h"
#interface YourTableViewController ()
#end
#implementation YourTableViewController
- (void)viewDidLoad
{
// Setup your data source for the table
self.tableView.dataSource = self;
// Setup other stuff after loading the view
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1; // Return the number of sections you want in the table view
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows for each section, in your case this would be something like this
return self.posts.count; // If your data is stored in an array
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"YourCustomCell";
YourCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
if (!cell){
cell = [[YourCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
// Configure the cell...
// Here you add the code to display the data in the cell e.g.
[cell.profileImageView setImage:yourImageToDisplay];
return cell;
}
#end
As the comment said, you'd better choose UITableView as the posts' container and inherit from UITableViewCell as your box view.
Detailedly speaking much more, suppose the class inherited from UITableViewCell named MyTableViewCell, and you treat its contentView as your UIView *box. After that, you could tell the UITableView to use your MyTableViewCell as the Cell by sending him registerClass:forCellReuseIdentifier:.
Then, you can get MyTableViewCell instance by sending UITableView the
dequeueReusableCellWithIdentifier:forIndexPath: message. After being bound data (telling him display what posts), this instance can be returned to UITableView, which will arrange everything for you. Besides, these usually should be done in the UITableView's dataSource method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.
I have a view controller loaded from xib with a table view and a text field as titleView in the navigation bar. Simple.
#interface ViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, weak) IBOutlet UITableView *tableView;
#end
#implementation ViewController
#synthesize tableView;
- (void)viewDidLoad {
[super viewDidLoad];
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
[tableView reloadData];
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
self.navigationItem.titleView = tf;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 42;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#""];
cell.textLabel.text = #"test cell";
return cell;
}
#end
I tap the text field, let the keyboard show and start to drag the table view to interact with keyboard.
The problem is when I release touch while interacting and let the keyboard fully show: it goes up without animation. If I release to hide it works.
Furthermore this is only in iOS 8. It works in iOS 7.
Am I missing anything?
I implemented a UITableview with all methods.
When the UITableviewController is the initial View Controller, it works fine, I can swipe to delete.
But when the UITableViewController is part of my project and reached by pushing the view, I can't swipe to delete. It seems the application doesn't always detect the swipe or something like this, because sometimes, the delete button appears.
This is a very simple project, there is no big operation.
(I'm using Google Analytics et Google Adsense library, but not in this view controller.)
---
EDIT : Some code and a question, the code of the previous screen may influence the performance of the uitableviewcontroller ?
My storyboard is like this :
[Navigation controller] --> [Root View Controller] --> [Table View Controller]
Code :
VerreTableViewController.h
#interface VerreTableViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *table_view_verres;
#end
VerreTableViewController.m
#interface VerreTableViewController ()
#end
NSArray *objects_verres;
#implementation VerreTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
objects_verres = [Verre allWithOrder:#{#"date_prise" : #"DESC"}];
_table_view_verres.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return objects_verres.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [_table_view_verres dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
UILabel *lbl_nom = (UILabel *)[cell viewWithTag:10];
UILabel *lbl_date = (UILabel *)[cell viewWithTag:11];
NSManagedObject *matches = objects_verres[indexPath.row];
lbl_nom.text = [matches valueForKey:#"nom_alcool"];
lbl_date.text = [[matches valueForKey:#"date_prise"] formattedDateWithFormat:#"HH:mm - dd/MM/yyyy"];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//code to delete
}
}
I would point you to this post: Swipe to Delete not working
Make sure you implement all the necessary methods, and you don't have a unusual view hierarchy/code running on the app delegate.
I vaguely remember an issue with storyboards and tableview controllers that are embedded inside a view controller. Perhaps someone else can shed more light on this.
I am trying to create a simple UItableview app in a project utilizing ARC. The table renders just fine but if I try to scroll or tap a cell the app crashes.
Looking at the NSZombies (is that the proper way to say that?) I get the message "-[PlacesViewController respondsToSelector:]: message sent to deallocated instance 0x7c29240"
I believe this has something to do with ARC as I have successfully implemented UItableviews in the past but this is my first project using ARC. I know I must be missing something very simple.
PlacesTableViewController.h
#interface PlacesViewController : UIViewController
<UITableViewDelegate,UITableViewDataSource>
#property (nonatomic, strong) UITableView *myTableView;
#end
PlacesTableViewController.m
#import "PlacesTableViewController.h"
#implementation PlacesViewController
#synthesize myTableView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
self.myTableView.dataSource = self;
self.myTableView.delegate = self;
[self.view addSubview:self.myTableView];
}
#pragma mark - UIViewTable DataSource methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 100;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *result = nil;
static NSString *CellIdentifier = #"MyTableViewCellId";
result = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(result == nil)
{
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
result.textLabel.text = [NSString stringWithFormat:#"Cell %ld",(long)indexPath.row];
return result;
}
#end
There is nothing obviously wrong with the code you posted. The problem is with the code that creates and holds onto PlacesViewController. You are probably creating it but not storing it anywhere permanent. Your PlacesViewController needs to be saved into an ivar or put in a view container that will manage it for you (UINavigationController, UITabController or similar)