UITextField inside UITableViewCell: becomeFirstResponder in didSelectRowAtIndexPath - ios

I am currently trying to get this working. Any help is appreciated.
I have a custom UITableViewCell that has a UITextField inside. When I select the table cell, I would like to make the UITextField first Responder.
However [textField becomeFirstResponder]; returns false.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
UITextField *textField;
for (UIView *view in [cell subviews]) {
if ([view isMemberOfClass:[UITextField class]]) {
textField = ((UITextField *)view);
}
}
[textField becomeFirstResponder];
}
As requested, the initialisation of the textfield. This is done in the UITableViewCell subclass:
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Init Textfield
_textField = [[UITextField alloc] init];
_textField.backgroundColor = [UIColor clearColor];
_textField.delegate = self;
[self addSubview:_textField];
}
return self;
}

If you have a custom cell, then you can do something like this:
#implementation CustomCell
#pragma mark - UIResponder
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (BOOL)becomeFirstResponder
{
return [self.textField becomeFirstResponder];
}
#end
Then inside the table view delegate:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell canBecomeFirstResponder]) {
[cell becomeFirstResponder];
}
}

Give tag for each UITextField and and use Following code:
UITableViewCell* cell = (UITableViewCell*)sender.superview.superview;
UITextField *txtField = (UITextField*)[cell viewWithTag:tag];
[txtField becomeFirstResponder];
In didSelectRowAtIndexPath method.
Its working very good.. :)

I believe you need to set you textField's delegate property.
Add textField.delegate = self; to your method, before you call [textField becomeFirstResponder]

I think you should include a tag value on the textfield when creating the cell:
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Init Textfield
_textField = [[UITextField alloc] init];
_textField.backgroundColor = [UIColor clearColor];
_textField.delegate = self;
_textField.tag = 999;
[self addSubview:_textField];
}
return self;
}
And on the didSelectRowAtIndexPath method use the tag value to recover the object:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
UITextField *textField = (UITextField*)[cell viewWithTag:999];
if (![textField isFirstResponder]){
[textField becomeFirstResponder];
}
}
I've including a validation to control if the textfield is already the first responder.
Hope it works as you expect

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
UITextField *textField;
for (id subV in [cell subviews]) {
if ([subV isKindOfClass:[UITextField class]]) {
textField = (UITextField *)subV;
[textField becomeFirstResponder];
break;
}
}
}
I think it will be helpful to you.

Updated the answer from #josh-fuggle to use Swift 2.2.
import Foundation
import UIKit
class CustomTableCell:UITableViewCell {
#IBOutlet var textValue: UITextField!
override func canBecomeFirstResponder() -> Bool {
return true
}
override func becomeFirstResponder() -> Bool {
return self.textValue.becomeFirstResponder()
}
}
And this is in your table view delegate:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
if ((cell?.canBecomeFirstResponder()) != nil) {
cell?.becomeFirstResponder()
}
}

You can do something like this:
class CustomCell: UITableViewCell {
#IBOutlet weak var textField: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(contentViewTapped))
self.contentView.addGestureRecognizer(tapGesture)
}
#objc func contentViewTapped() {
_ = self.textField.becomeFirstResponder()
}
}

[self.titleLab performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.2];

Related

update array when the user updates the text field in the cell

