UITableView cellForRowAtIndexPath is not being called - ios

I am having a problem with blank table data as this method is not getting called after I press search in my UISearchBar. I have tried everything and the table is just showing up blanking after pressing search.
This code takes the description from my json url and scans it for the searched word and then puts the index location of whatever description has that search term into an array (self.indexArray).
I would like to the call the table to only display those cells of the index values in that array.
- (void)viewDidLoad
{
[super viewDidLoad];
UISearchBar *tempSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 64, 320, 40)];
self.searchBar = tempSearchBar;
self.searchBar.delegate = self;
self.searchBar.placeholder = #"Search listings...";
[self.view addSubview:self.searchBar];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
[self sendData];
}
- (void)sendData
{
NSString *search = self.searchBar.text;
NSString *temp = [NSString stringWithFormat:#"MY JSON RETRIEVAL LINK"];
NSURL *url = [[NSURL alloc] initWithString:temp];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]
initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation
, id responseObject) {
NSLog(#"%#",responseObject);
NSLog(#"%#",[responseObject class]);
self.images = responseObject;
self.descriptions = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.images count]; i++)
{
[self.descriptions addObject:self.images[i][#"description"]];
}
for (int i = 0; i < [self.descriptions count]; i++)
{
NSLog(#"%d: %#", i, self.descriptions[i]);
if ([self.descriptions[i] rangeOfString:search options:NSCaseInsensitiveSearch].location != NSNotFound)
{
NSLog(#"ADDING, %d", i);
[self.indexArray addObject:[NSNumber numberWithInt:i]];
}
}
tableView = [[UITableView alloc] initWithFrame:CGRectMake(0,104,320,480) style:UITableViewStylePlain];
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:tableView];
[tableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error.localizedDescription);
}];
[operation start];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"FUNCTION CALLED");
TLCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if(cell == nil) {
cell = [[TLCustomCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
for(UIView *view in cell.contentView.subviews){
if ([view isKindOfClass:[UIView class]]) {
[view removeFromSuperview];
}
}
NSString *name = self.images[indexPath.row][#"name"];
NSString *location = self.images[indexPath.row][#"location"];
NSString *body = self.images[indexPath.row][#"description"];
NSString *list_type = self.images[indexPath.row][#"category"];
NSString *millisecs = self.images[indexPath.row][#"_createdAt"];
NSDate *date = [NSDate date];
NSTimeInterval ti = [date timeIntervalSince1970];
double myDouble = [millisecs doubleValue];
double delta = (ti * 1000) - myDouble;
NSString *time = [self calculateInterval:delta];
cell.nameLabel.text = name;
cell.locationLabel.text = location;
cell.bodyLabel.text = body;
CGFloat fixedWidth = cell.bodyLabel.frame.size.width;
CGSize newSize = [cell.bodyLabel sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = cell.bodyLabel.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
cell.bodyLabel.frame = newFrame;
cell.timeLabel.text = time;
if ([list_type isEqualToString:#"Sell"])
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"sell_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
else if ([list_type isEqualToString:#"Trade"])
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"trade_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
else if ([list_type isEqualToString:#"Wanted"])
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"want_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
else
{
UIImageView *thumbnailView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"ad_icon_small.png"]];
thumbnailView.frame = CGRectMake(12, 12, 50., 50.);
[cell addSubview:thumbnailView];
}
NSString *temp = self.images[indexPath.row][#"link"];
if ([temp isEqualToString:#"no_link"])
{
_thereIsAnImage = FALSE;
}
else
{
_thereIsAnImage = TRUE;
}
if (_thereIsAnImage)
{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:self.images[indexPath.row][#"link"]
options:0
progress:^(NSInteger receivedSize, NSInteger expectedSize)
{
// progression tracking code
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
{
if (image)
{
cell.imageView.image = image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.clipsToBounds = YES;
cell.imageView.tag = indexPath.row;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
[tap setNumberOfTapsRequired:1];
[tap setNumberOfTouchesRequired:1];
[cell.imageView setUserInteractionEnabled:YES];
[cell.imageView addGestureRecognizer:tap];
}
}];
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.indexArray.count;
}

If you are doing it programmatically then you need to set tableview.delegate = self and tableview.datasource = self in viewDidLoad method. Put a breakpoint in numberOfRowsInSection: to see the number that it's returning to check whether it's more than zero or not.

I would ask that you please check your header file - it should include the following...
#interface YourTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
Investigate how to implement UISearchBarDelegate and UISearchDisplayDelegate methods to manage search function in your (table) view controller. Read the Apple documentation UISearchBarDelegate and UISearchDisplayDelegate.
When you use a UISearchBar, you need a UISearchDisplayController to manage the search results.
If you are not using storyboards, it is important to set the appropriate data source and delegates for instances of both the UITableView and the UISearchDisplayController in your UITableViewController.
Then in your two table view data source methods, you need to provide information to the searchResultsTableView (accessed via self.searchDisplayController.searchResultsTableView) so that it knows how to prepare the search results table view.
For example...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger nofRowsInSection = 0;
if (tableView == self.searchDisplayController.searchResultsTableView) {
nofRowsInSection = self.searchResults.count;
} else {
nofRowsInSection = self.indexArray.count;
}
return nofRowsInSection;
}
...and...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
... <<other code>> ...
NSString *name = nil;
NSString *location = nil;
etc...
if (tableView == self.searchDisplayController.searchResultsTableView) {
name = self.searchResults[indexPath.row][#"name"];
location = self.searchResults[indexPath.row][#"location"];
...etc...
} else {
name = self.images[indexPath.row][#"name"];
location = self.images[indexPath.row][#"location"];
...etc...
}
... <<other code>> ...
}
Note that self.searchResults should be an NSMutableArray and it should contain data for the search results table view, prepared by filtering self.indexArray based on the search bar text.
Hope this helps.

Your code seems OK . check whether table from storeybaord is connected with the table and delegated correctly.

Did you put
#interface YourViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
to the top of you ViewController.m file?

You need to set tableView.delegate = self and tableView.dataSource = self in the viewDidLoad

Related

iOS - Why my next view callback my previous view?

My situation is the next :
I have two view controller.
The first contains an UITableView. When I tap on a cell, the second view is called and display another UITableView.
Problem :
Immediately that my second view has been displayed, it's removed and my app come back on the first view.
In debug mode, I can see that viewDidLoad() is called and the TableView has been initialised because the TableView is filled.
But I don't know why, viewWillDisappear() is called immediately, as if the view was removed...
Could someone to help me out please?
EDIT :
My first View :
#import "CIMSaddlesResearchesSavedViewController.h"
#import <Foundation/Foundation.h>
#interface CIMSaddlesResearchesSavedViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation CIMSaddlesResearchesSavedViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackground"] forBarMetrics:UIBarMetricsDefault];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
}
- (UIStatusBarStyle) preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.researches count];
}
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"researchCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
CIMSaddleResearch *research;
research = self.researches[indexPath.row];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"researchCell"];
}
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor clearColor];
if (research.dbId && ![research.dbId isEqual:#""]) {
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd/MM/yyyy"];
NSMutableString *minPrice = [NSMutableString stringWithString:#""];
NSMutableString *maxPrice = [NSMutableString stringWithString:#""];
NSMutableString *currencyS = [NSMutableString stringWithString:#""];
CIMCurrency *currency = [[CIMCurrency alloc] init];;
NSMutableString *researchText = [NSMutableString stringWithString:#""];
if (research.customer && ![research.customer isEqual:#""]) {
CIMCustomer *customer = [[CIMCustomer alloc] init];
customer.dbId = research.customer;
customer = [dbMngr firstObjectFromDb:customer];
[researchText appendFormat:#"%# le %#", customer.lastName, [formatter stringFromDate:research.date]];
}
CIMSaddleResearchLine *researchLine = [[CIMSaddleResearchLine alloc] init];
researchLine.saddleResearch = research.dbId;
NSArray *lines = [dbMngr objectsFromDb:researchLine];
for(CIMSaddleResearchLine *line in lines){
if([line.field isEqualToString:#"PRIX_MIN"])
[minPrice appendFormat:#"%#", line.value];
else if([line.field isEqualToString:#"PRIX_MAX"])
[maxPrice appendFormat:#"%#", line.value];
else if([line.field isEqualToString:#"DEVISE"])
[currencyS appendFormat:#"%#", line.value];
}
if(![minPrice isEqual:#""] || ![maxPrice isEqual:#""]){
if(currencyS){
currency.dbId = currencyS;
currency = [dbMngr firstObjectFromDb:currency];
} else {
currency = [dbMngr defaultSocietyCurrency];
}
[researchText appendString:#" | Budget : "];
if(![minPrice isEqual:#""] && ![maxPrice isEqual:#""])
[researchText appendFormat:#"%#%# → %#%#", minPrice, currency.symbol, maxPrice, currency.symbol];
else if(![minPrice isEqual:#""] && [maxPrice isEqual:#""])
[researchText appendFormat:#"%#%# min.", minPrice, currency.symbol];
else if([minPrice isEqual:#""] && ![maxPrice isEqual:#""])
[researchText appendFormat:#"%#%# max.", maxPrice, currency.symbol];
}
NSMutableString *researchDetailText = [NSMutableString stringWithFormat:#"Relance le : %#", [formatter stringFromDate:research.deadline]];
CIMResearchStatus *status = [[CIMResearchStatus alloc] init];
status.dbId = research.status;
status = [dbMngr firstObjectFromDb:status];
if(status){
[researchDetailText appendFormat:#" (%#)", status.name];
}
cell.textLabel.text = researchText;
cell.detailTextLabel.text = researchDetailText;
if (research.comment && ![research.comment isEqual:#""] ) {
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
} else {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"saddleCell"];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.text = NSLocalizedString(#"The saddle is not in this list", nil);
cell.textLabel.textAlignment = NSTextAlignmentCenter;
}
return cell;
}
-(void) tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
CIMSaddleResearch *research = self.researches[indexPath.row];
if (research.comment && ![research.comment isEqual:#""] ) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(#"Comment", nil)
message:research.comment
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *actionOk = [UIAlertAction actionWithTitle:NSLocalizedString(#"Ok", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action){}];
[alert addAction:actionOk];
[self presentViewController:alert animated:YES completion:nil];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.navigationController popViewControllerAnimated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"openResultResearch"]) {
UITableView *table = (UITableView*)[(UITableViewCell*)sender superview];
NSIndexPath *index = [table indexPathForCell:(UITableViewCell*) sender];
CIMSaddleResearch *research = self.researches[index.row];
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
CIMSaddleResearchLine *researchLine = [[CIMSaddleResearchLine alloc] init];
CIMSaddleResearchFormViewController *form = [[CIMSaddleResearchFormViewController alloc] init];
form.minimumPriceRow = [[XLFormRowDescriptor alloc] init];
form.maximumPriceRow = [[XLFormRowDescriptor alloc] init];
form.minimumYearRow = [[XLFormRowDescriptor alloc] init];
form.maximumYearRow = [[XLFormRowDescriptor alloc] init];
form.currency = [[CIMCurrency alloc] init];
NSMutableDictionary *filters = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
[[NSMutableArray alloc] init], #"brand",
[[NSMutableArray alloc] init], #"model",
[[NSMutableArray alloc] init], #"size",
[[NSMutableArray alloc] init], #"color",
[[NSMutableArray alloc] init], #"finishing",
nil];
researchLine.saddleResearch = research.dbId;
NSArray *lines = [dbMngr objectsFromDb:researchLine];
NSSortDescriptor *sortFieldDesc = [[NSSortDescriptor alloc] initWithKey:#"field" ascending:YES selector:#selector(compare:)];
NSSortDescriptor *sortOrderDesc = [[NSSortDescriptor alloc] initWithKey:#"order" ascending:YES selector:#selector(compare:)];
lines = [lines sortedArrayUsingDescriptors:#[sortFieldDesc, sortOrderDesc]];
for(CIMSaddleResearchLine *line in lines){
if([line.field isEqualToString:#"PRIX_MIN"]){
form.minimumPriceRow.value = line.value;
}else if([line.field isEqualToString:#"PRIX_MAX"]){
form.maximumPriceRow.value = line.value;
}else if([line.field isEqualToString:#"ANNEE_MIN"]){
form.minimumYearRow.value = line.value;
}else if([line.field isEqualToString:#"ANNEE_MAX"]){
form.maximumYearRow.value = line.value;
}else if([line.field isEqualToString:#"DEVISE"]){
form.currency.dbId = line.value;
form.currency = [dbMngr firstObjectFromDb:form.currency];
}
else if([line.field isEqualToString:#"GA_REFCONSTRUC"]){
form.serialNumberRow.value = line.value;
}else if([line.field isEqualToString:#"GA_QUARTIER"]){
form.flapRow.value = line.value;
}else if([line.field isEqualToString:#"GA_MARQUE"]){
CIMBrand *brand = [[CIMBrand alloc] init];
brand.dbId = line.value;
[[filters objectForKey:#"brand"] addObject:[dbMngr firstObjectFromDb:brand]];
}else if([line.field isEqualToString:#"GA_MODEL"]){
CIMModel *model = [[CIMModel alloc] init];
model.dbId = line.value;
[[filters objectForKey:#"model"] addObject:[dbMngr firstObjectFromDb:model]];
}else if([line.field isEqualToString:#"GA_TAILLE"]){
CIMSize *size = [[CIMSize alloc] init];
size.dbId = line.value;
[[filters objectForKey:#"size"] addObject:[dbMngr firstObjectFromDb:size]];
}else if([line.field isEqualToString:#"GA_COULEUR"]){
CIMColor *color = [[CIMColor alloc] init];
color.dbId = line.value;
[[filters objectForKey:#"color"] addObject:[dbMngr firstObjectFromDb:color]];
}else if([line.field isEqualToString:#"GA_FINITION"]){
CIMFinishing *finishing = [[CIMFinishing alloc] init];
finishing.dbId = line.value;
[[filters objectForKey:#"finishing"] addObject:[dbMngr firstObjectFromDb:finishing]];
}
}
if(!form.currency.dbId && [form.currency.dbId isEqualToString:#""]){
CIMCustomer *customer = [[CIMCustomer alloc] init];
customer.dbId = research.customer;
customer = [dbMngr firstObjectFromDb:customer];
form.currency.dbId = customer.currency;
form.currency = [dbMngr firstObjectFromDb:form.currency];
}
CIMSaddlesViewController *saddlesViewController = segue.destinationViewController;
saddlesViewController.filters = filters;
saddlesViewController.saddleDbId = [NSMutableString stringWithString:#""];
saddlesViewController.selectionMode = NO;
saddlesViewController.saddleNotFoundOption = NO;
saddlesViewController.showSaddlePictures = YES;
saddlesViewController.showSaddleWarehouse = YES;
saddlesViewController.showToolbar = NO;
saddlesViewController.saddles = [dbMngr stockSaddlesWithFilters:filters
andSerialNumber:form.serialNumberRow.value
andFlap:form.flapRow.value
betweenMinimumPrice:form.minimumPriceRow.value
andMaximumPrice:form.maximumPriceRow.value
inCurrency:form.currency.dbId
betweenMinimumYear:form.minimumYearRow.value
andMaximumYear:form.maximumYearRow.value
inStock:YES];
saddlesViewController.formResearch = form;
saddlesViewController.saddlesPricesCurrency = form.currency;
}
}
#end
My second view :
#import "CIMSaddlesViewController.h"
#interface CIMSaddlesViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation CIMSaddlesViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackground"] forBarMetrics:UIBarMetricsDefault];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
}
- (UIStatusBarStyle) preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.saddles count];
}
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"saddleCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
CIMItem *saddle;
saddle = self.saddles[indexPath.row];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"saddleCell"];
}
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor clearColor];
if (saddle.dbId && ![saddle.dbId isEqual:#""]) {
NSMutableString *saddleText = [NSMutableString stringWithString:saddle.dbId];
NSMutableString *saddleDetailText = [NSMutableString stringWithString:saddle.name];
// Serial number
if (saddle.serialNumber && ![saddle.serialNumber isEqual:#""]) {
[saddleText appendFormat:#" - %#", saddle.serialNumber];
}
// Warehouse
if (self.showSaddleWarehouse) {
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
CIMStock *stock = [[CIMStock alloc] init];
stock.item = saddle.dbId;
stock.quantity = [NSNumber numberWithInt:1];
stock = [dbMngr firstObjectFromDb:stock];
if (stock) {
CIMWarehouse *warehouse = [[CIMWarehouse alloc] init];
warehouse.dbId = stock.warehouse;
warehouse = [dbMngr firstObjectFromDb:warehouse];
[saddleText appendFormat:#" → [%#]", warehouse.name];
}
}
// Estimed price
if (self.saddlesPricesCurrency) {
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
CIMSaddlePrices *saddlePrices = [[CIMSaddlePrices alloc] init];
saddlePrices.item = saddle.dbId;
saddlePrices.currency = self.saddlesPricesCurrency.dbId;
saddlePrices = [dbMngr firstObjectFromDb:saddlePrices];
if (saddlePrices) {
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setMaximumFractionDigits:0];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setCurrencyCode:self.saddlesPricesCurrency.isoCode];
NSString *isEstimateStr;
if ([saddlePrices.isEstimate isEqual:#"-"]) {
isEstimateStr = NSLocalizedString(#"Official price", nil);
} else {
isEstimateStr = NSLocalizedString(#"Estimation", nil);
}
[saddleText appendFormat:#" | %# (%#)", [numberFormatter stringFromNumber:saddlePrices.price], isEstimateStr];
}
}
cell.textLabel.text = saddleText;
cell.detailTextLabel.text = saddleDetailText;
// Saddle pictures
if (self.showSaddlePictures && [[self.saddlesPicturesDictionary allKeys] containsObject:saddle.dbId]) {
UIButton *accessoryButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)];
if ([self.saddlesiPadPictures containsObject:saddle.dbId]) {
[accessoryButton setImage:[UIImage imageNamed:#"SaddleiPadPictureButton"] forState:UIControlStateNormal];
} else {
[accessoryButton setImage:[UIImage imageNamed:#"SaddlePictureButton"] forState:UIControlStateNormal];
}
accessoryButton.tag = indexPath.row;
[accessoryButton addTarget:self action:#selector(showSaddlePicturesViewForSaddleWithSender:) forControlEvents:UIControlEventTouchDown];
cell.accessoryView = accessoryButton;
} else {
cell.accessoryView = nil;
}
} else {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"saddleCell"];
cell.backgroundColor = [UIColor whiteColor];
cell.textLabel.text = NSLocalizedString(#"The saddle is not in this list", nil);
cell.textLabel.textAlignment = NSTextAlignmentCenter;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.selectionMode) {
CIMItem *saddle = self.saddles[indexPath.row];
[self.saddleDbId setString:saddle.dbId];
[self.navigationController popViewControllerAnimated:YES];
} else {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
#end
To be honest, this project is very big, I begun to work on it since 2 month ago and I'm alone to work on it. I didn't work in Objective-C before and even less with X-Code. I'm discovering features and Objective-C gradually...
In your first VC you call [self.navigationController popViewControllerAnimated:YES]; which tells the navigationVC to pop the currently visible view controller. If you set breakpoints to the tableview didSelectRowAtIndexPath: in first VC and to viewDidLoad in your second VC you'll see in what order they are called. I have a feeling that the order of execution could be the following:
prepare for segue in firstVC
view did load in secondVC
didSelectRowAtIndexPath in first VC
finally your second VC unloads
This is my idea without testing it. Please make sure you really need to pop the VC in didSelectRow

how to add search filter in uitableview

I am working on UITableView where I have a list of contacts. All the contacts are coming form a webservice in JSON format. I already parse it in my tableView, now I want to add a search logic to search contacts.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ChatListCell *cell=[tableView dequeueReusableCellWithIdentifier:#"contactListCell"];
if(!cell){
cell = [[ChatListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"contactListCell"];
}
ChatListData *chatlistData = [chatList objectAtIndex:indexPath.row];
NSString *txtName = chatlistData.name;
NSLog(#"name %#", txtName);
NSData *emojiData = [txtName dataUsingEncoding:NSUTF8StringEncoding];
NSString *emojiTxtName = [[NSString alloc] initWithData:emojiData encoding:NSNonLossyASCIIStringEncoding];
cell.txtName.text = emojiTxtName;
cell.txtTime.text = chatlistData.time;
NSString *stringImg = #"image";
NSString *stringVideo = #"video";
if(![chatlistData.mime_type isEqual: [NSNull null]]){
if ([chatlistData.mime_type rangeOfString:stringImg].location == NSNotFound || [chatlistData.mime_type rangeOfString:stringVideo].location == NSNotFound) {
if ([chatlistData.mime_type rangeOfString:stringImg].location == NSNotFound) {
cell.txtMsg.text = #"Image";
}else if([chatlistData.mime_type rangeOfString:stringVideo].location == NSNotFound){
cell.txtMsg.text = #"Video";
}
}else {
NSString *txtMsg = chatlistData.body;
NSData *emojiData = [txtMsg dataUsingEncoding:NSUTF8StringEncoding];
NSString *emojiTxtMsg = [[NSString alloc] initWithData:emojiData encoding:NSNonLossyASCIIStringEncoding];
cell.txtMsg.text = emojiTxtMsg;
}
}else {
NSString *txtMsg = chatlistData.body;
NSData *emojiData = [txtMsg dataUsingEncoding:NSUTF8StringEncoding];
NSString *emojiTxtMsg = [[NSString alloc] initWithData:emojiData encoding:NSNonLossyASCIIStringEncoding];
cell.txtMsg.text = emojiTxtMsg;
}
return cell;
}
- (void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//http://app.wazapper.com/api/users/inbox/45/#api_917838828123
ChatListData *chatlistData = [chatList objectAtIndex:indexPath.row];
if(![chatlistData.contact isEqual: [NSNull null]]){
NSString *chatUrl = [NSString stringWithFormat:#"http://app.wazapper.com/api/users/inbox/%#/#api_%#", [[User sharedInstance] userId], chatlistData.contact];
chatViewController.chatUrl = chatUrl;
[[NSNotificationCenter defaultCenter] postNotificationName:#"ChangeChatList" object:chatUrl];
}
}
this is my little piece of code, please give me some idea about it, I have already added the search bar in UITableView, I just need a logic for this purpose.
First add UISearchBarDelegate to your ViewController, then add this method to filter your search.
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
NSPredicate *pre0 = [NSPredicate predicateWithFormat:#"Fname contains[cd] %#", searchText];
NSPredicate *pre1 = [NSPredicate predicateWithFormat:#"Lname contains[cd] %#", searchText];
NSPredicate *preAll = [NSCompoundPredicate orPredicateWithSubpredicates:#[pre0, pre1]];
NSArray *filterAry= [jsonAry filteredArrayUsingPredicate:preAll];
}
UI implementation:
- (void)setupSearchBar {
CGFloat ySearchBarPosition = self.navigationController.navigationBar.bounds.size.height;
CGRect viewBounds = self.view.bounds;
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(CGRectGetMinX(viewBounds), ySearchBarPosition, CGRectGetWidth(viewBounds), kHeightDefault44)];
self.searchBar.backgroundImage = [[UIImage alloc] init];
self.searchBar.barTintColor = kYourBarTintColor;
self.searchBar.tintColor = kYourTintColor;
self.searchBar.delegate = self;
self.searchBar.placeholder = NSLocalizedString(#"searchBar.placeholder", nil);
self.searchBar.showsCancelButton = YES;
for (UIView *subview in self.searchBar.subviews) {
for (UIView *subSubview in subview.subviews) {
if ([subSubview conformsToProtocol:#protocol(UITextInputTraits)]) {
UITextField *textField = (UITextField *)subSubview;
textField.returnKeyType = UIReturnKeyDone;
textField.backgroundColor = kColorUnregisteredDevicesSearchBarBackground;
textField.textColor = kColorUnregisteredDevicesSearchBarText;
}
if ([subSubview isKindOfClass:NSClassFromString(#"UINavigationButton")]) {
UIButton *cancelBarButton = (UIButton *)subSubview;
cancelBarButton.tintColor = kColorUnregisteredDevicesSearchBarCancelButtonTintColor;
}
}
}
self.tableView.tableHeaderView = self.searchBar;
self.tableView.contentOffset = CGPointMake(0.0, self.tableView.tableHeaderView.bounds.size.height);
}
call this method where you create your tableView, before this line of code:
[self.view addSubview:self.yourTableView];
Functionality implementation:
1. You have to add UISearchBarDelegate on your .h class.
2. Use this delegation methods:
// delegation methods
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[self reloadModelAndTable];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
self.searchBar.text = #"";
[self.tableView reloadData];
[self.searchBar resignFirstResponder];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self.searchBar resignFirstResponder];
}
// private methods
- (void)reloadModelAndTable:(NSTimer *)timer {
[self filterModelForSearch:self.searchBar.text];
[self.tableView reloadData];
}
- (void)filterModelForSearch:(NSString *)searchText {
NSMutableArray *records = (NSMutableArray *)[self.unregisteredDevicesList mutableCopy];
NSIndexSet *resultSet = [records indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
YourModel *model = (YourModel *)obj;
BOOL hasObjects = [self resultHasObjects:model withSearchText:searchText];
return hasObjects;
}];
self.yourArrayWhichPopulatesTheTable = [[records objectsAtIndexes:resultSet] mutableCopy];
}
- (BOOL)resultHasObjects:(YourModel *)model withSearchText:(NSString *)searchText{
// I consider you make search for name
return ((model.name.length > 0) && [self containsString:model.name searchText:searchText]);
}
- (BOOL)containsString:(NSString *)haystack searchText:(NSString *)needle {
if (haystack) {
NSRange range = [haystack rangeOfString:needle options:NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch];
return range.location != NSNotFound;
}
return NO;
}
This code works perfect. Good luck! If something is not clear, please let me know.:)

How to Asynchronously load UITableViewcell images so that scrolling doesn't lag

I've tried using ASyncImageView for this purpose, but I'm a bit confused as to how I'd implement it for my specific case. I currently have a MatchCenterViewController that contains a table inside of it. It's loading the images for the cells synchronously, which is causing a lot of lag when scrolling through the table. How can I modify the way I'm loading the remote images so that it's done asynchronously? My code is below:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#import "MatchCenterCell.h"
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *matchCenter;
#property (nonatomic, assign) BOOL matchCenterDone;
#property (nonatomic, assign) BOOL hasPressedShowMoreButton;
#end
#implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_matchCenterDone = NO;
_hasPressedShowMoreButton = NO;
// Set up MatchCenter table
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
self.matchCenter.frame = CGRectMake(0,70,320,self.view.frame.size.height-100);
self.edgesForExtendedLayout = UIRectEdgeAll;
self.matchCenter.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, CGRectGetHeight(self.tabBarController.tabBar.frame), 0.0f);
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
self.expandedSection = -1;
_matchCenterArray = [[NSArray alloc] init];
// Refresh button
UIImageView *refreshImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"refresh.png"]];
refreshImageView.frame = CGRectMake(280, 30, 30, 30);
refreshImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(refreshPressed:)];
[refreshImageView addGestureRecognizer:tapGesture];
[self.view addSubview:refreshImageView];
// Preparing for MC and indicating loading
self.matchCenterArray = [[NSArray alloc] init];
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0);
[self.view addSubview: activityIndicator];
[activityIndicator startAnimating];
_matchCenterDone = NO;
// Disable ability to scroll until table is MatchCenter table is done loading
self.matchCenter.scrollEnabled = NO;
[PFCloud callFunctionInBackground:#"MatchCenter3"
withParameters:#{}
block:^(NSArray *result, NSError *error) {
if (!error) {
_matchCenterArray = result;
[activityIndicator stopAnimating];
[_matchCenter reloadData];
_matchCenterDone = YES;
self.matchCenter.scrollEnabled = YES;
NSLog(#"Result: '%#'", result);
}
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return _matchCenterArray.count;
}
//the part where i setup sections and the deleting of said sections
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 21.0f;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 40;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
//code snipped out for conciseness
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
//Header code snipped out for conciseness
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *currentSectionDictionary = _matchCenterArray[section];
NSArray *top3ArrayForSection = currentSectionDictionary[#"Top 3"];
return (top3ArrayForSection.count-1 < 1) ? 1 : top3ArrayForSection.count-1;
}
// Cell layout
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Initialize cell
static NSString *CellIdentifier = #"MatchCenterCell";
MatchCenterCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// if no cell could be dequeued create a new one
cell = [[MatchCenterCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//[cell.contentView addSubview:cell.priceLabel];
[cell.contentView addSubview:cell.conditionLabel];
// No cell seperators = clean design
tableView.separatorColor = [UIColor clearColor];
NSDictionary *currentSectionDictionary = _matchCenterArray[indexPath.section];
NSArray *top3ArrayForSection = currentSectionDictionary[#"Top 3"];
if (top3ArrayForSection.count-1 < 1) {
// title of the item
cell.textLabel.text = #"No items found, but we'll keep a lookout for you!";
cell.textLabel.font = [UIFont systemFontOfSize:12];
}
else {
// title of the item
cell.textLabel.text = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Title"];
cell.textLabel.font = [UIFont systemFontOfSize:14];
// price + condition of the item
NSString *price = [NSString stringWithFormat:#"$%#", _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Price"]];
NSString *condition = [NSString stringWithFormat:#"%#", _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Item Condition"]];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", price, condition];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = 2.5;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == self.expandedSection || indexPath.row <= 3) {
return 65;
}
return 0;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (_matchCenterDone == YES) {
self.itemURL = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row+1][#"Item URL"];
[self performSegueWithIdentifier:#"WebViewSegue" sender:self];
}
}
#end
#implementation MoreButton
#end
// Use background thread to avoid the laggy tableView
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// Download or get images here
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"url"]];
UIImage *cellImage = [[UIImage alloc] initWithData:imageData];
// Use main thread to update the view. View changes are always handled through main thread
dispatch_async(dispatch_get_main_queue(), ^{
// Refresh image view here
[cell.imageView setImage:cellImage];
[cell.imageView.layer setMasksToBounds:YES];
[cell.imageView.layer setCornerRadius:2.5f];
[cell setNeedsLayout];
});
});
The most common solution to this is AFNetworking's AFImageView. It handles this situation perfectly. It should take you no time at all to implement, so give it a go.
Guy Kogus' answer works great. He's right, I got into all kinds of issues like he mentions in the comment above, doing similar things like the first answer.
Still, here's an example on how to use AFNetworking's UIImageView category. Assuming the code below is in a Cell (or something inheriting from a UIView).
First import the class:
#import "UIImageView+AFNetworking.h"
Then add this code in your UITableViewCell:
NSString *url = #"http://www.domain.www/some_image.jpg";
[self.productImage setImageWithURL:[NSURL URLWithString:url]
placeholderImage:[UIImage imageNamed:#"placeholderImg.png"]];
[self setNeedsLayout];
Not 100% sure if setNeedsLayout is necessary in this case. Feel free to correct this.

tableview crash with '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

I got a problem.
I have a TableView in my ViewController. This TableView has 5 rows with textFields. The height of each row is 156 pixels. also I have button "Save", and after click I want save all my data to NSMutableArray in following method, but in result I got an error.
What should I do in this way?
thank you
my method example:
- (void) saveDataToArray
{
carCellTableViewCell * cell;
_carNewPrices = [[NSMutableArray alloc] init];
for (int i = 0; i < 5; i++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carPrices addObject:cell.priceText.text];
}
}
and here is cellForRowAtIndexPath:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
carCellTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.nameLabel.text = [_carNames objectAtIndex:indexPath.row];
cell.priceLabel.text = [NSString stringWithFormat:#"$%#/day",[_carPrices objectAtIndex:indexPath.row]];
cell.infoLabl.text = [_carInfos objectAtIndex:indexPath.row];
switch (indexPath.row) {
case 0:
{
[cell.img setImage:[UIImage imageNamed:#"rolls.jpg"]];
return cell;
}
case 1:
{
[cell.img setImage:[UIImage imageNamed:#"bentley.jpg"]];
return cell;
}
case 2:
{
[cell.img setImage:[UIImage imageNamed:#"mercedes.jpg"]];
return cell;
}
case 3:
{
[cell.img setImage:[UIImage imageNamed:#"bmw.jpg"]];
return cell;
}
case 4:
{
[cell.img setImage:[UIImage imageNamed:#"skoda.jpg"]];
}
default:
break;
}
return cell;
}
additional:
in my tableviewCell i have a label, and a textfield. when i click on "Save" i want save all my data from textField and send it to label.
here is all code from .m file:
#import "carListViewController.h"
#import "carCellTableViewCell.h"
#import "UserSingleton.h"
#import "CheckInternetConnection.h"
#define getCarList #"http:mylink.php" //changed
#define setCarList #"http:mylink.php" //changed
#interface carListViewController ()
#property (weak, nonatomic) IBOutlet UIBarButtonItem *editButtonOutler;
- (IBAction)editButtonOnClick:(id)sender;
#property BOOL editOrSave;//0 when edit, 1 when save
#property UserSingleton * userInfo;
#property NSMutableArray *json;
#property NSMutableArray * carNames;
#property NSMutableArray * carPrices;
#property NSMutableArray * carInfos;
#property NSMutableArray * carNewPrices;
- (void) setData;
#property (weak, nonatomic) IBOutlet UITableView *meTableView;
- (void) saveDataToArray;
- (void) getDataOfCars;
#end
#implementation carListViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"List of cars";
// Do any additional setup after loading the view.
}
- (void) viewWillAppear:(BOOL)animated
{
CheckInternetConnection * checkInternet = [[CheckInternetConnection alloc] init];
if (![checkInternet isInternetAvailable])
[self.navigationController popViewControllerAnimated:YES];
_userInfo = [UserSingleton sharedInstance];
if (_userInfo.priority == 2)
{
_editButtonOutler.enabled = YES;
_editButtonOutler.title = #"Edit";
}
else
{
_editButtonOutler.enabled = NO;
_editButtonOutler.title = #"";
}
_editOrSave = NO;
[self getDataOfCars];
[_meTableView reloadData];
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
carCellTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.nameLabel.text = [_carNames objectAtIndex:indexPath.row];
cell.priceLabel.text = [NSString stringWithFormat:#"$%#/day",[_carPrices objectAtIndex:indexPath.row]];
cell.infoLabl.text = [_carInfos objectAtIndex:indexPath.row];
switch (indexPath.row) {
case 0:
{
[cell.img setImage:[UIImage imageNamed:#"rolls.jpg"]];
return cell;
}
case 1:
{
[cell.img setImage:[UIImage imageNamed:#"bentley.jpg"]];
return cell;
}
case 2:
{
[cell.img setImage:[UIImage imageNamed:#"mercedes.jpg"]];
return cell;
}
case 3:
{
[cell.img setImage:[UIImage imageNamed:#"bmw.jpg"]];
return cell;
}
case 4:
{
[cell.img setImage:[UIImage imageNamed:#"skoda.jpg"]];
}
default:
break;
}
return cell;
}
- (IBAction)editButtonOnClick:(id)sender {
if (_editOrSave == 0)
{
_editOrSave = 1;
_editButtonOutler.title = #"Save";
carCellTableViewCell * cell;
for (int i = 0; i < 5; i ++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.priceLabel.hidden = YES;
cell.priceText.hidden = NO;
cell.priceText.text = [[_json objectAtIndex:i] objectForKey:#"cost"];
}
}
else if (_editOrSave == 1)
{
_editOrSave = 0;
carCellTableViewCell * cell;
for (int i = 0; i < 5; i ++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.priceLabel.hidden = NO;
cell.priceText.hidden = YES;
[self saveDataToArray];
[self setData];
//cell.priceLabel.text = [_carPrices objectAtIndex:i];
}
_editButtonOutler.title = #"Edit";
}
[self getDataOfCars];
[_meTableView reloadData];
}
- (void) getDataOfCars
{
_carInfos = [[NSMutableArray alloc] init];
_carNames = [[NSMutableArray alloc] init];
_carPrices = [[NSMutableArray alloc] init];
NSURLRequest* urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:getCarList] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];
_json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
carCellTableViewCell * cell;
for (int i = 0; i < _json.count; i ++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carNames addObject:[[_json objectAtIndex:i] objectForKey:#"name"]];
[_carPrices addObject:[[_json objectAtIndex:i] objectForKey:#"cost"]];
[_carInfos addObject:[[_json objectAtIndex:i] objectForKey:#"about"]];
}
}
- (void) setData{
for (int i = 0; i < 5; i ++)
{
NSMutableString * postString = [NSMutableString stringWithFormat:setCarList];
[postString appendString:[NSString stringWithFormat:#"?id=%d", i+1]];
[postString appendString:[NSString stringWithFormat:#"&cost=%#", [_carPrices objectAtIndex:i]]];
[postString setString:[postString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:postString]];
[request setHTTPMethod:#"POST"];
NSURLConnection * postConnection;
postConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
}
- (void) saveDataToArray
{
carCellTableViewCell * cell;
_carNewPrices = [[NSMutableArray alloc] init];
for (int i = 0; i < 5; i++)
{
cell = (carCellTableViewCell *)[_meTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[_carPrices addObject:cell.priceText.text];
}
}
#end
it seems that an error is caused because not all cells are visible in the screen. after my scroll down now even last cell has changed after my onclick on edit button.
how to resovle this problem?
It's upside-down to fill an array with what's in a UITableView. The way to do that is the other way around.
In other words, somewhere else in your code you determine what's in the priceText label. If it's a static table, then the information might be in IB, or if you're implementing tableview:cellForRowAtIndexPath:, you're looking up the priceText there.
Put those values in the priceArray.
Your edit helped. This line:
[NSString stringWithFormat:#"$%#/day",[_carPrices objectAtIndex:indexPath.row]];
Is your friend, so:
NSMutableArray *newArrayOfStrings = [NSMutableArray array];
for (int i=0; i<_carPrices.count; i++) {
NSString *str = [NSString stringWithFormat:#"$%#/day",_carPrices[i]];
[newArrayOfStrings addObject:str];
}
Edit again. More code and comments, more clarity:
Declare that your vc implements the UITextFieldDelegate, and declare a property to keep your edited prices:
#interface MyViewController <UITextFieldDelegate>
#property (nonatomic, strong) NSMutableArray *editedStrings;
// initialize this with the carPrices after you get these from JSON
self.editedStrings = [_carPrices mutableCopy]; // if they are NSNumbers
// if they are strings, you'll need a deeper copy:
self.editedStrings = [NSMutableArray array];
for (NSString *str in _carPrices) {
[self.editedStrings addObject:[str copy]];
}
In cellForRowAtIndexPath, make your vc the delegate, and tag the textFields, so you know which one is being edited:
cell.priceLabel.delegate = self;
cell.priceLabel.tag = indexPath.row;
Then implement the delegate method for when the user edits:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSInteger index = textField.tag;
NSString *candidateString = [textField.text stringByReplacingCharactersInRange:range withString:string];
[self.editedStrings replaceObjectAtIndex:index withObject: candidateString];
return YES;
}
Add a breakpoint to the line [_carPrices addObject:cell.priceText.text] and you'll see that at some index, the text will be nil. I can't tell you why will it be nil, since I don't know how you're creating the cell.

iOS UITableView content not loading - Property access result unused

I'm trying to load a table with content from Twitter. The table is in a UIView and being created in the drawRect()...but I keep getting a warning:
Property access result unused - getters should not be used for side effects
on each.
Nothing show up in my table.
Here's my .h file:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <Twitter/Twitter.h>
#import "ColorController.h"
#interface TwitterController : UIView <UITableViewDelegate, UITableViewDataSource> {
UIButton* btnCloseView;
UITableView* tblTweets;
UIImageView* imgTwitterIcon;
ColorController* colorManager;
NSMutableArray* tweetsArray;
NSString* twitterID;
}
#property (nonatomic, retain) NSString* twitterID;
- (void) getTweets;
- (void) closeWin;
#end
and my .m
#import "TwitterController.h"
#implementation TwitterController
#synthesize twitterID;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
colorManager = [ColorController new];
}
return self;
}
- (void)drawRect:(CGRect)rect {
imgTwitterIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"imgTwitterBird"]];
CGRect twitterIconFrame = [imgTwitterIcon frame];
twitterIconFrame.origin.x = 50.0;
twitterIconFrame.origin.y = 20.0;
tblTweets = [[UITableView alloc] initWithFrame:CGRectMake(50.0, 25.0, 220.0, 500.0)];
tblTweets.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
tblTweets.separatorColor = [colorManager setColor:176.0:196.0:222.0];
tblTweets.layer.borderWidth = 1.0;
tblTweets.rowHeight = 20.0;
tblTweets.scrollEnabled = YES;
tblTweets.delegate.self;
tblTweets.dataSource.self;
UIImage* imgCloseButton = [UIImage imageNamed:#"btnCloseWindow.png"];
CGSize imageSize = imgCloseButton.size;
btnCloseView = [[UIButton alloc] initWithFrame: CGRectMake(220.0, 550.0, imageSize.width, imageSize.height)];
[btnCloseView setImage:[UIImage imageNamed:#"btnCloseWindow.png"] forState:UIControlStateNormal];
[btnCloseView addTarget:self action:#selector(closeWin:) forControlEvents:UIControlEventTouchUpInside];
[self getTweets];
[self addSubview:tblTweets];
[self addSubview:imgTwitterIcon];
[self addSubview:btnCloseView];
}
- (void) getTweets {
//array to hold tweets
tweetsArray = [[NSMutableArray alloc] init];
///set up a NSURL to the twitter API
NSURL* twitterAPI = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=%#&count=10", twitterID]];
//get last 10 tweets (max is 20)
TWRequest *twitterRequest = [[TWRequest alloc] initWithURL:twitterAPI
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *tweetsDict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
for(NSDictionary* thisTweetDict in tweetsDict) {
[tweetsArray addObject:[thisTweetDict objectForKey:#"text"]];
}
[tblTweets reloadData];
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}
#pragma mark Table Management
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [tweetsArray count];
NSLog(#"%i", [tweetsArray count]);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tweetsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"tableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.textColor = [UIColor colorWithRed:66.0/255.0 green:66.0/255.0 blue:66.0/255.0 alpha:1];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size: 13.0];
cell.textLabel.text = [tweetsArray objectAtIndex:indexPath.row];
CGRect cellFrame = [cell frame];
cellFrame.size.height = 25.0;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* thisTweet = [tweetsArray objectAtIndex:indexPath.row];
}
#pragma mark Close Window
- (void) closeWin {
NSMutableDictionary* userData = [[NSMutableDictionary alloc] init];
[userData setObject:#"closeTwitter" forKey:#"theEvent"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"theMessenger" object:self userInfo: userData];
}
#end
drawRect is used to draw stuff inside this views, using drawing functions
You should move your views additions to the layoutSubviews
Instead of - (void)drawRect:(CGRect)rect use - (void)layoutSubviews
This may or may not solve your issues, but nevertheless its the correct approach

Resources