I have an unsorted NSArray of names. I know how to build a static table, but I am not sure how to make a dynamic table that will have a section with the first letter of the name and then the names for that letter in put into each section. I know this sounds like a beginner level programming question, and well it is. Any help would be great. New to iOS programming so I am just trying to get a feel for everything.
You can do this easily with TLIndexPathTools using the block-based data model initializer:
NSArray *items = ...; // and array containing your unorganized data (items of type NSString assumed here)
TLIndexPathDataModel *dataModel = [[TLIndexPathDataModel alloc] initWithItems:items sectionNameBlock:^NSString *(id item) {
return [[((NSString *)item) substringToIndex:1] upperCaseString];
} identifierBlock:nil];
The sectionNameBlock argument is a block that returns the first letter of the given item, which the initializer uses to organize the data into sections. Then you'd use dataModel (instead of an array) in your data source and delegate methods using the various APIs like [dataModel numberRowsInSection:], [dataModel itemAtIndexPath:], [dataModel indexPathForItem:], etc.
Try running the "Blocks" sample project for a working example.
Related
I am trying to check if the NSMutableArray has a specific object, before adding the object to it, if exists then don't add.
i looked over many posts explaining how to do this, managed to implement it like this, but it always gives me that the object "doesn't exist", though i already added it !
//get row details into FieldLables Object
AllItemsFieldNames *FieldLabels = feedItems[row];
// object to hold single row detailes
AllItemsFieldNames *SelectedRowDetails = [[AllItemsFieldNames alloc] init];
SelectedRowDetails.item_name = FieldLabels.item_name;
//SelectedRowDetails.item_img = FieldLabels.item_img;
SelectedRowDetails.item_price = FieldLabels.item_price;
//NSLog(#"item has been added %#", SelectedRowDetails.item_name);
//NSLog(#"shopcartLength %lu", (unsigned long)SelectedFieldsNames.count);
if([SelectedFieldsNames containsObject:SelectedRowDetails])
{
NSLog(#"Already Exists!");
}
else
{
NSLog(#"Doesn't Exist!");
[SelectedFieldsNames addObject:SelectedRowDetails];
}
I can display all object from the NSMutableArray into a table, what i need to do in the above code is stop the addition of duplicate objects.
The first method listed on the NSArray documentation under the section "querying an array" is containsObject:. If it's not working, that suggests that your implementation of isEqual: is not correct. Make sure you follow the note in the documentation:
If two objects are equal, they must have the same hash value. This
last point is particularly important if you define isEqual: in a
subclass and intend to put instances of that subclass into a
collection. Make sure you also define hash in your subclass.
You might also consider using an NSSet since you can't add duplicates to that. Of course, this would also require a working version of isEqual:.
Sets are composed of unique elements, so this serves as a convenient way to remove all duplicates in an array.
here some sample,
NSMutableArray*array=[[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4", nil];
[array addObject:#"4"];
NSMutableSet*chk=[[NSMutableSet alloc ]initWithArray:array]; //finally initialize NSMutableArray to NSMutableSet
array= [[NSMutableArray alloc] initWithArray:[[chk allObjects] sortedArrayUsingSelector:#selector(compare:)]]; //after assign NSMutableSet to your NSMutableArray and sort your array,because sets are unordered.
NSLog(#"%#",array);//1,2,3,4
I have my own class with several properties and I have them in NSArray. I need to use them for method which takes NSArray of strings. So I am asking what is best aproach to get array with strings from my array which has custom classes. I can create second array and use it but I think there could be better way. I need to have it for different custom classes (from one, I want to use for example name property to new NSArray, in second title property and so).
I hope I explained well but I tried it once more on example:
NSArray *arrayWitCustomClasses = ... fill with custom classes;
// setValues method takes NSArray with NSStrings
// when arrayWithCustomClasses used it returns copyWithZone: error on custom class
[someObject setValues:[arrayWithCustomClasses toArrayWithStrings]];
As long as your object exposes the required values as NSString properties you can use the valueForKey method of NSArray.
For example
NSArray *arrayOfTitles=[arrayWithCustomClasses valueForKey:#"title"];
NSArray *arrayOfNames=[arrayWithCustomClasses valueForKey:#"name"];
Or
[someObject setValues:[arrayWithCustomClasses valueForKey:#"title"]];
and so on
NSMutableArray *strings = [NSMutableArray array];
for (NSObject *item in arrayWithCustomClasses) {
/* You can use a different property as well. */
[strings addObject:item.description];
}
[someObject setValues:strings.copy];
Like #Tim says, but you could shorten it by just using:
[someObject setValues:[arrayWithCustomClasses valueForKey:#"description"]];
Same result. One line of code.
Then implement the description method of your custom classes to return whatever properties and formatting you want.
All,
I have about 3000 words with definitions that I am loading into a TableView. Right now, it's just a sorted list of words, sans the sections because I haven't added them yet.
I need to add sections to my TableView data (A,B,C ...) and there seems to be several ways to do this so before I jump into this I am looking for some confirmation or correction if I am going down the wrong rabbit hole.
Currently the data that the TableView reads is stored as objects in an NSMutableArray per this code:
//AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
//...
NSMutableArray *wordArray = [[NSMutableArray alloc] init];
//Loop through result set from DB and populate objects
while([rs next]){
[wordArray addObject:[Word wordWith:[rs stringForColumn:#"word"]
Definition:[rs stringForColumn:#"definition"]
SectionIndex:[rs stringForColumn:#"sectionIndex"]]];
}
MainViewController *mainViewController =
[[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
mainViewController.listContent = wordArray;
//...
}
Each object has a section index value ([A-Z0-9]) so I already know which section each word goes in, I know what the sections need to be and I can easily derive a count of objects for each section. All the words have been sorted via SQL before the NSMutableArray was populated so that's already handled.
Can I create multiple sections with the one NSMutableArray or do I need to do something different?
Thanks
You could store your words into arrays inside a NSDictionary holding keys for each letter.
Number of sections would return
[[dictionary allKeys] count];
Title for section
NSArray * keys = [dictionary allKeys];
[keys objectAtIndex:sectionIdx]
Number of rows in section would return
NSArray * keys = [dictionary allKeys];
[(NSArray *)[dictionary objectForKey:[keys objectAtIndex:sectionIdx]] count];
Each word would be
NSArray * keys = [dictionary allKeys];
[(NSArray *)[dictionary objectForKey:[keys objectAtIndex:sectionIdx]] objectAtIndex:indexPath.row];
I have found that you sometimes want to add sorting to your lists and then, another approach might be interesting. Put all your models (Word's in your example) in a dictionary with some unique value of the model as the key.
Implement a sorting method, that you run every time the underlying dictionary changes. The sorting method will use e.g. keysSortedByValueUsingComparator on the dictionary and supply a different blocks for different sort orders. Let the sorting method create section arrays and add keys in the arrays that corresponds to the keys in the dictionary.
You do not store anything twice and you get different sort orders by just providing different sort blocks (that can look at any properties of your model class).
I'm new to iOS programming. I'm trying to bind the specific field from the objects in an array to a UITableView. Here's my code:
NSArray *personInfo; //contains a record with fields: name, address, email
personInfo = [[PersonDatabase database] getAllPersons]; //pulling the record into array
From there, I'm trying to get the field "name" from my array.
cell.textLabel.text = [NSString stringWithFormat:#"%#", [personInfo objectAtIndex: indexPath.row] retain]
As it seems you have objects in your array, what you may be looking for is the -[NSArray valueForKey:] method (documentation here).
For example:
NSArray *names = [personInfo valueForKey:#"name"];
This should return you an array containing all of the names in the array.
Are you trying to create a 2D Array?. If so you'll need to call objectAtIndex: twice on it in a nested call, but since you're new I'd suggest breaking down to a few lines so you can see more clearly what is happening.
Also, theres heaps of good code snippets on google for dealing with NSArray and table view.
Please check that if you delcare your array in #interface file as
//////.h
NSArray *personInfo;
#property(nonatomic ,retain) NSArray personInfo;
and then
in #implementation file
add this line
#synthesize personInfo;
hope it works
I am polling an HTTP API - it returns one item at a time, in real-time (about every 4 seconds). As each item is received, I would like a new UITableView cell to be populated. The full list of received items must remain in a class property, I'm guessing an NSMutableArray. What is the best way to initialize an NSMutableArray as a class property, update it as new information comes in, and then use the count to update a new UITableViewCell?
Here's how I'm adding content to an NSMutableDictionary:
NSMutableDictionary *messageContents = [[NSMutableDictionary alloc] init];
[messageContents retain];
[messageContents setValue:messageText forKey:#"text"];
[messageContents setValue:image forKey:#"image"];
[self addMessageToDataArray:messageContents];
Here's the method stuffing objects into the array:
- (void)addMessageToDataArray:(NSArray *)messageDictionary {
[self.messageDataArray addObject:messageDictionary];
NSLog(#"count = %#", [self.messageDataArray count]);
[self reloadTableData];
}
At this point, calling count on the messageDataArray class property crashes the application. I'm very used to working with arrays in Actionscript, Obj-C is obviously totally different. Please explain the method for instantiating an NSMutableArray as a class property, filling it with NSMutableDictionary's and then finding the NSMutableArray count (which will be dynamically updating in real-time) so I can use that info to update a UITableView (on the fly).
Or... tell me I'm being silly and suggest a much easier solution.
From your description I would guess you're not allocating the messageDataArray before using it.
The init function for your table view (controller?) class should have a line like this
messageDataArray = [[NSMutableArray alloc] initWithCapacity:20];
It's also worth checking that you have [messageDataArray release]; in your dealloc method.