I was wondering if there's a way to update barcodeItemsQuantity array when the user updates the text field in a custom uitableviewcell. Below are my code snippets. and I want to update data from my array whenever the user changes the textfield from the custom tableviewcell.
viewcontroller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Cell Initialized");
static NSString *cellIdentifier = #"BarcodeItemsCell";
BarcodeItemsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (cell == nil) {
cell = [[BarcodeItemsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell...
if (indexPath.row == [barcodeItems count]) {
// Add new row
cell.barcodeLabel.text = #"scan SKU";
cell.barcodeLabel.textColor = [UIColor lightGrayColor];
UIImage *btnImage = [UIImage imageNamed:#"barcodeIcon"];
[cell.leftButton setImage:btnImage forState:UIControlStateNormal];
cell.leftButton.tintColor = [UIColor blackColor];
cell.quantityTextField.userInteractionEnabled = NO;
[cell.leftButton addTarget:self action:#selector(scanBarcode) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"Add another Item Requested");
}
else {
// Display barcode items
cell.barcodeLabel.text = [barcodeItems objectAtIndex:indexPath.row];
UIImage *btnImage = [UIImage imageNamed:#"deleteIcon"];
cell.leftButton.tintColor = [UIColor redColor];
[cell.leftButton setImage:btnImage forState:UIControlStateNormal];
cell.leftButton.tag = indexPath.row;
[cell.leftButton addTarget:self action:#selector(deleteRow:) forControlEvents:UIControlEventTouchUpInside];
[barcodeItemsQuantity addObject:cell.quantityTextField];
}
NSLog(#"Cell Populated");
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return true;
}
-(void) deleteRow:(id)sender {
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:photoCaptureView.itemsTableView];
NSIndexPath *indexPath = [photoCaptureView.itemsTableView indexPathForRowAtPoint:buttonPosition];
[barcodeItems removeObjectAtIndex:indexPath.row];
[photoCaptureView.itemsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
NSLog(#"Item Removed");
}
barcodeitestableviewcell.h
#interface BarcodeItemsTableViewCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UIButton *leftButton;
#property (strong, nonatomic) IBOutlet UILabel *barcodeLabel;
#property (strong, nonatomic) IBOutlet UITextField *quantityTextField;
#end
Yes, you can update your data model value for the textfield text placed inside custom table cell.
STEP 1:
Add delegate in your current class "UITextFieldDelegate"
class ViewController: UIViewController,UITextFieldDelegate
STEP 2:
on your "cellForRowAt indexPath" invoke the delegate to current textfield and also add the tag
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// add the following lines
cell.textField.delegate = self
cell.textField.tag = indexPath.row
return cell
}
STEP 3:
call the UITextField Delegates
func textFieldDidEndEditing(textField: UITextField) {
if !textField.text.isEmpty { // check textfield contains value or not
if textField.tag == 0 {
firstName = textField.text!
} else {
lastName = textField.text!
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(textField: UITextField!) {
if textField.tag == 0 {
firstName = ""
} else {
lastName = ""
}
}
Here, you can replace the firstName and lastName with your desired model variables.
Hope this will work for you.

How to call one class delegate methods from another class

In table list using swift here i want to load the one class table-list in another class view controller and this concept is working in objective-c but come down to swift delegate methods are not calling my objective -c#swift codes below please help me some one else
BackGroundView.h:-
#import <UIKit/UIKit.h>
#interface BackGroundView
UIViewController<UITableViewDataSource,UITableViewDelegate>
{
UITableView *tableView;
}
#property(nonatomic, retain) UITableView *tableView;
-(void)tableList:(UIView *) view1;
#end
BackGroundView.m:-
#import "BackGroundView.h"
#interface BackGroundView ()
{
NSArray * Mainarray;
}
#end
#implementation BackGroundView
#synthesize tableView;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)tableList:(UIView *) view1
{
Mainarray = [[NSArray alloc]initWithObjects:#"india",#"australia",#"usa", nil];
tableView=[[UITableView alloc]init];
tableView.frame = CGRectMake(0,0,320,400);
tableView.dataSource=self;
tableView.delegate=self;
tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
[tableView reloadData];
tableView.separatorColor = [UIColor blackColor];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
[view1 addSubview:tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return Mainarray.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath] ;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text= [Mainarray objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:#selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:#selector(setPreservesSuperviewLayoutMargins:)]) {
[cell setPreservesSuperviewLayoutMargins:NO];
}
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
#end
MaindView.h
#import <UIKit/UIKit.h>
#interface ViewController1 : UIViewController
#end
MaindView.m
#import "ViewController1.h"
#import "BackGroundView.h"
#interface MaindView ()
{
BackGroundView * v1;
}
#end
#implementation MaindView
- (void)viewDidLoad {
[super viewDidLoad];
v1 = [[BackGroundView alloc]init];
// Do any additional setup after loading the view.
[v1 tableList:self.view];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Now it's working fine in objective-c and table list is loading fine
come down to swift ios:-
Now i am calling TableViewAdding from Mainview class to BackgroundView it's calling but delegate methods are not calling in background class i.e it is showing empty view controller in swift table list is not loading properly please help me and this is my swift code
BackGroundView.swift
import UIKit
class BackGroundView: UIViewController,UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView = UITableView()
var items = NSArray ()
override func viewDidLoad() {
super.viewDidLoad()
}
func TableViewAdding(myview:UIView)
{
items = ["india","australia","usa"];
println(items)
tableView.frame = CGRectMake(0, 50, 320, 200);
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
myview.addSubview(tableView)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
println("numberOfRowsInSection")
return self.items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
println("cellForRowAtIndexPath")
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = self.items.objectAtIndex(indexPath.row) as NSString
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
println("in first")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Mainview.swift
import UIKit
class Mainview: UIViewController{
#IBOutlet var myview1: UIView!
override func viewDidLoad() {
super.viewDidLoad()
var total = BackGroundView.alloc()
total.TableViewAdding(self.view)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
[UPDATED]
You're not initializing the BackGroundView in mainview.swift. You're just allocating the memory for the object. Note that you both alloc and init a class in Objective-C. In Swift, you have to do the same thing with Class.alloc().initialize(). However, swift has replaced that verbose line of code with a simple call: Class()
Objective-C:
Class *myInstance = [[Class alloc] init];
Swift:
var myInstance = Class()
Some other things:
It's always a good idea to call tableView.reloadData() after you
change the information in it (like in your TableViewAdding) method.
It's never a good idea to hard code numbers (like the table view size).
TableViewAdding looks like a class method. tableViewAdding would follow the camelCase convention more accurately
Documentation for why using var myInstance = Class.alloc() is not the same as using var myInstance = Class() can be found in Apple's NSObject documentation under Creating, Copying, and Deallocating Objects
https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/index.html#//apple_ref/occ/clm/NSObject/alloc
Using KVC to get delegate property.
Using NSInvocation to call delegate method
Declare total as Class variable in Mainview.swift. Don't use .alloc()
import UIKit
class Mainview: UIViewController{
var total = BackGroundView()
#IBOutlet var myview1: UIView!
override func viewDidLoad() {
super.viewDidLoad()
total.TableViewAdding(self.view)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

UITableViewCell get deleted directly by tapping delete control on the left but not show delete button on the right

When I involve [tableView setEditing:YES animated:YES], delete control shows on every cell on the left,what I want to do is to get the event when I tap delete control,and directly delete cell but not to show delete button on the right.
I know apple's standard way to do this is to show delete button on the right, and when I tap it ,datasource's
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
gets involved, the reason I don't want to do like this is my cell is customised by scrollview which scroll horizontally so scroll to show delete button would made it a mess, so I wouldn't implement
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
in my datasource.
Have any idea?
one way u do is, customising the cell and put your own way of deleting the cell for example,
create a new custom cell by subclassing the UITableviewCell name it as something like CustomCellTableViewCell
in CustomCellTableViewCell.h define a delegate method for example,
#import <UIKit/UIKit.h>
#class CustomCellTableViewCell;
#protocol CellDelegate <NSObject>
- (void)deleteCell:(CustomCellTableViewCell *)cell;
#end
#interface CustomCellTableViewCell : UITableViewCell
+ (CustomCellTableViewCell *)createCell;
#property (weak, nonatomic) IBOutlet UIButton *deleteButton;
#property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
#property (weak,nonatomic) id<CellDelegate> cellDelegate;
- (IBAction)deleteAction:(id)sender;
- (void)showDeleteButton;
- (void)hideDeleteButton;
#end
and in CustomCellTableViewCell.xib add a button and set label connect to deleteButton and descriptionLabel
in CustomCellTableViewCell.m file
#import "CustomCellTableViewCell.h"
#implementation CustomCellTableViewCell
- (void)awakeFromNib {
// Initialization code
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
self = [CustomCellTableViewCell createCell];
}
return self;
}
+ (CustomCellTableViewCell *)createCell
{
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:#"CustomCellTableViewCell" owner:nil options:nil];
if ([arrayOfViews count] < 1) {
return nil;
}
for (id item in arrayOfViews) {
if([item isKindOfClass:[UITableViewCell class]])
return item;
}
return nil;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (IBAction)deleteAction:(id)sender {
if([self.cellDelegate respondsToSelector:#selector(deleteCell:)])
{
[self.cellDelegate deleteCell:self];
}
}
- (void)showDeleteButton
{
CGRect destRect = self.descriptionLabel.frame;
destRect.origin.x += 80;
[UIView animateWithDuration:0.3 animations:^{
self.descriptionLabel.frame = destRect;
}];
}
- (void)hideDeleteButton
{
CGRect destRect = self.descriptionLabel.frame;
destRect.origin.x = 0;
[UIView animateWithDuration:0.3 animations:^{
self.descriptionLabel.frame = destRect;
}] ;
}
#end
and in controller .m file
- (void)viewDidLoad {
[super viewDidLoad];
stringsArray = [[NSMutableArray alloc]initWithObjects:#"apple",#"dell",#"windows",#"nokia",#"sony",#"hp",#"lenovo", nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [stringsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SuggestionCell"];
if(cell == nil)
{
cell = [[CustomCellTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SuggestionCell"];
}
if(customEditTableView)
[cell showDeleteButton];
else
[cell hideDeleteButton];
cell.cellDelegate = self;
cell.descriptionLabel.text = [stringsArray objectAtIndex:indexPath.row];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50.0f;
}
- (IBAction)deleteCellsAction:(id)sender
{
if(customEditTableView)
customEditTableView = NO;
else
customEditTableView = YES;
[self.aTableView reloadData];
}
- (void)deleteCell:(CustomCellTableViewCell *)cell
{
NSIndexPath *indexPath = [self.aTableView indexPathForCell:cell];
[stringsArray removeObjectAtIndex:indexPath.row];
[self.aTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
try out in new project u will get it
You can achive this thing using UIViewController
Add tableview and tableviewcell in UIViewController
I have achive this same thing using swift. It will give you idea how to do in Objective-C
Below is Code:
var data:[String] = ["One","Three","Four","Five","Six"]
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem()
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel.text = self.data[indexPath.row]
if editing
{
cell.imageView.image = UIImage(named: "Button-Delete-icon.png")
}
else
{
cell.imageView.image = UIImage(named: "")
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if editing
{
self.data.removeAtIndex(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
}
}
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
self.tableView.reloadData()
}
Hope It will Help

UISearchBar: search results hidden behind the searchbar

I have implemented an empty ViewController i.e SearchViewController with a SearchBar in it. Ans as i am searching from a web service, i want the search results to be displayed only when the user presses the search button. That has been implemented. Bt the problem is, the results appear in a weird manner as shown below:
Dont know what are they getting hidden. How do i bring them to front??
Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
self.api.delegate = self
activateSearch()
searchTableView.delegate = self
searchTableView.dataSource = self
searchBar.delegate = self
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as UITableViewCell
var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary
cell.textLabel?.text = rowData["title"] as? String
return cell
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
func didReceiveAPIResults(results: NSDictionary) {
var resultsArr: NSArray = results["posts"] as NSArray
dispatch_async(dispatch_get_main_queue(), {
self.tableData = resultsArr
self.searchTableView!.reloadData()
})
}
func activateSearch() {
// self.navigationController?.navigationBarHidden = true
searchTableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: false)
searchBar.becomeFirstResponder()
}
override func viewWillAppear(animated: Bool) {
var newBounds:CGRect = self.searchTableView.bounds;
newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height;
self.searchTableView.bounds = newBounds;
self.navigationController?.navigationBarHidden = true
}
func searchBarSearchButtonClicked( searchBar: UISearchBar!)
{
api.searchItunesFor(searchBar.text)
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
self.viewWillAppear(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
I might hv done something silly. bt m not able to figure out what is it.. pls help
It looks like your search bar has been placed over your table view. Try to scale your table view down in the storyboard so the top of the table view is below the search bar element. The results should display correctly
You are changing the searchTableView frame inside the viewWillAppear method which will not get call when you are in the same view controller.
Try changing the searchTableView frame inside the searchBarSearchButtonClicked method.
Hope this will solve your problem. :)
Edit:
Also try adding the search bar to the searchTableView header.
Below is the objective-c code for adding the search bar to the tableView header.
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)] ;
self.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.searchBar.keyboardType = UIKeyboardTypeAlphabet;
self.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchBar;
Just posting the answer incase someone ends in a situation like mine.
I didn't connect the tableView to the SearchDisplayController.
The tableView should be the dataSource and Delegate for the SearchDisplayController.
We just need to control+Drag to connect.
PS. in XCODE 6.1 the SearchDisplayController is displayed as a button like thing in the header of ViewController.
#import <UIKit/UIKit.h>
#interface TableViewController : UITableViewController
#end
#import "TableViewController.h"
#interface TableViewController () {
NSInteger _rows;
}
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#end
#implementation TableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_rows = 3;
// [self hideSearchBar];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.tableView setContentOffset:CGPointMake(0,44) animated:NO];
// self.tableView.tableHeaderView = self.searchBar;
}
-(void)viewDidDisappear:(BOOL)animated{
//self.tableView.tableHeaderView = nil;
//[self.tableView.tableHeaderView removeFromSuperview];
[self.tableView setContentInset:UIEdgeInsetsMake(-0.3, 0, 0, 0)];
[super viewDidAppear:animated];
}
- (void)hideSearchBar {
// hide search bar
[self.tableView setContentOffset:CGPointMake(0,44) animated:NO];
}
- (IBAction)toggleCount:(UIBarButtonItem *)sender {
if (_rows == 20) {
_rows = 3;
} else {
_rows = 20;
}
[self.tableView reloadData];
}
- (IBAction)hideBar:(UIBarButtonItem *)sender {
[self hideSearchBar];
}
#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 the number of rows in the section.
return _rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = #"cell";
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end

Is it possible to add UITableView within a UITableViewCell

Hear is just the idea what i am thinking to implement this,
I want to implement book like pages, for this i want to take UITableView and rotated-90 degree and its cell by 90 degree, and now i want to subclass UITableViewCell, now within this tableview cell it is possible to add UITableview so that user can scroll vertically to see the contents and user can also scroll horizontally to go to next cell of rotated tableview.
It is just i am thinking, is there any better way to implement this.
yes it is possible, I added the UITableVIew within the UITableView cell
.. :)
no need to add tableview cell in xib file - just subclass the UITableviewCell and use the code below, a cell will be created programatically.
//in your main TableView
#import "ViewController.h"
#import "CustomCell.h"
#interface ViewController ()<UITableViewDataSource , UITableViewDelegate>
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
[_aTV release];
[super dealloc];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [self.aTV dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil)
{
cell = [[[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"]autorelease];
}
cell.dataAraay = [NSMutableArray arrayWithObjects:#"subMenu->1",#"subMenu->2",#"subMenu->3",#"subMenu->4",#"subMenu->5", nil];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 150;
}
//in your custom tableview cell
// .m file
#import "CustomCell.h"
#implementation CustomCell
#synthesize dataAraay; //array to hold submenu data
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.frame = CGRectMake(0, 0, 300, 50);
UITableView *subMenuTableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain]; //create tableview a
subMenuTableView.tag = 100;
subMenuTableView.delegate = self;
subMenuTableView.dataSource = self;
[self addSubview:subMenuTableView]; // add it cell
[subMenuTableView release]; // for without ARC
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)layoutSubviews
{
[super layoutSubviews];
UITableView *subMenuTableView =(UITableView *) [self viewWithTag:100];
subMenuTableView.frame = CGRectMake(0.2, 0.3, self.bounds.size.width-5, self.bounds.size.height-5);//set the frames for tableview
}
//manage datasource and delegate for submenu tableview
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return dataAraay.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellID"];
if(cell == nil)
{
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cellID"]autorelease];
}
cell.textLabel.text = [self.dataAraay objectAtIndex:indexPath.row];
return cell;
}
#end
Swift version
Create a single view project add tableview inside storyboard and set up its datasource and delegate
Paste code below to ViewController.swift
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:CustomCell? = tableView.dequeueReusableCellWithIdentifier("Cell") as? CustomCell
if cell == nil {
cell = CustomCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
cell?.dataArr = ["subMenu->1","subMenu->2","subMenu->3","subMenu->4","subMenu->5"]
return cell!
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 150.0
}
}
create a new file CustomCell.swift which is the subclass of UITableViewCell and do not select with xib this file is without .xib file table and its cell will be created programatically as in objective-c code.
Paste code below to CustomCell.swift
import UIKit
class CustomCell: UITableViewCell,UITableViewDataSource,UITableViewDelegate {
var dataArr:[String] = []
var subMenuTable:UITableView?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style , reuseIdentifier: reuseIdentifier)
setUpTable()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
setUpTable()
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setUpTable()
}
func setUpTable(){
subMenuTable = UITableView(frame: CGRectZero, style:UITableViewStyle.Plain)
subMenuTable?.delegate = self
subMenuTable?.dataSource = self
self.addSubview(subMenuTable!)
}
override func layoutSubviews() {
super.layoutSubviews()
subMenuTable?.frame = CGRectMake(0.2, 0.3, self.bounds.size.width-5, self.bounds.size.height-5)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArr.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("cellID")
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cellID")
}
cell?.textLabel?.text = dataArr[indexPath.row]
return cell!
}
}
Better way: use a UIPageViewController for your left/right page scrolling. Each page can contain a table view.
Although rob's Idea is better but yes it is possible. Check how:
Take 2 table view, give them tag 1, 2, let's call these kTagBaseTableView, kTagInnerTableView. Now below is the blue print, how to deat with two table view, with delegate and data source attached to single view controller.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ // Default is 1 if not implemented
switch (tableView.tag) {
case kTagBaseTableView:
return baseSectionCount;
break;
case kTagInnerTableView:
return innerSectionCount;
break;
default:
break;
}
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
switch (tableView.tag) {
case kTagBaseTableView:
return [baseDataSource count];
break;
case kTagInnerTableView:
return [innerDataSource count];
break;
default:
break;
}
return 0;
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
switch (tableView.tag) {
case kTagBaseTableView:{
static NSString* baseIdentifier = #"baseTableViewCell";
cell = [tableView dequeueReusableCellWithIdentifier:genderIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:genderIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
cell.textLabel.text = NSLocalizedString(titleKey, nil);
return cell;
}
break;
case kTagInnerTableView:{
static NSString* innerIdentifier = #"innerTableViewCell";
cell = [tableView dequeueReusableCellWithIdentifier:genderIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:genderIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
cell.textLabel.text = NSLocalizedString(titleKey, nil);
return cell;
}
default:
break;
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ // fixed font style. use custom view (UILabel) if you want something different
switch (tableView.tag) {
case kTagBaseTableView:
break;
case kTagInnerTableView:
break;
default:
break;
}
return nil;
}
//TABLE VIEW DELEGATE
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
selectedIndexPath = indexPath;
switch (tableView.tag) {
case kTagBaseTableView:{}
break;
case kTagInnerTableView:{
}
break;
default:
break;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Create a subclass for tableView and override the intrinsicContentSize. I have answered here.
#import "API.h"
#import "Parsing.pch"
#import "HomeViewController.h"
#import "ASIFormDataRequest.h"
#import "MBProgressHUD.h"
#import "UIImageView+WebCache.h"
#import "HomeCollectionViewCellForSubCat.h"
#import "CollectionViewTableViewCell.h"
#import "NewsTableViewCell.h"
#import "CategoryTableViewCell.h"
#import "HomeCollectionViewCellForSubCat.h"
#import "WebviewController.h"
#import "TopFreeAppsCollectionViewTableViewCell.h"
#import "TopSitesCollectionViewTableViewCell.h"
#import "TrandingVideoCollectionViewTableViewCell.h"
#import "SportsTableViewCell.h"
#import "JokesTableViewCell.h"
#interface HomeViewController ()
{
MBProgressHUD *hud;
NSMutableArray *Details;
NSIndexPath *IndexPath;
CollectionVIewTableViewCell *TrafficCell;
NewsTableViewCell *NewsCell;
CategoryTableViewCell *CategoryCell;
TopFreeAppsCollectionViewTableViewCell *TopAppsCell;
TopSitesCollectionViewTableViewCell *TopSitesCell;
TrandingVideoCollectionViewTableViewCell *TrendingVideosCell;
SportsTableViewCell *SportsCell;
JokesTableViewCell *JokesCell;
}
#end
NSString *More;
NSMutableArray *news;
#implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.automaticallyAdjustsScrollViewInsets = NO;
//[self.navigationController setNavigationBarHidden:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return dataArray.count;
}
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Traffic" ])
{
if(!TrafficCell)
{
TrafficCell = [tableView dequeueReusableCellWithIdentifier:#"CollectionVIewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TrafficCell.Traffic = [dict valueForKey:#"detail"];
[TrafficCell.collectionView reloadData];
return TrafficCell;
}
return TrafficCell;
}
else if([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"News"])
{
if(!NewsCell)
{
NewsTableViewCell *cell = (NewsTableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"NewsTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
cell.News = [dict valueForKey:#"detail"];
[cell.NewsTableView reloadData];
return cell;
}
return NewsCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"TopApps"])
{
if(!TopAppsCell)
{
TopAppsCell = [tableView dequeueReusableCellWithIdentifier:#"TopFreeAppsCollectionViewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TopAppsCell.TopApps = [[dict valueForKey:#"detail"]valueForKey:#"small_banner"];
[TopAppsCell.TopAppsCollectionView reloadData];
return TopAppsCell;
}
return TopAppsCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"TopSites"])
{
if(!TopSitesCell)
{
TopSitesCell = [tableView dequeueReusableCellWithIdentifier:#"TopSitesCollectionViewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TopSitesCell.TopSites = [dict valueForKey:#"detail"];
[TopSitesCell.TopSitesCollectionView reloadData];
return TopSitesCell;
}
return TopSitesCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Category"])
{
if(!CategoryCell)
{
CategoryCell= [tableView dequeueReusableCellWithIdentifier:#"CategoryTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
CategoryCell.Category = [dict valueForKey:#"detail"];
[CategoryCell.CategorycollectionView reloadData];
return CategoryCell;
}
return CategoryCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"TrendingVideos"])
{
if(!TrendingVideosCell)
{
TrendingVideosCell= [tableView dequeueReusableCellWithIdentifier:#"TrandingVideoCollectionViewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TrendingVideosCell.TrendingVideos = [[dict valueForKey:#"detail"]valueForKey:#"small_banner"];
[TrendingVideosCell.VideosCollectionView reloadData];
return TrendingVideosCell;
}
return TrendingVideosCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Sports"])
{
if(!SportsCell)
{
SportsCell= [tableView dequeueReusableCellWithIdentifier:#"SportsTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
SportsCell.Sports = [dict valueForKey:#"detail"];
[SportsCell.SportsTableView reloadData];
return SportsCell;
}
return SportsCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Jokes"])
{
if(!JokesCell)
{
JokesCell= [tableView dequeueReusableCellWithIdentifier:#"JokesTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
JokesCell.Jokes = [dict valueForKey:#"detail"];
[JokesCell.JokesTableView reloadData];
return JokesCell;
}
return JokesCell;
}
else
{
}
return nil;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *dict = dataArray[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath];
if([dict[#"type"] isEqual:#"Traffic" ])
{
//Find your collectionView in cell
//Tap on Traffic cells
}
else if([dict[#"type"] isEqual:#"News"])
{
//Tap on News cells
}
else if([dict[#"type"] isEqual:#"Category"])
{
//Tap on Category cells
}
else if([dict[#"type"] isEqual:#"TopApps"])
{
//Tap on TopApps cells
}
else if([dict[#"type"] isEqual:#"TopSites"])
{
//Tap on TopSites cells
}
else if([dict[#"type"] isEqual:#"TrendingVideos"])
{
//Tap on Trending cells
}
else if([dict[#"type"] isEqual:#"Sports"])
{
//Tap on Sports cells
}
else if([dict[#"type"] isEqual:#"Jokes"])
{
//Tap on Jokes cells
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = dataArray[indexPath.row];
if([dict[#"type"] isEqual:#"Traffic" ])
{
return 155;
}
else if([dict[#"type"] isEqual:#"News"])
{
return 300;
}
else if([dict[#"type"] isEqual:#"Category"])
{
return 120;
}
else if([dict[#"type"] isEqual:#"TopApps"])
{
return 180;
}
else if([dict[#"type"] isEqual:#"TopSites"])
{
return 240;
}
else if([dict[#"type"] isEqual:#"TrendingVideos"])
{
return 270;
}
else if([dict[#"type"] isEqual:#"Sports"])
{
return 310;
}
else if ([dict[#"type"] isEqual:#"Jokes"])
{
return 280;
}
return 200;
}

Resources