On UITableView editing mode, UITableView:didSelectRowAtIndexPath: doesn't respond - ios

I'm developing an iOS application and I'm trying to implement my own custom UITableView edit mode with a custom UITableViewCell.
I have an edit button and this is the IBAction for it:
- (IBAction)editFavList:(id)sender
{
if ([_favList isEditing])
{
[_favList setEditing:NO animated:YES];
[_editButton setTitle:#"Edit" forState:UIControlStateNormal];
}
else
{
[_favList setEditing:YES animated:YES];
[_editButton setTitle:#"Done" forState:UIControlStateNormal];
}
}
I have connected UITableView* _favList delegate with UIViewController and this UITableViewDelegate method works fine until I tap over edit button:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.editing)
{
NSNumber* obj = [favsSelected objectAtIndex:indexPath.row];
BOOL selected;
if (obj == nil)
selected = NO;
else
selected = [obj boolValue];
FavouriteCell* cell =
(FavouriteCell*)[tableView cellForRowAtIndexPath:indexPath];
cell.checked = !selected;
// Actualizo el estado en el vector de los favoritos seleccionados
[favsSelected insertObject:[NSNumber numberWithBool:!selected] atIndex:indexPath.row];
}
}
After tapping edit button, this method doesn't fire (I'm sure about that because I add a breakpoint on the method).
This is custom cell implementation:
#import "FavouriteCell.h"
const NSInteger EDITING_HORIZONTAL_OFFSET = 35;
#implementation FavouriteCell
#synthesize selectIcon = _selectIcon;
#synthesize favName = _favName;
#synthesize checked = _checked;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.checked = NO;
}
return self;
}
- (void)setChecked:(BOOL)checked
{
if (checked == _checked)
return;
_selectIcon.highlighted = checked;
_checked = checked;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
+ (NSString *)reuseIdentifier
{
return #"favouriteCell";
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
//self.editing = editing;
[super setNeedsLayout];
}
#pragma mark - Private methods
- (void)layoutSubviews
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[super layoutSubviews];
if (((UITableView *)self.superview).isEditing)
{
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = EDITING_HORIZONTAL_OFFSET;
self.contentView.frame = contentFrame;
self.accessoryType = UITableViewCellAccessoryNone;
}
else
{
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = 0;
self.contentView.frame = contentFrame;
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
[UIView commitAnimations];
}
#end
But if I tap over edit button again (and then, I leave edit mode), if I tap over a row, didSelectRowAtIndexPath it's triggered again.
Why am I doing wrong? Probably this issue is related to if UITableView is in editing mode or not.

Check nib file .You should change the tableView editing property into Single Selection during editing.

You should set: allowsSelectionDuringEditing property of UITableView to YES
In your case:
_favList.allowSelectionDuringEditing = YES;

Related

How to locate the layout across view hierarchy?

I have a menuView in a list view controller. The menuView added on the UITableViewCell when a more button in the cell being taped.
I achieved the effect with singleton.
#implementation ProductsOperationMenu
static ProductsOperationMenu *_instance;
+ (instancetype)sharedInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] initWithFrame:CGRectZero];
});
return _instance;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
ZBMyProductsCell.m
#implementation ZBMyProductsCell
- (void)awakeFromNib
{
[super awakeFromNib];
_operationMenu = [[ProductsOperationMenu alloc] initWithFrame: CGRectZero];
}
- (IBAction)operationButtonClick:(UIButton *)sender {
if ([self.contentView.subviews containsObject:_operationMenu]) {
_operationMenu.hidden = ![_operationMenu isHidden];
} else{
[self.contentView addSubview:_operationMenu];
_operationMenu.hidden = NO;
}
[_operationMenu mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(205);
make.height.mas_equalTo(60);
make.bottom.mas_equalTo(self.operationButton).offset(0);
make.right.mas_equalTo(self.operationButton.mas_left).offset(-10);
}];
}
Without Singleton, it became this:
So the question come.
I want to put the menuView on the controller's view, because it is unique or hidden, which used to belong to the cell.
How to convert layout of the more button selected to the controller's view?
How to use the methods to calculate?
- convertPoint:toView:
- convertPoint:fromView:
......
I did it in a simple way. Here is the code:
- (void)clickOperationButtonOfProductsCell:(ZBMyProductsCell *)myProductsCell{
NSUInteger * operationIndex = [self.myProductsTableView.visibleCells indexOfObject:myProductsCell];
CGFloat originY = operationIndex.row * 110 + 50 + 40;
CGRect originFrame = CGRectMake(KScreenWidth - 55, originY, 0, 60);
CGRect finalFrame = CGRectMake(KScreenWidth - 260, originY, 205, 60);
self.operationMenuView.frame = originFrame;
[UIView animateWithDuration: 0.5 delay: 0 options: UIViewAnimationOptionCurveEaseIn animations:^{
self.operationMenuView.frame = finalFrame;
} completion:^(BOOL finished) { }];
}
How to achieve it more adaptively?
Maybe you can try it like this:
// here is your cell where the more button belongs to
#interface ZBMyProductsCell: UITableViewCell
#property (nonatomic, copy) void(^moreAction)(ZBMyProductsCell *cell);
#end
#implementation ZBMyProductsCell
- (void)_moreButtonClicked:(UIButton *)sender {
!self.moreAction ?: self.moreAction(self);
}
#end
// here is your view controller where your table view belongs to
// this is a `UITableViewDataSource` delegate method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ZBMyProductsCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ZBMyProductsCell" forIndexPath:indexPath];
// Configure the cell...
cell.moreAction = ^(ZBMyProductsCell *cell) {
CGRect rect = [tableView rectForRowAtIndexPath:indexPath];
// write your own code to show/hide the menu
};
return cell;
}
Create a variable in each cell model called cellIndexpath and in cellForRow init it
cell.cellIndexpath = indexpath
have a look of UIPopoverPresnetationController and see if it can do the job. It should be available on iPhone. Putting menu view on the controller’viewwill cause issue when you scroll the table view.
use
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect:self.detaiLabel.frame inView:self];

