Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Note for the person who downvoted: This question was closed so many days back . If anyone find which is not necessary please leave a comment
I have some textfield values & uiimage stored in one view controller. I have tableview in another view controller . I want store values using nsuserdefaults in tableview and retrieve using nsuserdefaults then want to add rows dynamically as user enters?
Let's say you have an NSMutableArray of this data like this:
NSMutableArray *cellLabelValues = [[NSMutableArray alloc] initWithObjects: #"1",#"2",#"3",nil];
In your tableView delegates do this:
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return cellLabelValues.count;
}
You must have a button or something to receive user's intent to add new cells. Lets assume it calls this method:
-(void) addNewCell:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Enter New Value"
message:#" "
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
And write the delegate of UIAlertView. Make sure you have made your ViewController to be UIAlertViewDelegate:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
NSString *value = [alertView textFieldAtIndex:0].text;
[cellLabelValues addObject:value];
[tableView reloadData];
}
}
What happens here is, user taps new cell button. It takes entry from user. Then it reloads the table after adding it to your array. When it reaches numberOfRowsInSection delegate method, it sees that the array is now incremented by 1. So it will show one extra cell.
You can maintain a Mutable array with strings from textfield.
Then based on the array.count you can get the size of array.
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return array.count
}
and also don't forget to reload table view.
Suppose you have two UIViewControllers ViewController1 with UITextFields and ViewController2 with UITableView
Now in ViewController2 declare an NSMutableArray *dataArray;
and add record in it from ViewController1 before moving to ViewController2
In ViewController2
use this function
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return dataArray.count;
}
It will help.
Related
I have method called
- (void)redeemOfferService
{
// in this method i want access OffersBoughtCellTableViewCell,
how to access tableview cell here ?
// want to update selected tableview cell values
// here i am getting selected cell details in selectedOfferBoughtObj which
is actually NSObject in that i am having five string values
i want show that values in my tableview cell how can i ?
//
}
The above method is calling from
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex
{
if(alertView.tag == 10)
{
if(buttonIndex == 0)
{
[self redeemOfferService];
}
}
}
and this method is calling when i tap on tableview cell i.e.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *logoutAlert = [[UIAlertView alloc]initWithTitle:#"Are you sure you want to redeem?" message:nil delegate:self cancelButtonTitle:#"Yes" otherButtonTitles:#"No", nil];
logoutAlert.tag = 10;
[logoutAlert show];
}
i know there is way, we can send sender from button click but i want in above scenario.
Use a global variable in your class NSIndexPath type and on selected store your selected indexpath
NSIndexPath *selectedIndexPath; //declare it as a global
After assign selected value in didSelect
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
UIAlertView *logoutAlert = [[UIAlertView alloc]initWithTitle:#"Are you sure you want to redeem?" message:nil delegate:self cancelButtonTitle:#"Yes" otherButtonTitles:#"No", nil];
logoutAlert.tag = 10;
[logoutAlert show];
selectedIndexPath = indexPath;
}
And change like this in your function
- (void)redeemOfferService
{
OffersBoughtCellTableViewCell * _selectedCell = [offersTableView cellForRowAtIndexPath:selectedIndexPath]; //Now Its your selected cell Try this .
}
It will work fine try once and revert back
You are surely updating the tableview from some NSMutableArray, meaning you are filling up your tableview with this array.
In your redeemOfferService method, change the value of that Object inside the NSMutableArray with which you are filling up the tableview.
Then call [self.tableviewName reloadData]
You can use the indexPathForSelectedRow property of UITableView to access selected indexPath.
- (void)redeemOfferService
{
OffersBoughtCellTableViewCell *selectedCell = (OffersBoughtCellTableViewCell *)[tableViewObject cellForRowAtIndexPath:offersTableView.indexPathForSelectedRow];
}
This gives you the selected OffersBoughtCellTableViewCell
Using the following delegate method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PLOTCheckinTableViewCell *cell = (PLOTCheckinTableViewCell *)[self.checkinsTableView dequeueReusableCellWithIdentifier:CheckinCellIdentifier forIndexPath:indexPath];
[cell setSwipeGestureWithView:crossView color:redColor mode:MCSwipeTableViewCellModeSwitch state:MCSwipeTableViewCellState2 completionBlock:^(MCSwipeTableViewCell *cell, MCSwipeTableViewCellState state, MCSwipeTableViewCellMode mode) {
self.indexPathToDelete = [tableView indexPathForCell:cell];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Delete?"
message:#"Are you sure your want to remove this checkin?"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
[alertView show];
}];
}
Then inside the UIAlertView delegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
// No
if (buttonIndex == 0) {
}
// Yes
else {
PLOTCheckinTableViewCell *cell = (PLOTCheckinTableViewCell *)[self.checkinsTableView cellForRowAtIndexPath:self.indexPathToDelete];
[self.checkins removeObjectAtIndex:self.indexPathToDelete.row];
[self.checkinsTableView deleteRowsAtIndexPaths:#[self.indexPathToDelete] withRowAnimation:UITableViewRowAnimationFade];
self.indexPathToDelete = nil;
}
}
However, whenever I hit "Ok" in the alert view, the cell that's deleted is always the last one in the tableview, ie. not the cell the user actually swiped.
Is it something to do with the dequeuing?
Yes. You should not be referencing to your cell. Instead, try to reference to the actual object that caused the cell to exist (i.e. if this is a list of messages, the message that is displayed within that cell).
The cell object is being reused and the UIAlertView wont know about that. Even if you have 1000 items in your list, you are not going to have more than 20 cells. They are always going to be reused thorough your table view scrolling.
You should be looking into removing an element from your data source array instead of removing the cell itself. After removing the element, you can always reload your table view to visually reflect the elemnt removed state.
I have a fitness plan page with an app which is a UITableViewController with multiple custom uitableviewcells. It relies on a reasnably large data feed - I'd like to show a loader when accessing this page whilst the data feed is being pulled back from the server.
I have setup a custom uiTableviewCell containg a styled loader message / activity indicator and would like to show this on load - then when the data is available - refresh the tableview and deque the data into the relevant cells.
Currently I have the following method in my viewdidload method, which currently shows an alert if the feed hasn't completed its load-
[[RKObjectManager sharedManager].HTTPClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
if(status == AFNetworkReachabilityStatusNotReachable)
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:nil
message:#"There is no network connection!"
delegate:nil
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil];
[alert show];
}
else
{
i'd like to alter this to show the loader cell instead - then refresh the view once the data load is complete -
I've altered to the following -
[[RKObjectManager sharedManager].HTTPClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
if(status == AFNetworkReachabilityStatusNotReachable)
{
_WoHpTV.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
workoutBannerCell *cell = [_WoHpTV
dequeueReusableCellWithIdentifier:#"loaderCell" ];
}
else
{
so i've got a refernce to the custom cell in the above - but my question is how do I add it to my TableView?
i've got a refernce to the custom cell in the above - but my question
is how do I add it to my TableView?
You need to implement datasource methods of UITableView. Since you want to show loading indicators in each of the table cell you would need a temp data (You cannot load 0 cells in table view even to show loader you need some visible cells). In view did load create an array of temp objects and call reloadData of tableview.
for(int i = 0; i < 5; i++) {
[_dataArray addObject:#{#"text":#"text_value"}];
_isDataLoaded = NO;
[_table reloadData];
Now this will populate your table with Temp data. Once HTTP call is done set that BOOL isDataLoaded to YES
Then in Data Source methods -
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (!_isDataLoaded)
return _dataArray.count; // No data return count for Temp Data
else
return _feedArray.count; // Return correct feed items count
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCustomCell *cell = [_tableView dequeueReusableCellWithIdentifier:#"cell_id"];
if (cell == nil)
// Initialise cell here
if (!_isDataLoaded) { // Data has not yet loaded. Set loaders
NSDictionary *data = [_dataArray objectAtIndex:indexPath.row];
// set Cell properties here
} else {
// Fetch data from feed array
}
}
And in your question you are trying to detect if feed is loaded or not based on AFNetworkReachabilityStatusNotReachable. Which is actually incorrect, as this state indicates no internet connection. To track availability of data a simple BOOL as shown above will do.
I have UITableViewController which pop UIActionSheet when user click on a cell with accessoryType =UITableViewCellAccessoryDetailDisclosureButton;
Now the method -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { works fine, except, i dont know in which cell user clicked.
I could , for example, declare a property where I save selected cell in didSelectRowAtIndexPath:(NSIndexPath *)indexPath { but I think there must be a better way.
I usually set the action sheet's tag to be the index path's row, but that only works if you don't care about the section number. If you do need the section as well, creating a property would be the best way to go about it.
You could also mess with a category and associated objects, but for me personally that would be too involved.
If your table only have one section, you could store which row presented the action sheet in the tag, something like this.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
NSString *title = [NSString stringWithFormat:#"Sheet for row %i", indexPath.row];
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:#"Option 1", #"Option 2", nil];
[sheet setTag:indexPath.row];
[sheet showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
int row = actionSheet.tag;
NSLog(#"Selected actionSheet buttonIndex %i for row: %i", buttonIndex, row);
}
It's probably the easiest way, but I wouldn't say it's the best way to do it.
Implement this UITableView delegate method to get the index path of the cell when the accessory button is tapped:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
}
I have a standard CoreData/NSFetchedResultsController/UITableView setup. There is no edit button on top, but right-swiping a row will reveal the delete button. If the delete button pressed, I want to pop up a UIActionSheet to confirm the deletion.
Before the UIActionSheet, I just implemented tableView:commitEditingStyle:forRowAtIndexPath: and in it, I called deleteObject: on the managedObjectContext for the indexPath and let the FetchedResultsController overrides handle the visual aspect of it.
Now, I have tableView:commitEditingStyoe:forRowAtIndexPath: create the UIActionSheet and show it. I implemented actionSheet:clickedButtonAtIndex: and put the deleteObject: in the case where the delete button is pressed. The problem is that I need the indexPath of the item to delete and it is no longer in scope.
Do I...
A) delete the ManagedObject in tableView:commitEditingStyle:forRowAtIndexPath: and either save or roll back in actionSheet:clickedButtonAtIndex: ?
B) store the index path as a property so I can set it in tableView:commitEditingStyle:forRowAtIndexPath: and read it in actionSheet:clickedButtonAtIndex:?
C) something else...
Option A seems like more overhead than necessary. Either way it will be deleted, just sometimes it will be rolled back.
Option B seems very hawkish. An external value like that doesn't seem to fit the object oriented model very well.
Is there a generic object in UIActionsSheet for passing in values like this? Or is there something else I'm missing?
I needed a similar solution. I solved this by creating an ivar NSIndexPath * currentPath; and used the following idea for tableView:commitEditingStyle:forRowAtIndexPath:
- (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView * alert;
UITableViewCell * cell;
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// save current indexPath
[currentPath release];
currentPath = [indexPath retain];
// display warning
alert = [[UIAlertView alloc] initWithTitle:#"Really?"
message:#"Are you really really sure you want to delete this item?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Delete", nil];
[alert show];
[alert release];
// clear delete confirmation from table view cell
cell = [tableView cellForRowAtIndexPath:indexPath];
[cell setEditing:NO animated:NO];
[cell setEditing:YES animated:YES];
};
return;
}
If the user taps the delete button, I then remove the row from the UITableViewCell and remove the entry from the data source. If they tap cancel, I simply ignore the action.
Instead of the indexPath I would store the managed object itself in a property in the -tableView:commitEditingStyle:forRowAtIndexPath: method:
self.deleteCandidate = [self.controller objectAtIndexPath:indexPath]
and then delete that object (or not) in -actionSheet:clickedButtonAtIndex:, and set self.deleteCandidate = nil in either case.
The reason is that the fetched results controller objects might change between those two methods being called.
Another option is to use "Associative References" (objc_setAssociatedObject, objc_getAssociatedObject) to store a reference from the UIActionSheet to the object in question.