I am trying to use refreshControl doing everything by Code the problem appears when I pull the tableView and I call the server. It tells me this error :
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 6 beyond bounds for empty array'
When I run this simple application I watch the data in the table view. I don't know why I have this problem.
Here is the code:
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) NSMutableArray * data;
#property (nonatomic, strong) UIRefreshControl *spinner ;
#end
#implementation YPProjectListViewController
#synthesize tableView;
#synthesize data;
#synthesize spinner;
- (void)viewDidLoad {
[super viewDidLoad];
spinner = [[UIRefreshControl alloc]initWithFrame:CGRectMake(130, 10, 40, 40)];
[self loadProjectsFromService];
[spinner addTarget:self action:#selector(loadProjectsFromService) forControlEvents:UIControlEventValueChanged];
[tableView addSubview:spinner];
}
-(void)loadProjectsFromService{
[spinner beginRefreshing];
self.data = [[NSMutableArray alloc] init];
[self.view addSubview:self.tableView];
__weak typeof(self) weakSelf = self;
successBlock = ^(NSMutableArray *newData) {
if ([newData count] > 0) {
[weakSelf refreshData:newData];
}
};
[spinner endRefreshing];
[ypNetManager getProjectListWithSuccessBlock:successBlock error:NULL];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Custom getter
- (UITableView *)tableView {
//custom init of the tableview
if (!tableView) {
// regular table view
tableView = [[UITableView alloc] initWithFrame:UIEdgeInsetsInsetRect(self.view.bounds, tableViewInsets) style:UITableViewStylePlain];
tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
tableView.delegate = self;
tableView.dataSource = self;
tableView.backgroundColor = [UIColor clearColor];
return tableView;
}
return tableView;
}
#pragma mark - Private methods
- (void)refreshData:(NSMutableArray *)newData {
NSLog(#"data %#", newData);
self.data = newData;
[self.tableView reloadData];
}
I don't think there is anything wrong with your fetching data from server. The only thing you might be doing incorrectly is not to refresh the tableView when you reinitialize self.data.
When you pull down and release table view needs to display the 6th tableView cell which went out of viewport and your cell needs 6th object from your data but your data is not present anymore.
just insert the following.
-(void)loadProjectsFromService{
[spinner beginRefreshing];
self.data = [[NSMutableArray alloc] init];
[self.tableView reloadData]; //Insert table reload here.
//... rest of your code ...
}
Related
I am new to ios programming, and I am trying to write a view controller that will display a question (via a label) at the top of the view and then a list of answers in a tableview subview below. The view is set up with interface builder, but I add the tableview programmatically.
I am able to load the data from a JSON source and print it out with a swipe gesture, but the data cannot be accessed inside my table view. I know from putting NSLog's that the numberOfRowsInSection runs once at the beginning to return 0 but does not run again when I invoke [self.tableView reloadData], which means the table still thinks it has 0 rows even though it should have about 20. I do set the UIViewController as the table view delegate and data source. What else do I need to do?
MAIN QUESTION: How can I access the view controller's NSMutablearray property inside my table view functions when that table view is a subview of my view controller? Thank you!
Here's my initial declarations and setup:
#interface BNRJudgeViewController () <UITextFieldDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate, UITableViewDataSource, UITableViewDelegate >
#property (nonatomic, strong) NSURLSession *session;
#property (weak, nonatomic) IBOutlet UILabel *question;
#property (weak, nonatomic) UITableView *tableView;
#property (nonatomic) NSMutableArray *answerArray;
#end
#implementation BNRJudgeViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if ([self isKindOfClass:[UIViewController class]]) {
if(self){
// Custom initialization
self.title=#"Judge";
self.navigationController.navigationItem.title = #"Judge";
self.answerArray = [[NSMutableArray alloc] init];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil];
CGRect frame = CGRectMake(61, 252, 200, 225);
UITableView *tableView = [[UITableView alloc] initWithFrame:frame];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
}
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if ([self isKindOfClass:[UIViewController class]]) {
[self fetchFeed];
}
UISwipeGestureRecognizer *rightSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
rightSwipe.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:rightSwipe];
UISwipeGestureRecognizer *leftSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft:)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
leftSwipe.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:leftSwipe];
}
Here's where I fetch the JSON data and assign it to an NSMutableArray property of my view controller:
- (void)fetchFeed
{
NSString *requestString = #"http://wsomeurl";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask =
[self.session dataTaskWithRequest:req completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error){
NSMutableArray *jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
self.answerArray = jsonObject;
// NSLog(#"%#", self.answerArray);
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
[self.tableView reloadData];
[dataTask resume];
[self.tableView reloadData];
}
Here are my tableview required functions, implemented in my view controller:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"recent integer count is %d", [self.answerArray count]);
return [self.answerArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
// NSDictionary *cellD = self.answerArray[indexPath.row];
NSLog(#"%#", self.answerArray);
NSLog(#"hi hi!");
// NSLog(#"%#", [cellD objectForKey:#"username"]);
// cell.textLabel.text = [cellD objectForKey:#"username"];
return cell;
}
And finally here are some swipe functions showing that those functions can see the array - it's just the table view functions that aren't.
- (void)swipeRight:(UISwipeGestureRecognizer *) gr
{
NSLog(#"right swipe worked");
NSLog(#"right swipe array count is %d", [self.answerArray count]);
}
- (void)swipeLeft:(UISwipeGestureRecognizer *) gr
{
NSLog(#"left swipe worked");
NSLog(#"left swipe array count is %d", [self.answerArray count]);
}
Sorry for the long post. Again, MAIN QUESTION: How can I access the view controller's NSMutablearray property inside my table view functions? Thank you!
Extra technique related questions/comments...I recoded this making a custom tableviewcontroller class to load this data and have the right size and location and then initialize this tableview controller class within my view controller and put its view as a subview. But I don't want to be passing data between two view controllers because I'd like to update both the view and the subview with a swipe on the view as cleanly as possible...but might this be the better way to go?
Two related technique questions as well. First would it make more sense to stuff this information into a singleton class that I can access from any view controller? Second, would it make more sense to write some protocol (haven't done this, just know of it) to pass the information force reload in the right place?) As a newbie, I see both of these as sloppier than just sticking with one view controller as I'm trying to do, but I might just not understand objective c very well yet. Thanks in advance.
You have UITableView *tableView = [[UITableView alloc] initWithFrame:frame]; in your init method, so tableView is a local variable. Elsewhere you have [self.tableView reloadData], but you've never assigned your property to the table view, so self.tableView is nil. You should change the code in your init method to,
_tableView = [[UITableView alloc] initWithFrame:frame];
_tableView.delegate = self;
_tableView.dataSource = self;
[self.view addSubview:_tableView];
I've implemented UISearchControl (iOS8 version which is slightly different then previous ones). It seems to be firing correctly when I type stuff in according to the NSLog statement seen below, only issue is it the UITableView actually never gets updated, and I added a NSLog to the } else { part of the numberOfRowsInSection to confirm that it's not called like so:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.tableView) {
return self.objects.count;
} else {
// NOT BEING FIRED WHEN STUFF IS TYPED IN SEARCH BAR?
NSLog(#"Search Results Returned in TableView");
return self.searchResults.count;
}
}
Although these methods are firing fine...and updating the searchResults array correctly according to the NSLog added in the updateFilter method:
#pragma mark - UISearchResultsUpdating
-(void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = [self.searchController.searchBar text];
[self updateFilteredContentForSaleName:searchString];
// ASSUMING THIS IS WHAT CAUSES TABLEVIEW TO REFRESH, BUT ISNT REFRESHING IT WITH NEW ARRAY?
[((UITableViewController *)self.searchController.searchResultsController).tableView reloadData];
}
#pragma mark - Content Filtering
- (void)updateFilteredContentForSaleName:(NSString *)saleName {
[self.searchResults removeAllObjects];
for (PFObject *sale in self.objects)
{
NSString *saleTitle = [sale objectForKey:#"name"];
if ([[saleTitle lowercaseString] hasPrefix:[saleName lowercaseString]])
{
[self.searchResults addObject:sale];
}
}
// THIS LOG SHOWS SEARCH RESULTS CORRECTLY HOW THEY SHOULD BE, JUST NO UPDATE TO UITABLEVIEW
NSLog(#"%#", self.searchResults);
}
But simply no update to the tableview...
Any idea why this is? Am I calling the refresh wrong here?:
[((UITableViewController *)self.searchController.searchResultsController).tableView reloadData];
I've tried PFQueryTableViewController * too since that's essentially what I'm using for actual view controller, but no luck.
EDIT
Here is the code used to create the UISearchControl
#interface LocalSalesViewController () <UISearchResultsUpdating>
#property (nonatomic, strong) UISearchController *searchController;
#property (nonatomic, strong) NSMutableArray *searchResults; // Filtered search results
#end
#implementation LocalSalesViewController
- (id)initWithCoder:(NSCoder *)aCoder {
self = [super initWithCoder:aCoder];
if (self) {
self.parseClassName = #"Sales";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = YES;
self.objectsPerPage = 25;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.searchResults = [NSMutableArray array];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.tableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
}
I'm trying to create a table but none of the data I inputted is displaying when I run the simulator. I'm trying to create a simple address book application and So far, here is what I did:
From the empty story board, I added a View Controller from the Object Library then inside the view controller, I added a Table View. Then I embedded the View Controller inside a Navigation Controller. I also added another View Controller in the end to act as a "Details" View.
Inside my viewController.h I added the following code:
#property (strong, nonatomic) NSArray *contact;
#property (strong, nonatomic) NSArray *contactDetails;
#property (nonatomic) NSInteger selectedIndex;
contact is to act as the array that shows all the contacts within the phonebook (This is what I'm having trouble displaying)
contactDetails shows once a user selects a contact.
selectedIndex is my way of telling the application which contact has been selected.
Inside my viewController.m I added the following code:
#import "HWViewController.h"
#interface HWViewController ()
#end
#implementation HWViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.tableView registerClass: [UITableViewCell class] forCellReuseIdentifier:#"Cell"];
self.contact = [[NSArray alloc] initWithArray: [NSArray arrayWithObjects:#"Joe", #"Simon", nil]];
self.contactDetails = [[NSArray alloc] initWithArray: [NSArray arrayWithObjects: #"+689171898057", #"+689173104153", nil]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (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 self.contact.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
if(cell==nil){
cell = [[[NSBundle mainBundle] loadNibNamed:#"SampleCell" owner:nil options:nil] objectAtIndex:0];
}
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 100, 30)];
label.text = [self.contact objectAtIndex:indexPath.row];
[cell.contentView addSubview:label];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
self.selectedIndex = indexPath.row;
[self performSegueWithIdentifier:#"TranslationSegue" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
UIViewController *vc = [segue destinationViewController];
UILabel *details = [[UILabel alloc] initWithFrame:CGRectMake(10, 80, 250, 32)];
details.text = [self.contactDetails objectAtIndex:((HWViewController*)sender).selectedIndex];
[vc.view addSubview:details];
}
#end
After that, I ran the simulation and I get nothing showing up on the table.
you have no cell in the tableview. so add tableview cell in your storyboard
http://www.appcoda.com/customize-table-view-cells-for-uitableview/
Add this in your viewController.h :
#property(nonatomic, strong) IBOUTLET UITableView * TableView;
And then link this outlet to your tableview and then try it out.
And there is no cell in your table view because the prototype cell will be set to zero by default. Now select the tableview go to attribute inspector and set the prototype cell to 1 and then try to run your program with proper cell identifier it will work.
HTH :)
Set tableView delegate and DataSource protocol in you viewdidload method.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.tableView registerClass: [UITableViewCell class] forCellReuseIdentifier:#"Cell"];
self.tableview.delegate = self;
self.tableview.dataSource = self;
self.contact = [[NSArray alloc] initWithArray: [NSArray arrayWithObjects:#"Joe", #"Simon", nil]];
self.contactDetails = [[NSArray alloc] initWithArray: [NSArray arrayWithObjects: #"+689171898057", #"+689173104153", nil]];
}
The purpose is to implement a fixed search bar just like Contacts in iOS7.
I have a view controller called SearchViewController inherited from UIViewController.
And I add a searchBar and a tableView as its navigationController.view's subView.
But since searchBar and tableView are separated, when I start to search, no dim effect on tableView and result table view is shown in correctly.
I just want it behaves just like Contacts app.
Here is my code:
SearchViewController.h
#import <UIKit/UIKit.h>
#class UWTabBarController;
#class InfoSessionModel;
#interface SearchViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
SearchViewController.m
#import "SearchViewController.h"
#interface SearchViewController ()
#property (nonatomic, strong) UISearchBar *searchBar;
#property (nonatomic, strong) UISearchDisplayController *searchController;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) NSArray *data;
#end
#implementation SearchViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initiate search bar
NSInteger statusBarHeight = 20;
NSInteger navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, statusBarHeight + navigationBarHeight, 320, 44)];
// _searchBar.tintColor = [UIColor clearColor];
_searchBar.delegate = self;
_searchBar.barStyle = UIBarStyleDefault;
//NSMutableArray *scopeTitles = [[NSMutableArray alloc] initWithObjects:#"Employer", #"Program", #"Note", nil];
_searchBar.scopeButtonTitles = [[NSArray alloc] initWithObjects:#"Employer", #"Program", #"Note", nil];//[#"Employer|Program|Note" componentsSeparatedByString:#"|"];
// initiate search bar controller
_searchController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
_searchController.delegate = self;
_searchController.searchResultsDataSource = self;
_searchController.searchResultsDelegate = self;
// initiate table view
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, statusBarHeight + navigationBarHeight, 320, [UIScreen mainScreen].bounds.size.height - statusBarHeight - navigationBarHeight)];
[_tableView setContentInset:UIEdgeInsetsMake(_searchBar.frame.size.height, 0, _tabBarController.tabBar.frame.size.height, 0)];
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass:[InfoSessionCell class] forCellReuseIdentifier:#"InfoSessionCell"];
[_tableView registerClass:[LoadingCell class] forCellReuseIdentifier:#"LoadingCell"];
[self.navigationController.view addSubview:_tableView];
[self.navigationController.view addSubview:_searchBar];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (_searchController.searchResultsTableView == tableView) {
return 1;
}
else {
return [data count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (_searchController.searchResultsTableView == tableView) {
static NSString *cellIdentifier = #"LoadingCell";
LoadingCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[LoadingCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.loadingLabel.text = #"Test cell for search result";
return cell;
}
else {
//... configure cell and return cell
return cell;
}
}
}
#pragma mark - UISearchDisplayController Delegate Methods
// hasn't been implemented
#pragma mark - UISearchBar Delegate Methods
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
//move the search bar up to the correct location
[UIView animateWithDuration:.3
animations:^{
searchBar.frame = CGRectMake(searchBar.frame.origin.x,
20,// status bar's height
searchBar.frame.size.width,
searchBar.frame.size.height);
}
completion:^(BOOL finished){
//whatever else you may need to do
}];
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
//move the search bar down to the correct location
[UIView animateWithDuration:.25
animations:^{
NSInteger statusBarHeight = 20;
NSInteger navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
searchBar.frame = CGRectMake(_searchBar.frame.origin.x,
statusBarHeight + navigationBarHeight,
_searchBar.frame.size.width,
_searchBar.frame.size.height);
}
completion:^(BOOL finished){
//whatever else you may need to do
}];
return YES;
}
This is the effects of my code:
All right, my problem is caused by my misunderstanding of views and navigationController's views.
In view did load method:
before is:
[self.navigationController.view addSubview:_tableView];
[self.navigationController.view addSubview:_searchBar];
but should be:
[self.view addSubview:_tableView];
[self.view addSubview:_searchBar];
In this way, the original table view and result table view will show correctly.
And other things are moving search bar up and down, these things should be done through UISearchBar delegate protocol methods and UISearchDisplayController delegate protocol methods.
This is a right way to implement a fixed searchBar and tableView bellow it.
Currently I have custom UITablViewCell's (BIDSelectBusinessCustomCell) that are displayed in a tableView (myTableView). The custom cell is made up of a UIImageView and a label. When the view loads the labels are populated with the strings from my model. UIImageViews are blank. I want to be able for a user to 'tap' the UIImageView, select a picture from what is stored on their phone and for that image to be saved to the UIImageView.
From the below code I can get the 'tap' gesture, then the pickercontroller pops up and a user selects an image. The way the code is now one image that is selected is set for all of the UIImageViews. Which is understandable. But I want it to be set to that particular UIImageView and don't know how to.
Code:
#import <UIKit/UIKit.h>
#interface BIDBusinessSelectViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UIGestureRecognizerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (weak, nonatomic) IBOutlet UITableView *myTableView;
#property (strong, nonatomic) NSArray *linkedBusinessParseArray;
//Stores the array of models
#property (strong, nonatomic) NSMutableArray *linkedBusinessParseModelArray;
#property NSUInteger relevantIndex;
#property (strong, nonatomic) UIImage *tempImageHolder;
#end
#import "BIDBusinessSelectViewController.h"
#import <Parse/Parse.h>
#import "BIDBusinessModel.h"
#import "BIDSelectBusinessCustomCell.h"
#interface BIDBusinessSelectViewController () <ImageSelect>
{
BIDSelectBusinessCustomCell *aCell;//define a cell of ur custom cell to hold selected cell
UIImage *choosenImage; //image to set the selected image
}
#end
#implementation BIDBusinessSelectViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
self.linkedBusinessParseModelArray = [[NSMutableArray alloc]init];
//create query
PFQuery *linkedBusinessParseQuery = [PFQuery queryWithClassName:#"linkedBusinessParseClass"];
//follow relationship
[linkedBusinessParseQuery whereKey:#"currentBusinessUserParse" equalTo:[PFUser currentUser]];
[linkedBusinessParseQuery whereKey:#"linkRequestSentParse" equalTo:#"Approved"];
[linkedBusinessParseQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
self.linkedBusinessParseArray = objects; //store them in my model array
//loop through model array from Parse
for (NSDictionary *dict in self.linkedBusinessParseArray) {
NSString *descPlaceNameParse = [dict objectForKey:#"placeDescriptionParse"];
NSLog(#"descPlacesNameParse: %#",descPlaceNameParse);
PFObject *tempObj = (PFObject *) dict;
NSString *tempObjString = tempObj.objectId;
NSLog(#"tempObjString (inside dict): %#", tempObjString);
//storing values from Parse into my model
BIDBusinessModel *userModel = [[BIDBusinessModel alloc]init];
userModel.descriptionModelParse = descPlaceNameParse;
userModel.objectIdModelParse = tempObjString;
[self.linkedBusinessParseModelArray addObject:userModel];
NSLog(#"self.linkedBusinessParseModelArray: %lu", (unsigned long)[self.linkedBusinessParseModelArray count]);
//Reload tableview. Has to go here in block otherwise it does not occur
[self.myTableView reloadData];
}
}];
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Device has no camera"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[myAlertView show];
}
choosenImage = [UIImage imageNamed:#"pin.png"]; //hear u need to set the image for cell assuming that u are setting initially same image for all the cell
}
#pragma mark -
#pragma mark Table Delegate Methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.linkedBusinessParseModelArray.count; //returns count of model NSMutableArray
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Start cellforRowStIndex");
static NSString *CellIdentifier = #"Cell";
BIDSelectBusinessCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[BIDSelectBusinessCustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
BIDBusinessModel *bizModel;
bizModel = self.linkedBusinessParseModelArray[indexPath.row];
bizModel.image = choosenImage;
//cell.descLabel.text = [NSString stringWithFormat:#"bid= %d",indexPath.row];//set text from the model//Omitted for my desc
cell.descLabel.text = bizModel.descriptionModelParse;
cell.logoImage.image =bizModel.image; //setting the image initially the image when u set in "viewDidLoad" method from second time onwords it will set from the picker delegate method
//insted of settig the gesture hear set it on the custom cell
cell.ImageSelectDelegate = self; //setting the delegate
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
// hear implementation of delegate method
- (void)selectSetImageForSelectedLogImage:(UIImageView *)logoImgView;
{
//open up the image picker
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
aCell = (BIDSelectBusinessCustomCell *)logoImgView.superview; //her getting the cell
[self presentViewController:picker animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *aChosenImage = info[UIImagePickerControllerEditedImage];
//UIImage holder to transfer to cellForRowAtIndexPath
choosenImage = aChosenImage;
NSIndexPath *indexPath = [self.myTableView indexPathForCell:aCell];
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; //hear reloading the selected cell only not entire tableview
//get the model and set the choosen image
BIDBusinessModel *bizModel;
bizModel = self.linkedBusinessParseModelArray[indexPath.row];
bizModel.image = aChosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
#import <UIKit/UIKit.h>
#protocol ImageSelect<NSObject> //for this u need use custom delegate so i did like this
- (void)selectSetImageForSelectedLogImage:(UIImageView *)logoImgView;
#end
#interface BIDSelectBusinessCustomCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *descLabel;
#property (strong, nonatomic) IBOutlet UIImageView *logoImage;
#property (nonatomic, assign) id<ImageSelect>ImageSelectDelegate; // deleagte
#end
#import "BIDSelectBusinessCustomCell.h"
#implementation BIDSelectBusinessCustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.logoImage = [[UIImageView alloc]init];
self.descLabel = [[UILabel alloc]init];
//set up gesture hear in the custom cell insted in the controller class
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapLogoImage:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
self.logoImage.userInteractionEnabled = YES;
[self.logoImage addGestureRecognizer:tap];
//[self addSubview:logoImage];
//[self addSubview:descLabel];
}
return self;}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)tapLogoImage:(UITapGestureRecognizer *)guesture
{
if([self.ImageSelectDelegate respondsToSelector:#selector(selectSetImageForSelectedLogImage:)])
{
[self.ImageSelectDelegate selectSetImageForSelectedLogImage:self.logoImage];//call the delegate method from the selected cell
}
}
#end
Yup for this, i tried but finally i did something like this, go through this u may find some solution. and hope this helps u :)
//in custom cell "BIDSelectBusinessCustomCell.h"
#import <UIKit/UIKit.h>
//define a delegate method that is called each time when u tapped on cell
#protocol ImageSelect<NSObject> //for this u need use custom delegate so i did like this
- (void)selectSetImageForSelectedLogImage:(UIImageView *)logoImgView;
#end
#interface BIDSelectBusinessCustomCell : UITableViewCell <UIImagePickerControllerDelegate,UINavigationControllerDelegate>
{
UIImageView *logoImage; //your image holder
UILabel *descLabel; //label
}
#property (nonatomic, retain) UIImageView *logoImage;
#property (nonatomic, retain) UILabel *descLabel;
#property (nonatomic, assign) id<ImageSelect>ImageSelectDelegate; // deleagte
#end
//in custom cell "BIDSelectBusinessCustomCell.m"
#import "BIDSelectBusinessCustomCell.h"
#implementation BIDSelectBusinessCustomCell
#synthesize logoImage;
#synthesize descLabel;
#synthesize ImageSelectDelegate;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
logoImage = [[UIImageView alloc]init];
descLabel = [[UILabel alloc]init];
//set up gesture hear in the custom cell insted in the controller class
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapLogoImage:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
logoImage.userInteractionEnabled = YES;
[logoImage addGestureRecognizer:tap];
[self addSubview:logoImage];
[self addSubview:descLabel];
}
return self;
}
- (void)dealloc
{
[logoImage release];
[descLabel release];
[super dealloc];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)layoutSubviews
{
//in this method simply i am setting the frames of subviews
[super layoutSubviews];
self.logoImage.frame = CGRectMake(130, 2, 44,44 );
self.descLabel.frame = CGRectMake(20, 2, 60, 44);
}
- (void)tapLogoImage:(UITapGestureRecognizer *)guesture
{
if([self.ImageSelectDelegate respondsToSelector:#selector(selectSetImageForSelectedLogImage:)])
{
[self.ImageSelectDelegate selectSetImageForSelectedLogImage:self.logoImage];//call the delegate method from the selected cell
}
}
#end
//in your view controller class u need to do something like this ;)
//ViewController.h file
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (retain, nonatomic) IBOutlet UITableView *aTableView;
#property (nonatomic, retain) NSIndexPath *selectedIndexPath; //no need just try
#end
//in your "ViewController.m" file
#interface ViewController ()<UITableViewDataSource, UITableViewDelegate,UITextFieldDelegate,UIImagePickerControllerDelegate,UINavigationControll erDelegate,ImageSelect>//delegate
{
BIDSelectBusinessCustomCell *aCell;//define a cell of ur custom cell to hold selected cell
UIImage *choosenImage; //image to set the selected image
}
- (void)viewDidLoad
{
[super viewDidLoad];
choosenImage = [UIImage imageNamed:#"Star.png"]; //hear u need to set the image for cell assuming that u are setting initially same image for all the cell
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[aTableView release];
[super dealloc];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 4; //pass array check array contains valid objects
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BIDSelectBusinessCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell == nil)
{
cell = [[BIDSelectBusinessCustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
BIDBusinessModel *bizModel;
bizModel = self.linkedBusinessParseModelArray[indexPath.row];
bizModel.image = aChosenImage;
cell.descLabel.text = [NSString stringWithFormat:#"bid= %d",indexPath.row];//set text from the model
cell.logoImage.image =bizModel.image; //setting the image initially the image when u set in "viewDidLoad" method from second time onwords it will set from the picker delegate method
//insted of settig the gesture hear set it on the custom cell
cell.ImageSelectDelegate = self; //setting the delegate
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
// hear implementation of delegate method
- (void)selectSetImageForSelectedLogImage:(UIImageView *)logoImgView;
{
//open up the image picker
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
aCell = (BIDSelectBusinessCustomCell *)logoImgView.superview; //her getting the cell
[self presentViewController:picker animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *aChosenImage = info[UIImagePickerControllerEditedImage];
//UIImage holder to transfer to cellForRowAtIndexPath
choosenImage = aChosenImage;
NSIndexPath *indexPath = [aTableView indexPathForCell:aCell];
[self.aTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; //hear reloading the selected cell only not entire tableview
//get the model and set the choosen image
BIDBusinessModel *bizModel;
bizModel = self.linkedBusinessParseModelArray[indexPath.row];
bizModel.image = aChosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
Yes it is true this would set the image to every row..
Now what you can do is : -
While loading of tableViewCells just assign the tag of UIImageView as the (indexPath.Row).
This would assign unique tags to the ImageView.
You can easily get the tag of that imageView while tapping and now you can assign the image to particular imageView through tagValue of that imageView.
This would assign image to a particular imageView as all have unique tags.
Hope you got the answer of your problem.