My program has a tableview, I want to show selected items from the tableview in a textview
I have following code which shows only the last item of the NSMutablearray in textview:
I guess problem is the for loop but couldnt figure it out.
stands is NSMutablearray, selectItems is NSMutablearray, selected items is UItexview.
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
[selectItems addObject:[stands objectAtIndex:indexPath.row]];
for (NSString *yourVar in selectItems) {
selectedItems.text=yourVar;
NSLog (#"Your Array elements are = %#", yourVar);
}
[self.mytableView reloadData];
}
I try the following but it crashes:
[selectItems addObject:[stands objectAtIndex:indexPath.row]];
int length = [selectItems count];
for(int i=0;i<=length;i++){
selectedItems.text= [selectItems objectAtIndex:i];
}
how can I show all the items of NSmutablearray in a texview ?
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
[selectItems addObject:[stands objectAtIndex:indexPath.row]];
NSMutableString *exString = [[NSMutableString alloc]init];
for (NSString *yourVar in selectItems) {
NSLog (#"Your Array elements are = %#", yourVar);
[exString appendFormat:#"\n%#",yourVar];
}
selectedItems.text=exString;
[self.mytableView reloadData];
}
What about something like this? It takes each object, puts a newline in it, then adds it to exString to form one long chain of the objects in your array.
Make sure you properly allocated and inited selectItems. Just adding objects does not create the NSMutableArray. Then you also need to concatenate your elements instead of overwriting the UITextView over and over again.
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.
I am populating a tableview with the contents of an array. Right now, I create the array in viewdidload and I calculate the number of rows in the delegate method
//in viewdidload
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL: kItemsURL];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
[self.tableView reloadData];
//method called in viewdidload to create array...
- (void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSLog(#" %#",json);
NSArray* latestItems = [json objectForKey:#"items"];
NSLog(#" array:%#",latestItems);
//getItems is a property in .h file
self.getItems = latestItems;
NSLog(#"getItems %#",_getItems); //logs out array ok
int size = [_getItems count];
NSLog(#"there are %d objects in the array", size);//provides correct number
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"getItems %#",_getItems); //logs (null)
int size = [_getItems count];
NSLog(#" %d objects in the array", size);//logs 0
When I count rows in viewdidload after creating the array, I get the correct number, however, when I call count on the array in the delegate method, it returns zero possibly because the tableview is created before Viewdidload is called.
Where should I create the array so that is known by the time numberofrows counts the number of rows in the array?
Edit:
After constructing the array, I save it to a property. However, I have discovered that this property is empty when I then log it to console in the numberofrowsinsection method so the problem seems to lie in how I am storing this array.
Right now, I have a property in the .h file and I've also tried it in the implementation but either way it is not persisting for some reason.
I'm not to familiar with obj-C, but I know you need to initialize your array outside your viewDidLoad() function. The reason why your .count is returning zero, is because your array is acting as a local variable to your viewDidLoad() function. Instead you could initialize the array as field in your UITableViewController class. This is how you would do so in swift, but it applies to obj-C as well:
class YourTableViewController: UITableViewController {
var yourArray = [AnyObject]()
override func viewDidLoad() {
//You can still do any programming to set up values and elements in yourArray[] here
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourArray.count
}
//Plus all your other tableView functions...
}
Also if you are passing information to your array between other UIViewController's you can add this function to your class, so every time you come back to your table view it loads the correct table cell count:
override func viewWillAppear(animated: Bool) {
self.tableView.reloadData()
}
I suggest to load the content of your array in viewDidLoad(), that is called once and before the table view use the array. The table view do not load the items before viewDidLoad. Are you doing something much different than this example structure below?
#implementation ViewController {
NSArray *arrayList;
}
- (void)viewDidLoad {
[super viewDidLoad];
arrayList = #[#"item 1", #"item 2"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.textLabel.text = [arrayList objectAtIndex:indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return arrayList.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
Consider abstracting the creation of your data - the array instantiated in your tableview, into a model instead. This is generally considered to be a better software engineering practice (read : https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html ).
What I would do is have another file as a Class or Struct, and populate the data for the array used in your table view in there. I would also recommend having setter/getter methods in your array class/struct as well. When loading the tableview, we would then grab the data from the class/struct in your tableview viewDidLoad() method. The data from your array would also be available at any other point of your application as well, as it is no longer dependant on the tableview.
Side note : You can consider making the class/struct a singleton as well, if the model is supposed to only get instantiated once.
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];
}
So I'm currently listening to a text change from the searchBar:
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)searchText
{
[self filterContentForSearchText:searchText];
}
I want to design a method filterContentForsearchText such that it automatically filters through my UITableView as I type.
The problem I'm having is that my UITableView is complicated. It has multiple sections with multiple fields. It's basically an contact/address book that is an array of arrays that holds contact objects.
CustomContact *con = [contacts[section_of_contact] allValues][0][x] where x is a specific row in that section returns a CustomContact "con" that has properties like con.fullName.
The UITableView currently displays fullNames of contacts in separate sections. How can I filter through this structure of an array/UITableView as I type using my UISearchBar?
Here's how the table is filled:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BrowseContactCell *cell = [tableView dequeueReusableCellWithIdentifier:#"BROWSECELL"];
CustomContact *thisContact = [self.contacts[indexPath.section] allValues][0][indexPath.row];
cell.labelName.text = thisContact.fullName;
return cell;
}
I also created an address-book with sections (an array of arrays), so I'll just post my solution, which is however not my own solution (I somewhere found it here on stackoverflow some time ago):
In your UITableViewController subclass just add the following two UISearchDisplayDelegate methods (link to the api reference) and the "custom" method filterContentForSearchText to filter through your array. For better understanding, please read my comments in the code blocks. Further questions or ideas for improvement are always welcome.
#pragma mark - search Display Controller Delegate
- (BOOL) searchDisplayController : (UISearchDisplayController *) controller
shouldReloadTableForSearchString : (NSString *) searchString {
[self filterContentForSearchText : searchString
scope : [[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex : [self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
#pragma mark - Search Filter
- (void) filterContentForSearchText : (NSString*) searchText
scope : (NSString*) scope {
// Here, instead of "lastName" or "firstName" just type your "fullName" a.s.o.
// I have also a custom NSObject subclass like your CustomContact that holds
//these strings like con.firstName or con.lastName
NSPredicate* resultPredicate = [NSPredicate predicateWithFormat : #" (lastName beginswith %#) OR (firstName beginsWith %#)", searchText, searchText];
// For this method, you just don't need to take your partitioned and
// somehow complicated contacts array (the array of arrays).
// Instead, just take an array that holds all your CustomContacts (unsorted):
NSArray* contactsArray = // here, get your unsorted contacts array from your data base or somewhere else you have stored your contacts;
// _searchResults is a private NSArray property, declared in this .m-file
// you will need this later (see below) in two of your UITableViewDataSource-methods:
_searchResults = [contactsArray filteredArrayUsingPredicate : resultPredicate];
// this is just for testing, if your search-Filter is working properly.
// Just remove it if you don't need it anymore
if (_searchResults.count == 0) {
NSLog(#" -> No Results (If that is wrong: try using simulator keyboard for testing!)");
} else {
NSLog(#" -> Number of search Results: %d", searchResults.count);
}
}
Now, you need to do some changes to your following three UITableViewDataSource-methods:
Note: the searchResultsTableView is also loaded with the normal common data source
methods that are usually called to fill your (sectioned address-book-)tableView:
1.
- (NSInteger) numberOfSectionsInTableView : (UITableView *) tableView
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
// in our searchTableView we don't need to show the sections with headers
return 1;
}
else {
return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] count];
}
}
2.
- (NSInteger) tableView : (UITableView *) tableView
numberOfRowsInSection : (NSInteger) section {
if (tableView == self.searchDisplayController.searchResultsTableView) {
// return number of search results
return [_searchResults count];
} else {
// return count of the array that belongs to that section
// here, put (or just let it there like before) your
// [contacts[section] allValues][count]
return [[currentMNFaces objectAtIndex : section] count];
}
}
3.
- (UITableViewCell*) tableView : (UITableView *) tableView
cellForRowAtIndexPath : (NSIndexPath *) indexPath {
BrowseContactCell *cell = [tableView dequeueReusableCellWithIdentifier:#"BROWSECELL"];
CustomContact *thisContact = nil;
// after loading your (custom) UITableViewCell
// you probably might load your object that will be put into the
// labels of that tableCell.
// This is the point, where you need to take care if this is your
// address-book tableView that is loaded, or your searchTable:
// load object...
if (tableView == self.searchDisplayController.searchResultsTableView) {
// from search list
faceAtIndex = [self->searchResults objectAtIndex: indexPath.row];
} else {
// from your contacts list
contactAtIndex = [self.contacts[indexPath.section] allValues][0][indexPath.row];
}
}
Hope that works for you.
i'm pretty sure this is really simple. But i can't get to make this work. I have a UITableView where i display dynamically a list of facebook friends, thanks to their FBID. Basically, i would like to return the FBIDs of the friends i selected, in one string separated with commas. If possible, in a IBAction, so i can pass them into parameters of a php.
For example, let's pretend i have a list of 4 friends, A B C D, and their ids are 1,2,3,4.
If i select A and C, i would like to have a string which says 1,3.
All i managed to do is to display the id of the friend i select, one at a time.
Here's my code :
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
rowcount = [[tableView indexPathsForSelectedRows] count];
indexer = [idFriends objectAtIndex:indexPath.row];
aapell = [NSString stringWithFormat:#"%#", indexer];
NSMutableString * arrayIds = [[NSMutableString alloc] init];
[arrayIds appendString:aapell];
NSLog(#"ids: %#", arrayIds);
}
Thank you in advance, i'm sure this is not complicated.
-(IBAction)gatherFBIds
{
NSString *listOfFacebookIDs = #"";
NSArray *indexPathArray = [self.tableView indexPathsForSelectedRows];
for(NSIndexPath *index in indexPathArray)
{
//Assuming that 'idFriends' is an array you've made containing the id's (and in the same order as your tableview)
//Otherwise embed the ID as a property of a custom tableViewCell and access directly from the cell
//Also assuming you only have one section inside your tableview
NSString *fbID = [idFriends objectAtIndex:index.row];
if([indexPathArray lastObject]!=index)
{
listOfFacebookIDs = [listOfFacebookIDs stringByAppendingString:[fbID stringByAppendingString:#", "]];
}
else
{
listOfFacebookIDs = [listOfFacebookIDs stringByAppendingString:fbID];
}
}
NSLog(#"Your comma separated string is %#",listOfFacebookIDs);
//Now pass this list to wherever you'd like
}
The problem is that you are not using the information in indexPathsForSelectedRows. That is telling you all the selected rows. Instead, you are just looking at indexPath.row, which is the one row most recently selected.
What you need to do is cycle through indexPathsForSelectedRows and gather up the info for every row that is currently selected (I'm assuming you've enabled multiple selection here).
Use the following code to get the selected rows in a table view. :)
NSArray *selectedRows=[tableView indexPathsForSelectedRows];
NSMutableArray *rownumberArray=[[NSMutableArray alloc]init];
for (int i=0; i<selectedRows.count; i++) {
NSIndexPath *indexPath = [selectedRows objectAtIndex:i];
NSInteger row = indexPath.row;
NSNumber *number = [NSNumber numberWithInteger:row];
[rownumberArray addObject:number];
}
// rownumberArray contains the row numbers of selected cells.