I have a mapView and tableView, with each annotation in the mapView corresponding with a cell in the table. What I want to do is select the appropriate cell anytime an annotation is selected on the map.
As of right now, im creating an NSDictionary when the cells are created, which maps the row number to the annotationID. This works, but the problem is that the dictionary isnt completely populated until all the cells have been created, and all the cells arent created until youve scrolled all the way through the table. Thus, when the app starts for the first time, only the 4 annotations originally visible can be selected from the mapView.
So what im looking for is either a method to automatically populate my dictionary, or a better way of accomplishing what i need to do. Thanks a lot!
Well, first thoughts are that instead of populating the NSDictionary during scrolling, just populate it during viewDidLoad ..I do something similar where I populate all of my data into an NSDictionary and then use that to initialize/update the UI on the cells during scrolling for re-usable cells.
Also, by putting your data into an array of some kind, you can also map it to the cells. Just remember that arrays start at 0, so position in table = indexOfYourArray + 1
Simple example of loading an array stored in a plist into an NSArray in viewDidLoad
// Load the data
NSString *pathToFile = [[NSBundle mainBundle] pathForResource:someArrayNameString ofType:#"plist"];
self.someArrayYouCreated = [NSArray arrayWithContentsOfFile:pathToFile];
Now that you just dumped a whole bunch of data into that array, you can populate it during scrolling in cellForRowAtIndexPath
NSDictionary *dataItem = [someArrayYouCreated objectAtIndex:indexPath.row];
UILabel *label;
label = (UILabel *)[cell viewWithTag:1];
label.textColor = [UIColor colorWithRed:(58/255.f) green:(58/255.f) blue:(58/255.f) alpha:1.0];
label.text = [dataItem objectForKey:#"PersonName"];
With this example, you are just populating the cells from an array that you created in viewDidLoad and therefore all of your data is ready to use almost right away. If you have a ton of data, you could also throw up a progress circle to delay for a second until the array is finished loading.
Again, I don't quite understand how you are storing your data (since you have not said anything about that) so I can only speculate that this will work for you. Until you provide more detail, this is the best I can do.
Related
I have a UITableView that is broken up into a user defined number of sections. Within each of these sections there are always 2 rows. Each of these two rows contains a UITextField which the user is able to edit.
What I need is a way of being able to access the data in these UITextFields at a later point. I was hoping it would be a simple problem however it's causing me a great deal of grief.
So far I have tried two approaches:
Attempt 1
I created two NSMutableArrays in which I added the UITextField objects to at index i (corresponding to the section it came from). I then tried to access the values by iterating through the array. This didn't work since the UITextFields kept getting wiped clean. Every-time I scroll down the table and the UITextField is out of view, when I go back it's contents have been wiped clean.
Attempt 2
I tried to get hold of the number of sections in the UITableView (this was fine). I then wanted to iterate through each section of the UITableView, recording the values in the rows of each. This is where I became unstuck since I'm not sure how to do this or if it's even possible.
I apologise if this is a naive question to ask, however I'm really struggling and would appreciate any advice.
Keep in mind that the text fields get reused as you scroll, so you don't really want to store references to them.
What you do instead, is to capture the information as it is entered. The easiest way to do this is to implement the textFieldDidEndEditing protocol method in the delegate.
The tricky part is figuring out which row the text field is in. The best way is to create a UITableViewCell subclass which has a NSIndexPath property. You can then set that when you configure the cell with tableview:willDisplayCell:forRowAtIndexPath:.
Then, in textFieldDidEndEditing, access the tableViewCell indexPath property through its superview. i.e.:
NSIndexPath indexPathOfParentCell = [(MyUITableViewCellSubclass *)self.superview indexPath];
Doing it this way allows you to know both the section and row of the cell.
Create your TextField in the cellForRow of the Table like so and give it a tag
UITextField * userField = [[[UITextField alloc] initWithFrame:CGRectMake(0, 12, self.view.frame.size.width -20, 20)] autorelease];
userField.tag = 1001;
userField.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:14];
userField.textAlignment = UITextAlignmentCenter;
userField.delegate = self;
userField.autocorrectionType = UITextAutocorrectionTypeNo;
userField.autocapitalizationType = UITextAutocapitalizationTypeNone;
userField.clearButtonMode = UITextFieldViewModeWhileEditing;
if (indexPath.row == 0)
[cell.contentView addSubview:userField];
then access the TextField like so:
UITextField *userField = (UITextField *)[[(UITableViewCell *)[(UITableView *)tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]] contentView] viewWithTag:1001];
Your "Attempt 1" should work OK if you keep the text field's text in your arrays rather than the text field itself. (Anything that tries to make a view or control into a data object has a good chance of going wrong.)
Whatever acts as a data source for your table view should be able to re-populate the scrolled cells according to section and row if the content is stored separately.
I'm trying to initialize a tableview with an image, name and surname of each user that I have stored in a NSMutableArray.
In this mutablearray I save a class that I created to store users data and its schema is as follows:
ResultSearchController{
NSInteger *userID;
NSString *userName;
NSString *userSurname;
NSString *userThumb;
}
I have read the documentation of TableView but I still have doubts and problems to display the data in TableView (seems rather complicated to use such objects). Could you help me to get started with this?
Thanks!!
I guess you have a Custom UITableViewCell for that.
Simply use in cellForRowAtIndexPath delegate of UITableView (to set the image):-
yourCustomCellObject.yourImageViewINCustCell.image=[UIImage imageNamed:[(yourClassToStoreData *)[yourNSMutableArray objectAtIndex:indexPath.row] userThumb]];
Similarly you can do in the same manner to set other control elements.
It's just an example of how you can do.I am assuming you have stored the data over some class objects and adding it to an NSMtableArray.
I read tutorial here
http://adeem.me/blog/2009/05/19/iphone-programming-tutorial-part-1-uitableview-using-nsarray/
which shows how to fill a UITableView at initialization. I can't find tut to do so after initialization (for example when User has clicked on a button).
Any suggestion ?
You would just update the data source and reload the table view.
Following that tutorial, you would do it like so:
- (IBAction)myButtonPressed:(id)sender
{
self.arrayData = [[NSArray alloc] initWithObjects:#"iPhone", #"iPod", #"MacBook", #"MacBook Pro", #"iMac"];
[self.tblSimpleTable reloadData]
}
This will tell the UITableView to reload the data source and adjust the amount of sections, rows etc.
Note that you might prefer to use a NSMutableArray instead.
[self.mutableArrayData addObject:#"iMac"];
Is there a way to get access to a UITableViewCell that is not currently on screen? I'm trying to update rows that are currently not in view. I am using this collapsable/expandable rows for a UITableView in one of Apple's example codes. I use this:
for (NSInteger row = 0; row < totalRows; row++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section];
OrderTableViewCell *cell = (OrderTableViewCell *)[_tableView cellForRowAtIndexPath:path];
cell.CheckmarkButton.selected = YES;
cell.Symbol.isSelected = YES;
}
My totalRows is correct in that I get the number of rows from the TableView. So I thought I could use that, loop through all the rows, and set some values. However, if I check the state of the rows, the ones that are currently on screen have values and I can change them, but the ones off screen are null and cannot be set. Is there a way I can get around this? Thanks.
Depending on what you want to update you could just update the ith entry in a backing collection.
For example you could have a collection that stores bools corresponding to CheckmarkButton selected. In your loop you could set myArray[row] = YES. In cellForRowAtIndexPath you can do cell.CheckmarkButton.selected = myArray[indexPath.row].
If you want to maintain multiple items for each cell then myArray in the above example could contain instances of an object that holds values relevant to the ith cell.
Well why do you have to update a cell like that... If the cell is out of view, to save memory the system unloads it, and since its not in the view there is no need for you to update the cell directly, rather you should have the state be reflected in such way that when cellForRowIndexPath is called by the table view to load the cell the desired look is shown... The only reason youd want to do what you are doing is if the cell is showing and you need to update the cell, for the user... Even then you can still set your state and call the reloadRowsAtIndexPaths instead of manipulating the cell directly... Hope that helps
I am writing a program, and one part of my program has a UItableView in which I set cell contents manually by using the following...
cell.textLabel.text = #"CELL CONTENTS HERE!";
How can I copy a string displayed in a particular TableView Cell into another NSString?
Try something like this:
NSString *anotherString = [NSString stringWithString:cell.textLabel.text];
Keep your #"CELL CONTENTS HERE!" string as a #property of your view controller. Then set the cell's text property to it:
cell.textLabel.text = cellContentsHereProperty;
inside the table view delegate method -tableView:cellForRowAtIndexPath:. You want to do this because you can only access cell.textLabel.text inside this method, or by calling the delegate method to retrieve the cell, which is awkward.
As a general concept, you want your view controller ("control") to keep the string value ("model") separate from how it is displayed ("view"). Keeping things compartmentalized lets you retrieve and change the data without worrying about how it is displayed.
This separation of responsibilities is called the MVC or Model-View-Control design pattern, which Apple subscribes to for iPhone application design.