MLPAutoCompleteTextField suggestion table interaction issue

Currently I'm using this third-party library in my project https://github.com/EddyBorja/MLPAutoCompleteTextField. This library is used to show the suggestion list based on user input.
I did setup the text field like this
self.searchTextField = [[MLPAutoCompleteTextField alloc] initWithFrame:CGRectMake(0, 0, 250, 30)];
[self.searchTextField setBorderStyle:UITextBorderStyleRoundedRect];
self.searchTextField.backgroundColor = [UIColor whiteColor];
self.searchTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
self.searchTextField.textColor = [UIColor blackColor];
self.searchTextField.returnKeyType = UIReturnKeyDone;
self.searchTextField.placeholder = #"Enter name to search";
self.searchTextField.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchTextField.delegate = self;
self.searchTextField.autoCompleteDelegate = self;
self.searchTextField.autoCompleteDataSource = self;
Implement the Datasource protocol as below
- (NSArray *)autoCompleteTextField:(MLPAutoCompleteTextField *)textField possibleCompletionsForString:(NSString *)string {
return #[#"AAA", #"BBB", #"CCC", #"DDD"];
When I input something to the text field, the drop down list was shown but when I tap on a cell in the drop down list, the list dissappeared without completing any words in the text field.
Anyone experienced this problem please explain to me where I was wrong. Thanks in advance.
I had the same issue awhile back. I happened to be using MLPAutocomleteTextField inside a UITableView, so all the touch events were likely intercepted by the tableview.
I worked around this issue by setting the autoCompleteTableAppearsAsKeyboardAccessory of my MLPAutocomleteTextField instance to TRUE to enable enable autocomplete as a keyboard accessory. This allowed me to select my autocomplete options. Hopefully this solves your issue as well. :)
I solved it by subclassing my UITableViewCell, a little tricky but it's working for me:
#import "AutoCompleteTableViewCell.h"
#interface AutoCompleteTableViewCell()
#property (nonatomic, assign) BOOL selectedCell;
#end
#implementation AutoCompleteTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
self.selectedCell = NO;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* hitView = [super hitTest:point withEvent:event];
if (hitView != nil)
{
[self.superview bringSubviewToFront:self];
}
return hitView;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
CGRect rect = self.bounds;
BOOL isInside = CGRectContainsPoint(rect, point);
if(!isInside)
{
for (UIView *view in self.subviews)
{
isInside = CGRectContainsPoint(view.frame, point);
if(isInside)
break;
}
}
if (!self.selectedCell) {
self.selectedCell = YES;
id view = [self superview];
while (view && [view isKindOfClass:[UITableView class]] == NO) {
view = [view superview];
}
UITableView *tableView = (UITableView *)view;
NSIndexPath *indexPath = [tableView indexPathForCell:self];
[tableView.delegate tableView:tableView didSelectRowAtIndexPath:indexPath];
}
return isInside;
}
Then delegate method is called:
- (void)autoCompleteTextField:(MLPAutoCompleteTextField *)textField
didSelectAutoCompleteString:(NSString *)selectedString
withAutoCompleteObject:(id<MLPAutoCompletionObject>)selectedObject
forRowAtIndexPath:(NSIndexPath *)indexPath;

