Once a user finished entering text in a UITextfield I wand the data to be in a dictionary first and then the dictionary added to array. But for some reason after inserting into array .. It logs null..
.h
#interface Bread_TableViewController : UITableViewController <UITextFieldDelegate>
{
NSMutableArray * inventoryarray;
}
**.m**
- (void)textFieldDidEndEditing:(UITextField *)textField
{
// Make sure to set the label to have a ta
NSString*textfieldclicked;
if (textField.tag == 1) {
textfieldclicked=#"Unit";
} else if (textField.tag ==2) {
textfieldclicked=#"Case";
}
id textFieldSuper = textField;
while (![textFieldSuper isKindOfClass:[UITableViewCell class]]) {
textFieldSuper = [textFieldSuper superview];
}
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)textFieldSuper];
InventoryTableViewCell *cell = (InventoryTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
NSMutableDictionary * productinfo = [[NSMutableDictionary alloc] init];
[productinfo setObject:cell.product.text forKey:#"product"];
[productinfo setObject:textField.text forKey:textfieldclicked];
NSLog(#"productin %#", productinfo);
[inventoryarray addObject: productinfo];
}
-(IBAction)save{
NSLog(#"array %#", inventoryarray);
}
The non-visible cells do not actually exist. Only the visible ones plus one outside the screen at each end are actually in memory. The other ones are created when you scroll and their data is pulled from the data source.
As soon as a cell is pushed out of the screen (+1 cell) it will be removed from the hierarchy and added to the reuse pool.
TL;DR: You can't loop through out-of-screen cells since they don't exist. If you want to access the data for each item, do it in your data source.
alloc-init the array in which you want to add your objects.
do alloc-init of your dictionary outside the textFieldDidEndEditing method and where it scope it visible might be in viewDidLoad
like
#interface yourViewController ()
#property (strong, nonatomic) NSMutableDictionary * product info;
- (void)viewDidLoad {
self.productinfo = [[NSMutableDictionary alloc] init];
}
Related
I have an NSMutableDictionary with a specific key and value. This dictionary is inside an NSMutableArray. I want to update the dictionary with a specific key which is at a certain index inside the array. I want to find the index of this dictionary object. Currently, my dictionary is at index 0 and my editingIndexPath is 1 which is of NSIndexPath type, so editingIndexPath.row doesn't help me.
My code is as follows:
//UpdatedDateAndTime is the NSMutableArray.
//selectedDay is a NSString object.
//dateKeySelected is also a string key.
[[updatedDateAndTime objectAtIndex:editingIndexPath.row] setObject:selectedDay forKey:dateKeySelected];
My problem is that I want to get the right index of the dictionary that is found.
The answer used to be a for loop with a counter, but you're in luck: NSArray has a new method, indexOfObject:, which should do the trick just fine:
NSUInteger i = [myArray indexOfObject:#{myKey:myValue}];
Swift: index(of:)
If your array contains just one special NSMutableDictionary then use below code. I didn't test it but the idea is to search NSMutableDictionary class in the array. And you have to do this search in indexPath which equals to the cell that you want to assign some data.
#interface ViewController (){
NSMutableArray *array;
NSMutableDictionary *dictionary;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (indexPath.row == 1) {
for (int i = 0; i < array.count; i++) {
if ([updatedDateAndTime[i] objectForKey:#"open_house_updated_date"] == selectedDay) {
NSLog(#"%i th index contains NSMutableDictionary that you want",i);
//do whatever needed
break;
}
}
}
else{
//define other cells which doesn't contain NSMutableDictionary
}
return cell;
}
#end
I hope this is what you are looking for.
Working on a small iOS app, and I made a custom tableview cell (and its own class) for my UITableView. Two of the things on the cell are "Add" and "Remove" button. When these are clicked, I need to update an array object that is in the UITableView, but because the table cell is a separate class, how can I send those changes over to the UITableView class?
For example, the code below is for my "remove" button on the cell:
- (IBAction)decrementItem:(id)sender {
int count = (int)[self.specificItemCount.text integerValue];
//Cannot have negative amount of food
if(count == 0) {
return;
} else {
count--;
self.specificItemCount.text = [NSString stringWithFormat:#"%i",count];
}
But I need to update my array object in my table view when that button is clicked, how can I do that?
Define a protocol on your cell class that your tableview class will implement. Here's an example: http://www.tutorialspoint.com/ios/ios_delegates.htm. Then set your tableview as a delegate on the cell (make sure to use a weak reference).
Use delegate or block.
If you only have one cell to operate, I recommend you use a block.
Define block, call when needed
// CustomCell.h
#interface CustomCell : UITableViewCell
#property (nonatomic, copy) void(^addBlock)(NSString *text);
#property (nonatomic, copy) void(^removeBlock)(NSString *text);
#end
// CustomCell.m
- (IBAction)decrementItem:(id)sender {
int count = (int)[self.specificItemCount.text integerValue];
//Cannot have negative amount of food
if(count == 0) {
return;
} else {
count--;
self.specificItemCount.text = [NSString stringWithFormat:#"%i",count];
}
if (removeBlock) {
removeBlock(self.specificItemCount.text)
}
}
Write the operation you need inside
// VC.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath == customIndexPath) {
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:customIdentifier forIndexPath:indexPath];
__weak typeof(self)weakSelf = self;
cell.removeBlock = ^(NSString *text) {
__strong typeof(weakSelf)strongSelf = weakSelf;
// operation
};
cell.addBlock = ^(NSString *text) {
__strong typeof(weakSelf)strongSelf = weakSelf;
// operation
};
return customCell;
}
// ······
}
My app is currently generating random numbers (see code below). What I want is to save that number once the user hits the "Save" button and show it on a table view.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.clickyButton setTitle:#"Generate" forState:UIControlStateNormal];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)handleButtonClick:(id)sender {
// Generates numbers 1 to 49, without creating duplicate numbers.
NSMutableSet * numberSet = [NSMutableSet setWithCapacity:5];
while ([numberSet count] < 7 ) {
NSNumber * randomNumber = [NSNumber numberWithInt:(arc4random() % 49 + 1)];
[numberSet addObject:randomNumber];
}
NSArray * numbers = [numberSet allObjects];
self.n1.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:0]];
self.n2.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:2]];
self.n3.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:3]];
self.n4.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:4]];
self.n5.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:5]];
self.n6.text = [NSString stringWithFormat:#"%#", [numbers objectAtIndex:6]];
}
#end
Please explain me how I can save it on a table view. xcode beginner.
You should create a variable that's accessible within the scope of the whole class rather than just the specific -handleButtonClick: method, and then add the generated numbers to that variable - an array, set, etc...
From there, you can implement the table view to read the values from the variable via var[indexPath.row] (assuming it's an array), and display it. You will need to call [tableView reloadData]; once the array has been filled with objects to make sure that the tableview displays the data.
create a NSMutableArray for UITableViewDataSource and cache the number.
when a number created by the user,add this number into NSMutableArray.
reload UITableView and show all numbers.
If you use only one number you should think about displaying it in another UI element, preferably a UILabel I would say.
If you want to use a UITableView you will either have to create it with static cells (e.g. in a Storyboard) or configure the data source and delegate object for it (which doesn't really seem what you want right now, unless maybe if you wanted to display multiple random numbers in a list...)
Before anything you should make the array numbers as a variable. In that way it is much easier than creating n1,n2,n3,.... I will show you how to solve your problem based on an existing numbers NSArray variable defined.
You need to implement the UITableView delegates in your header file. So let's suppose this is your header file after implementing the delegates:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
Then take your tableview (IBOutlet or programatically) and set the dataSource and delegate in the implementation file. You should do this in the viewDidLoad: method like this:
[_tableView setDelegate:self];
[_tableView setDataSource:self];
After you have done this you need to implement the delegate methods for the UITableView. This ones:
This method will tell the Table View how many rows it needs to show. In your case is the size of the NSArray called numbers:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return numbers.count;
}
This method will tell the Table View what to show on each cell (DON'T FORGET TO ASSING THE CELL IDENTIFIER OF THE CELL IN THE INTERFACE BUILDER TO "Cell")
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [numbers objectAtIndex:indexPath.row];
return cell;
}
Use this method if you want to do something when the user touches a cell in the table view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
Finally to add numbers to the list as the user touches the button you just need to add these lines of code to your method triggered by the button:
- (IBAction)handleButtonClick:(id)sender {
// Generates numbers 1 to 49, without creating duplicate numbers.
NSMutableSet * numberSet = [NSMutableSet setWithCapacity:5];
while ([numberSet count] < 7 ) {
NSNumber * randomNumber = [NSNumber numberWithInt:(arc4random() % 49 + 1)];
[numberSet addObject:randomNumber];
}
//In case you want to delete previous numbers
[numbers removeAllObjects];
numbers = [numberSet allObjects];
[_tableView reloadData];
}
UITableView data disappears on touch, as per screen shots below
The data loads correctly when the view is first loaded, like so.
On touching the screen and then releasing, the data disappears. (If I touch and hold, the data is still present.)
I set a breakpoint in the UITableView custom class and noticed that the methods within (such as cellForRowAtIndexPath:) are called when the view is loaded, but not after touch. The didSelectRowAtIndexPath: method is never called.
The code is very similar to the DateCell example. I'm trying to load a DatePicker (configured to show time only) when a cell is touched.
The relevant code is below, along with a screenshot of the IB delegate and datasource connections. Please let me know if you need any more info. I am new to iOS, so I would greatly appreciate as much detail of possible causes and solutions as possible.
#interface ScheduleTableViewController ()
#property (nonatomic, strong) NSArray *dataArray;
#property (nonatomic, strong) NSDateFormatter *timeFormatter;
#property (nonatomic, strong) NSIndexPath *timePickerIndexPath;
#property (assign) NSInteger pickerCellRowHeight;
#property (nonatomic, strong) IBOutlet UIDatePicker *pickerView;
#property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton; //to be used later for ios 6 compatability
#end
#implementation ScheduleTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableDictionary *itemOne = [[#{ kPeriodKey : #" Tap a cell to change the survey time: " } mutableCopy ] autorelease];
NSMutableDictionary *itemTwo = [[#{ kPeriodKey : #"Morning Survey",
kTimeKey : [NSDate date] } mutableCopy] autorelease];
NSMutableDictionary *itemThree = [[#{ kPeriodKey : #"Evening Survey",
kTimeKey : [NSDate date] } mutableCopy] autorelease];
self.dataArray = #[itemOne, itemTwo, itemThree];
self.timeFormatter = [[[NSDateFormatter alloc] init] autorelease];
[self.timeFormatter setDateFormat:#"h:mm a"];
[self.timeFormatter setDateStyle:NSDateFormatterNoStyle];
[self.timeFormatter setTimeStyle:NSDateFormatterShortStyle];
UITableViewCell *pickerViewCellToCheck = [self.tableView dequeueReusableCellWithIdentifier:kTimePickerID];
self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
[self.tableView setDelegate:self];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.reuseIdentifier == kDayPeriodAndTimeCellID) {
// todo check for ios < 7.0
[self displayInlineTimePickerForRowAtIndexPath:indexPath];
} else {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
NSString *cellID = kDayPeriodAndTimeCellID;
if ([self indexPathHasPicker:indexPath]) {
cellID = kTimePickerID;
}
cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
if (indexPath.row == 0) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSInteger modelRow = indexPath.row;
if (self.timePickerIndexPath != nil && self.timePickerIndexPath.row < indexPath.row) {
modelRow--;
}
NSDictionary *itemData = self.dataArray[modelRow];
if ([cellID isEqualToString:kDayPeriodAndTimeCellID]) {
cell.textLabel.text = [itemData valueForKey:kPeriodKey];
cell.detailTextLabel.text = [self.timeFormatter stringFromDate:[itemData valueForKey:kPeriodKey]];
}
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self hasInlineTimePicker]) {
NSInteger numRows = self.dataArray.count;
return ++numRows;
}
return self.dataArray.count;
}
I am adding to an existing application, so all of the existing UI is implemented in XIB files, however this table is implemented in a storyboard. Here is a screen shot of the delegate and datasource outlet connections.
I think you need to provide a little more context here, but I have a guess. A UITableView needs a UITableViewDataSource to tell it what data should be in the cells. Do you hook that up in the XIB? If so, I don't see any of the methods implemented in your ScheduleTableViewController.
Make sure you implement that protocol and specifically the method "tableView:cellForRowAtIndexPath:". This is where you actually configure the cells that appear in the table view.
It sounds like you created the prototype table cells in InterfaceBuilder. For each prototype cell you created, make sure you set it's cell identifier in the properties inspector. Then use this cell identifier to identify which cell you are configuring in the call to "tableView:cellForRowAtIndexPath:".
Have you tried setting your table data with the functions
numberOfSectionsInTableView:tableView
tableView:tableView numberOfRowsInSection:section
I had the similar issue (in swift). It was solved by putting an instance variable to my tableViewManager responsible for presenting tableView. Initially an instance of it was created and called from button action method. So it was deallocated by ARC and consequently tableView had disappeared when I was trying to interact with it.
Inspired by: iOS TableViewController in PopOver disappears after touching tableview
In my case I was using SwipeMenuViewController (https://github.com/yysskk/SwipeMenuViewController)
and in each page there was a table view.
When I click the tabs it's switch the tables with no problem. but when I touched the table the data disappeared although
the table exists (I used background colours to check)
My solution was to hold a reference to the UIViewControllers return from the SwipeMenuViewController method:
func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController {
viewControllers[index.description] = baseContactsTableViewController
return baseContactsTableViewController
}
I have a Dynamic table view which has 5 prototype cells, inside each cell I have 6 textfields. I´m tagging the textfields but I´m having trouble understanding How can I get the values from all of them in the "textFieldDidEndEditing".
In my code I have this:
-(void) textFieldDidEndEditing:(UITextField *)textField
{
NSMutableArray *cellOneContentSave = [[NSMutableArray alloc] init];
NSString *cellOneTexfieldOneTxt;
if (textField == [self.view viewWithTag:1503])
{
cellOneTexfield1Txt = textField.text;
[cellOneContentSave addObject:cellOneTexfieldOneTxt];
}
Problem 1: BUT! this only get´s me the value from one texfield in cell one...Should I be using a switch for each cell and texfield?.
Problem 2: I said it was a dynamic tableview, so the user can insert news rows(per section) pressing the green + button that appears on the left side when he enters the commit edit style...and when he enters, should the tag´s of the newtexfields have different tag´s?. In one hand I think not, because it´s new texfields BUT different indepaxth.row....but in the other hand I don´t know if the controller demands new tag´s...
-(void) textFieldDidEndEditing:(UITextField *)textField
{
// assuming your text field is embedded directly into the table view
// cell and not into any other subview of the table cell
UITableViewCell * parentView = (UITableViewCell *)[textField superview];
if(parentView)
{
NSMutableArray *cellOneContentSave = [[NSMutableArray alloc] init];
NSString *cellOneTexfieldOneTxt;
NSArray * allSubviews = [parentView subviews];
for(UIView * oneSubview in allSubviews)
{
// get only the text fields
if([oneSubview isKindOfClass: [UITextField class]])
{
UITextField * oneTextField = (UITextField *) oneSubview;
if(oneTextField.text)
{
[cellOneContentSave addObject: oneTextField.text];
} else {
// if nothing is in the text field, should
// we simply add the empty string to the array?
[cellOneContentSave addObject: #""];
}
}
}
}
// don't forget to actually *DO* something with your mutable array
// (and release it, in case you're not using ARC), before this method
// returns.
}