cellForRowAtIndexPath not called when compiled with xcode 6.1

In my app I have a popup with a [table view][1] .
When compiled with Xcode 5.1 everything works fine, but the same code compiled with Xcode 6.1 failed to call the [cellForRowAtIndexPath][3] [delegate][4] method.
The other delegate meths are called.
One intersting point is self.tableView.rowHeight; returns -1
I have tried explicitly setting the delegate and data source to self but that makes not difference
The class is called by the following code;
`-(IBAction)selectLanguage:(id)sender
{
ATLMLanguagePopoverTableViewController *pvc = [[ATLMLanguagePopoverTableViewController alloc] initWithNibName:nil bundle:nil];
pvc.target = self;
pvc.action = #selector(popoverDidSelectItem:);
pvc.items = [[[ATLMLibraryManager getManager]libraryDefaults]getAvailableLanguageNames];
_myPopoverController.contentViewController = pvc;
[_myPopoverController setPopoverContentSize:[pvc popoverContentSize]];
[_myPopoverController presentPopoverFromBarButtonItem:(UIBarButtonItem *)sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
`
Hear is the definition of the class
/
/ LanguagePopoverTableViewController.m
// SalesAid
//
// Created by phuang on 1/16/13.
// Copyright (c) 2013 Align Technology. All rights reserved.
//
#import "ATLMLanguagePopoverTableViewController.h"
#import "ATLMLocalizationManager.h"
#import "ATLMUtils.h"
#interface ATLMLanguagePopoverTableViewController ()
#end
#implementation ATLMLanguagePopoverTableViewController
#synthesize items, selectedItem, target, action;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
selectedItem = -1;
target = nil;
action = NULL;
}
return self;
}
-(void) resetLocalization {
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)setItems:(NSArray *)newItems {
items = [newItems copy];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
selectedItem=0;
NSString *curLang = (NSString *) [[ATLMLocalizationManager getManager]getCurrentLanguage] ;
for(int i = 0; i < items.count ; i++ ){
if([curLang isEqualToString:(NSString *)[items objectAtIndex:i]]){
selectedItem = i;
break;
}
}
NSIndexPath *i = [NSIndexPath indexPathForRow:selectedItem inSection:0];
[self.tableView selectRowAtIndexPath:i animated:NO scrollPosition:UITableViewScrollPositionNone];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (CGSize)popoverContentSize {
NSInteger rowHeight = self.tableView.rowHeight;
UITableView *tv = self.tableView;
rowHeight = 50;
return CGSizeMake(100, [items count] * rowHeight);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.font = [UIFont systemFontOfSize:14];
UIView *myBackView = [[UIView alloc] initWithFrame:cell.frame];
myBackView.backgroundColor = [ATLMUtils getAlignBlue];
cell.selectedBackgroundView = myBackView;
[cell setSelectedBackgroundView: myBackView ];
NSString *textLabelKey = [items objectAtIndex:[indexPath indexAtPosition:1]];
cell.textLabel.text = ATLMLocalizedString(textLabelKey, nil);
cell.textLabel.textAlignment = NSTextAlignmentCenter;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedItem = indexPath.row;
if (target != nil && action != NULL) {
[target performSelector:action withObject:self];
}
}
#end
`
OK to answer my own question;
Basically the code adds the model to the view controller after the init method is called. However is seem the thread model has changed a bit and the view is created before the model is added so the row count in the model is zero
The solution is to pass the model as part of the init method.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil items:(NSArray *)itemArray
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
items = [itemArray copy];
selectedItem = -1;
target = nil;
action = nil;
}
return self;
}

TableView UILabel alignment changes when scrolling

I have a TableView with 3 UILabel: title, author name and category and a UIImage. All cells should look similar to this layout:
Correct cell layout:
When the app starts for some reason some cells have the title UILabel alignment not as it should be:
After scrolling the TableView a few times, these cells end up with the proper alignment. I'm not quite sure what is causing this.
I have created a Custom TableView Cell class (followed this tutorial)
CustomTableViewCell.h
#interface CustomTableViewCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UIImageView *image;
#property (nonatomic, weak) IBOutlet UILabel *titleLabel;
#property (nonatomic, weak) IBOutlet UILabel *authorLabel;
#property (nonatomic, weak) IBOutlet UILabel *categoryLabel;
#end
CustomTableViewCell.m
#implementation CustomTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)awakeFromNib
{
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self.contentView layoutIfNeeded];
self.titleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.titleLabel.frame);
[self.titleLabel sizeToFit];
[self.titleLabel setNumberOfLines:0];
}
#end
This is how this class is implemented in the ViewController:
#interface CurrentIssueViewController () {
CurrentIssueModel *_currentIssueModel;
Article *_selectedArticle;
}
#end
#implementation CurrentIssueViewController
static NSString *cellIdentifier = #"BasicCell";
UIActivityIndicatorView *activityView;
//#synthesize _feedItems;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didChangePreferredContentSize:)name:UIContentSizeCategoryDidChangeNotification object:nil];
// Create array object and assign it to _feedItems variable
self._feedItems = [[NSArray alloc] init];
// Create new HomeModel object and assign it to _homeModel variable
_currentIssueModel = [[CurrentIssueModel alloc] init];
// Set this view controller object as the delegate for the home model object
_currentIssueModel.delegate = self;
// Call the download items method of the home model object
[_currentIssueModel downloadItems];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIContentSizeCategoryDidChangeNotification object:nil];
}
- (void)didChangePreferredContentSize:(NSNotification *)notification
{
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)itemsDownloaded:(NSArray *)items
{
// This delegate method will get called when the items are finished downloading
// Set the downloaded items to the array
self._feedItems = items;
[activityView stopAnimating];
// Reload the table view
[self.tableView reloadData];
}
#pragma mark Table View Delegate Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of feed items (initially 0)
return self._feedItems.count;
}
/* ================================================== */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
[self configureCell:cell forRowAtIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell isKindOfClass:[CustomTableViewCell class]])
{
CustomTableViewCell *textCell = (CustomTableViewCell *)cell;
Article *article_item = self._feedItems[indexPath.row];
NSString *fulltitle = article_item.Title;
if (article_item.Subtitle != nil && article_item.Subtitle.length != 0) {
fulltitle = [fulltitle stringByAppendingString:#": "];
fulltitle = [fulltitle stringByAppendingString:article_item.Subtitle];
}
textCell.titleLabel.text = fulltitle;
if ([article_item.Author isEqualToString:#"accountant"]) {
textCell.authorLabel.text = #"";
}
else {
textCell.authorLabel.text = article_item.Author;
}
textCell.categoryLabel.text = article_item.Cat_Name;
textCell.titleLabel.numberOfLines = 0;
textCell.titleLabel.font = [UIFont fontWithName:#"Arial" size:12.0f];
textCell.authorLabel.font = [UIFont fontWithName:#"Arial" size:10.0f];
textCell.categoryLabel.font = [UIFont fontWithName:#"Arial" size:10.0f];
textCell.categoryLabel.textAlignment = NSTextAlignmentRight;
NSURL *url;
if ([article_item.ImageUrl length] != 0) {
url = [NSURL URLWithString:article_item.ImageUrl];
}
else {
url = [NSURL URLWithString:#"imageurl"];
}
[textCell.image sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:#"default_image.jpg"]];
}
}
- (CustomTableViewCell *)prototypeCell
{
if (!_prototypeCell)
{
_prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
}
return _prototypeCell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
[self configureCell:self.prototypeCell forRowAtIndexPath:indexPath];
self.prototypeCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.tableView.bounds), CGRectGetHeight(self.prototypeCell.bounds));
[self.prototypeCell layoutIfNeeded];
CGSize size = [self.prototypeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height+1;
}
/* ================================================== */
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Set selected article to var
_selectedArticle = self._feedItems[indexPath.row];
[self performSegueWithIdentifier:#"detailSegue" sender:self];
}
#pragma mark Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get reference to the destination view controller
ArticleViewController *articleVC = segue.destinationViewController;
// Set the property to the selected article so when the view for
// detail view controller loads, it can access that property to get the feeditem obj
articleVC.selectedArticle = _selectedArticle;
}
#end
I guess it's something to do with forRowAtIndexPath but I can't really figure out what's the issue.
Update:
I noticed that there is another problem with the title UILabel. Whenever you select a cell, view the article in another ViewController and go back to the UITableView the title labels are positioned in the Center Left rather than Top Left. Once you scroll again the title labels adjust to the proper position.
You have auto layout selected for the NIB/Storyboard but have not added any constraints to your cells. Add layout constraints to your cells. There is a great answer here that explains it in some details:

iOS partial screen dialog for drop down listbox (android spinner) style control

In iOS for the iPhone I want to make a control with similar appearance and behavior to the android spinner control when configured to behave like a drop down list box. Specifically when pressed a modal list of text options with radio buttons comes up and when one of them is pressed the list disappears and the control updates to that choice. Example:
So far I have seen a full-screen option using [self presentViewController...] with a custom ViewController but I want a partial screen (like pictured above) solution. Does anyone know how to do this or could point in the right direction.
The native solution to this will be a UIActionSheet which on iPhone will appear from the bottom and be partial screen or on iPad be very similar to the android version.
You can find the documentation here: UIActionSheet
if you didnt want to use the UIActionSheet and you wanted to make it reusable rather than adding a whole bund of UIViews to your current XIB, you could create a custom UIView with whatever interface you would need to populate it and use the interface builder to help make it look ok.
that view could have a message handler that posts the response that you would need to listen for.
then just init and load the view into your subviews and populate it
then post a message from the custom view to the handler you registered
so for your custom view you would have something like this.
#implementation SomeCustomView
+(SomeCustomView*)viewFromNibNamed:(NSString *)nibName{
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:NULL];
NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
SomeCustomView *customView = nil;
NSObject* nibItem = nil;
while ((nibItem = [nibEnumerator nextObject]) != nil) {
if ([nibItem isKindOfClass:[AADropDown class]]) {
customView = (SomeCustomView*)nibItem;
break;
}
}
return customView;
}
-(void)someInitializationWith:(NSArray*)repeatableData andNotificationId:(NSString*)noteId{
//set your stuff up for the view here and save the notification id
}
...
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[[NSNotificationCenter defaultCenter] postNotificationName:Your_Notification_Id object:somevalue];
}
#end
and include other things, like in this case the tableview stuff or any other logic.
then in your viewcontroller you could call it like
__block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:#"customViewAction" object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
//deal with notification here
[[NSNotificationCenter defaultCenter] removeObserver: observer];
}];
SomeCustomView *cv =(SomeCustomView*) [SomeCustomView viewFromNibNamed:#"SomeCustomView"];
[cv someInitializationWith:arrayOptions andNotificationId:#"customViewAction"];
[self.view addSubview:cv];
and in your interface builder you will just need to make sure that the class of the view is set to your class type.
then you can easily reuse this code again whenever a user needs to select something else in the same manner.
Here is a variation on the solution suggested by AtomRiot.
On your view (xib or storyboard) make a button and assign this graphic to it. Don't worry if it appears stretched out in the editor. The code will make it a realizable graphic.
2X version
Then include the following files in your project (copied below):
DDLBHelper.h
DDLBHelper.m
Then in your ViewController's .h file make links to the button:
#property (weak, nonatomic) IBOutlet UIButton *ddlbB;
- (IBAction)ddlbBClick:(id)sender;
In you ViewController's .m file make the following calls:
#synthesize ddlbB, choiceLabel;
DDLBHelper *mDDLBH;
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *strings = [[NSArray alloc] initWithObjects:#"Item 1", #"Item 2", #"Item 3", nil];
mDDLBH = [[DDLBHelper alloc] initWithWithViewController:self button:ddlbB stringArray:strings currentValue:1];
}
- (IBAction)ddlbBClick:(id)sender {
[mDDLBH popupList];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[mDDLBH adjustToRotation];
}
Works just like android.
Here are the files:
DDLBHelper.h
// DDLBHelper.h
// Created by MindSpiker on 9/27/12.
#import <Foundation/Foundation.h>
#protocol DDLBHelperDelegate <NSObject>
#required
- (void) itemSelected: (int)value;
#end
#interface DDLBHelper : UIViewController <UITableViewDelegate, UITableViewDataSource>{
id <DDLBHelperDelegate> delegate;
}
#property (retain) id delegate;
// external interface
- (id) init;
- (id) initWithWithViewController:(UIViewController *)viewController button:(UIButton *)button stringArray:(NSArray *)values currentValue:(int) currentValue;
- (void) popupList;
- (BOOL) isShown;
- (void) adjustToRotation;
- (int) getValue;
- (NSString *)getValueText;
#end
DDLBHelper.m
// DDLBHelper.m
// Created by MindSpiker on 9/27/12.
#import "DDLBHelper.h"
#import <QuartzCore/QuartzCore.h>
#interface DDLBHelper () {
#private
UIViewController *mVC;
UIButton *mButton;
NSArray *mValues;
int mValue;
UITableView *mTV;
UIView *mBackgroundV;
}
#end
#implementation DDLBHelper
#synthesize delegate;
- (id) init {
self = [super init];
mVC = nil;
mButton = nil;
mValues = nil;
mValue = -1;
return self;
}
- (id) initWithWithViewController:(UIViewController *)viewController button:(UIButton *)button stringArray:(NSArray *)values currentValue:(int) currentValue {
self = [super init];
// save pointers
mVC = viewController;
mButton = button;
mValues = values;
mValue = currentValue;
[self setupButton];
return self;
}
- (void) popupList{
if (mBackgroundV == nil){
mBackgroundV = [self setupBackgroundView];
[mVC.view addSubview:mBackgroundV];
}
if (mTV == nil){
mTV = [self setupTableView];
[mVC.view addSubview:mTV];
}
[mTV reloadData];
[mBackgroundV setHidden:NO];
[mTV setHidden:NO];
}
- (BOOL) isShown{
return !mTV.isHidden;
}
- (void) adjustToRotation{
BOOL isShown = [self isShown];
// remove the controls
if (mBackgroundV != nil){
[mBackgroundV removeFromSuperview];
mBackgroundV = nil;
}
if (mTV != nil){
[mTV removeFromSuperview];
mTV = nil;
}
if (isShown){
[self popupList];
}
}
- (int) getValue{
return mValue;
}
- (NSString *) getValueText{
if (mValues != nil && mValue > -1) {
if (mValues.count > mValue){
return [mValues objectAtIndex:mValue];
}
}
return nil;
}
- (void) updateButtonTitle{
NSString *title = [NSString stringWithFormat:#" %#", [self getValueText]];
[mButton setTitle:title forState:UIControlStateNormal];
}
- (void) setupButton {
UIImage *buttonBG = [UIImage imageNamed:#"sis_proceeds_ddlb.png"];
UIEdgeInsets insets = UIEdgeInsetsMake(8, 8, 8, 45);
UIImage *sizableImg = [buttonBG resizableImageWithCapInsets:insets];
[mButton setBackgroundImage:sizableImg forState:UIControlStateNormal];
[mButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[self updateButtonTitle];
}
- (UIView *) setupBackgroundView{
UIView *v = [[UIView alloc] initWithFrame:mVC.view.bounds];
[[v layer] setOpaque:NO];
[[v layer] setOpacity:0.7f];
[[v layer] setBackgroundColor:[UIColor blackColor].CGColor];
return v;
}
- (UITableView *) setupTableView {
CGRect rect = [self makeTableViewRect];
UITableView *tv = [[UITableView alloc] initWithFrame:rect style:UITableViewStylePlain];
[tv setDelegate:self];
[tv setDataSource:self];
[tv setBackgroundColor:[UIColor whiteColor]];
[[tv layer] setBorderWidth:2];
[[tv layer] setBorderColor:[UIColor lightGrayColor].CGColor];
[[tv layer] setCornerRadius:10];
[mVC.view addSubview:tv];
return tv;
}
- (CGRect) makeTableViewRect {
float l=0.0, t=0.0, w=0.0, h=0.0, maxH=0.0, cellH=0.0, cellsH=0.0;
// get
l = mButton.frame.origin.x;
w = mButton.frame.size.width;
t = mVC.view.bounds.origin.y + 50;
maxH = mVC.view.bounds.size.height - 100;
// get cell height
UITableViewCell *c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cellH = c.bounds.size.height;
// see if list will overlow maxH(eight)
cellsH = cellH * mValues.count;
if (cellsH > maxH) {
h = maxH;
} else {
h = cellsH;
}
return CGRectMake(l, t, w, h);
}
#pragma mark - TableView Delegate functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1; // this is a one section table
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return mValues.count; // should be called for only one section
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// try to resuse a cell if possible
static NSString *RESUSE_IDENTIFIER = #"myResuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:RESUSE_IDENTIFIER];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:RESUSE_IDENTIFIER];
}
cell.textLabel.text = [mValues objectAtIndex:indexPath.row];
if (mValue == indexPath.row){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
// save value and hide view
mValue = indexPath.row;
[self updateButtonTitle];
[mBackgroundV setHidden:YES];
[mTV setHidden:YES];
[delegate itemSelected:mValue];
}
#end

Resources