Working with NSMutable Array that contain custom class object - ios

I have an array - placeObjectsArray, that hold a lot of objects called place. Place is object of class PlaceHolder, in which i create different properties, filled with data:
self.place = [[PlaceHolder alloc]init];
// A lot of code here during parson XML with data
[self.placeObjectsArray addObject:self.place];
Header of this file look like this:
#interface PlaceHolder : NSObject
#property (strong, nonatomic) NSString *name;
#property (strong, nonatomic) NSString *description;
#property (strong, nonatomic) NSString *webPage;
It actually a container for an entity, each one hold data for name, description, image links etc. At now, i have array with place objects. What i want to, to manipulate with that objects inside an array. For example, how could i find all of data for specific "name"? (Name is one of properties in PlaceHolder class). How could i make an array that contain only names? How could i see in console 10 random "description"?
Any advice would be appreciated, thanks!

You're asking a bunch of separate questions.
First, how to select items in your array that match a particular name: Create an NSPredicate and use filteredArrayUsingPredicate. Google NSPredicate and you should find lots of examples.
Alternately you could use indexesOfObjectsPassingTest to get an index set of the items in the array that match your search criteria, and then use objectsAtIndexes: to turn the index set into a sub-array.
As for how to get all the names from the entries in your array, you can use a very cool trick in key value coding.
If you send an array the valueForKey message, it tries to fetch an item from each entry in the array using that key, and return them all in a new array. The code would look like this:
NSArray *names = [placeObjectsArray valueForKey #"name"];
Fetching 10 random descriptions is a little more complicated. You would need to write code that loops through the array, selecting 10 random items, and appends the description of each one into a new mutable array.
The trick there is to use arc4random_uniform to get a random index in your array:
NSUInteger random_index = arc4random_uniform(placeObjectsArray.count);
I leave the rest to you as a learning exercise.
If you want to fetch 10 random descriptions and make sure you never fetch the same description twice it's more complicated. You need to create a mutable copy of your array, then loop through the copy, fetching a random item, adding it's description to an array, and deleting the item from the array.

You can use NSPredicates:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.name LIKE[cd] %#", nameSearch];
NSArray *filtered = [self.placeObjectsArray filteredArrayUsingPredicate:predicate];

You could iterate over your array looking for the PlaceHolder with a given name, like:
PlaceHolder *namedPlaceholder = nil;
for (PlaceHolder *placeholder in theArray) {
if ([placeholder.name isEqualToString:"whateverName"]) {
namedPlaceholder = placeholder;
break;
}
}
If you want to find PlaceHolders by name efficiently you might consider using a dictionary instead of an array. With a dictionary you can map names to objects, like:
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
myDictionary[#"foo"] = somePlaceholder;
myDictionary[#"bar"] = someOtherPlaceholder;
and retrieve them like:
PlaceHolder *somePlaceholder = myDictionary[#"foo"];
To get random objects from an array, I recommend getting random indexes using arc4random_uniform. This gives pseudo-random numbers with a better uniform distribution than rand or random, and does not require you to explicitly seed the sequence with srand or srandom.
PlaceHolder *randomPlaceholder = theArray[arc4random_uniform(theArray.count)];
or
const NSUInteger arrayCount = theArray.count;
for (NSUInteger j = 0; j < 10; j++) {
PlaceHolder *randomPlaceholder = theArray[arc4random_uniform(arrayCount)];
// Do something with randomPlaceholder.
}

Related

update value at specific index in NSArray

I am hoping not to need to use an NSMutableArray here. I have an array with 10 elements. I want to change the value at index 4. Is there a way to do this without having to use NSMutableArray? The problem with NSMutableArray is that we can change anything about it, including its size. I don't want the size of this array to change accidentally. I just want to change the value at index 4 from say 22 to 25. How might I do that? doing array[4]=25 is not working.
NSArray *ar1 = #[#"1",#"2"];
NSMutableArray *ar1update = [ar1 mutableCopy];
ar1update[1] = #"Changed";
ar1 = [NSArray arrayWithArray:ar1update];
The only way is to create a new NSArray and change your pointer to a new NSArray. I can give an example...
In interface:
#property (strong, nonatomic) NSArray *myArray;
In implementation:
- (void) updateMyArray{
NSMutableArray *myArrayMut = [self.myArray mutableCopy];
myArrayMut[4] = #"new item";
self.myArray = [myArrayMut copy];
}
So basically, you can create a mutable copy temporarily, make the change you need, and then make an immutable copy. Once you have the immutable copy, you can point myArray to the new copy. As long as you are only changing existing items in updateMyArray and the myArray starts out with 10 items or less, you will never be able to have more than 10 items.
If you don't wish to use NSMutableArray how about a plain old C array? E.g.:
int array[10];
...
array[4] = 25;
You can store Objective-C objects in such an array and ARC will handle the memory management.
If you really want a fixed-sized NSArray/NSMutableArray you can do that by subclassing those types yourself - subclassing NSArray only requires implementing two methods and you can use an underlying C array or NSMutableArray for the actual storage.
HTH

Filter/Search NSMutableDictionary

I have an NSMutableDictionary (PerosnsListSections) and a class names Persons
NSMutableDictionary:
Keys are letters like "a,b,m ..."
Values are NSMutableArray
-> NSMutableArray have objects of class Persons
Persons class:
#property (assign,nonatomic) NSInteger pid;
#property (strong,nonatomic) NSString *name;
Now i have PerosnsListSections displayed in UITableView as shown in the image
what I want to achieve is when user types in the search bar first i have to filter the section which is the first letter then to filter the names under that section.
Sorry for my bad English (:
You can first select the correct array in the dictionary by doing:
NSString *firstLetter = [searchString substringWithRange:(NSRange){0,1}];
NSArray *people = PersonsListSection[firstLetter];
Then you can filter down on the people by using NSPredicates:
NSPredicate *namesBeginningWithKeyword = [NSPredicate predicateWithFormat:#"(name BEGINSWITH[cd] $letter)"];
NSArray *filteredPeople = [people filteredArrayUsingPredicate:[namesBeginningWithKeyword predicateWithSubstitutionVariables:#{#"letter": searchString}]]);
The question of how you make that be reflected in the tableview's content is a whole another question though.
Typically, you'll want your view controller to be the UISearchBar's delegate and react to change using the – (void)searchBar:textDidChange: delegate method.
There you could just call your tableview's - reloadData method so it tries recompute its content, calling all of its dataSource method like - numberOfSectionsInTableView: and so forth.
In these methods, in turn, you'll want to check whether some text was entered in the search bar and use the above tips to return the right sections/cells.

NSMutableArray Allocate then replaceObjectAtIndex

I have a NSMutableArray that i define in the header file as:
#property (strong, nonatomic) NSMutableArray *tempPhotosArray;
Then i allocate as:
_tempPhotosArray = [[NSMutableArray alloc] init];
What i'd like to know is if i then go to replaceObjectAtIndex the program will complain on an out of bounds. I want to keep only a set number of items in that array, so is it possible to do a insert or replace? i.e. if at index 0 it is empty do an insert, if there is an object already replace it?
Thanks
i think i agree with Hani Ibrahim. Since you said you only want to keep a set number of objects in the array. So how many you want?
// add these code when you initialize the array
int aSetNumber = 5;
_tempPhotosArray = [[NSMutableArray alloc] init];
for (int i = 0; i < aSetNumber; i++)
{
[_tempPhotosArray addobject: [NSNull null]];
}
i guess then you can do whatever you want, i don't know what exactly you want to do in this case, but i would check if the object in that position is NSNUll, if so, replace that, if not, i don't know what you want them
//use these code when you trying to insert the real object
if([[_tempPhotoArray objectAtIndex:anIndex] isKindOfClass: [NSNull class]])
{
//replace it here
}
As to why you are getting an error, what everyone else wrote is accurate, but....
The description of what you want doesn't match what an NSArray is. It sounds like you want a list of up to 5 items and never more than 5. It might be that if you try to add a 6th item the "oldest" goes away. Like a "recently opened" file history. You can make this type of functionality with an NSArray, but that's not what it is out of the box.
I would suggest making your own object class. I'm not going to write all the code for you, because this sounds suspiciously like programming homework, but I will point you in the correct direction.
FivePack <-- our class
NSArray *storage; <-- where we house the data
// a public method which lets you add things.
- (void)addItem:(id)item {
int indexOfLastItemInArrayToSave = 4;
if (storage.length < 4)
indexOfLastItemInArrayToSave = length-1;
NSRange range = NSMakeRange(0, indexOfLastItemInArrayToSave);
NSArray *temp = [storage subArrayWithRange:range];
// now create a new array with the first item being "item" that
// was passed in and the rest of the array being the contents of temp.
// Then save that to storage.
}
What you want to do with the data and writing something to get it from your new object is up to you, because I'm not sure how you want to do it.
There are no objects in the array when you initially created it, so there is nothing to replace.
Like this?
if([_tempPhotosArray count] > 0)
//replace object
else
//add object to array

How to access NSDictionary by key number?

I'm a beginner in iPhone development and I need some help.
I created an NSDictionary to hold some quotes followed by keys (which is the person who quoted them).
Now, I'v created a method to pull a random quote, and to use this method 'arc4random_uniform' I need to use integer...and them I do 'return [self.insperationalQuotes objectForKey:"here i want a random number"];
Usually it probably would be easier to use an array but I want to use the key to attach it to a specific photo of the person who quoted it...or you still recommend to do it with array and say object at #1 will einstein for instance...
This is my code:
#import "NOQuotes.h"
#implementation NOQuotes
- (NSDictionary *) insparationalQuotes {
if (_insparationalQuotes == nil) {
_insparationalQuotes = [[NSDictionary alloc] initWithObjectsAndKeys:
#"Try not to become a man of success but a man of value.",
#"ALBERT EINSTEIN",
#"What lies behind us and what lies before us are tiny matters compared to what lies within us.",
#"HENRY STANLEY HASKINS",
#"It is never too late to be what you might have been.",
#"GEORGE ELIOT",
#"All our dreams can come true–if we have the courage to pursue them.",
#"WALT DISNEY",
#"The best way to predict the future is to invent it.",
#"ALAN KAY",
#"You miss 100% of the shots you don’t take.",
#"WAYNE GRETZKY",
#"If opportunity doesn’t knock, build a door.",
#"MILTON BERLE",
#"Failure is the condiment that gives success its flavor.",
#"TRUMAN CAPOTE", nil];
}
return _insparationalQuotes;
}
- (NSString *) getRandomQuote {
int randomNum = arc4random_uniform(self.insparationalQuotes.count);
return [self.insparationalQuotes objectForKey:randomNum]; //error
}
Thanks!
For what you're trying to do, I recommend creating a Quote class, which will store a quote, an "author", and the image associated with that person. I'd then fill an NSArray or NSMutableArray with instances of these Quote objects so you can randomly select an index.
#interface Quote : NSObject
#property NSString *quote;
#property NSString *author;
#property UIImage *picture;
+(instancetype)quoteWithQuote:(NSString*)quote
author:(NSString*)author
picture:(UIImage*)picture;
-(instancetype)initWithQuote:(NSString*)quote
author:(NSString*)author
picture:(UIImage*)picture;
#end
Then just fill in that class. Arguably, you may even want the #propertys to be readonly, making the Quote class immutable.
Alternatively, you can keep your NSDictionary as is, and pair it with an NSArray made up of all the author names (which you're using as keys). Then select a random index from the array of names, and use that name as the key into the dictionary for the quote. The problem here is it's a little redundant, and you can't have multiple quotes with the same author.
Use allValues to pull an array of values, and index into that array using a random number, like this:
- (NSString *) getRandomQuote {
int randomNum = arc4random_uniform(self.insparationalQuotes.count);
return [[self.insparationalQuotes allValues] objectAtIndex:randomNum];
}
I agree that what you really want is an array of custom objects, but I would like to point out that it is possible to select a random entry from an NSDictionary object:
- (id)randomObjectInDictionary:(NSDictionary *)dict {
NSArray *keyArray = [dict allKeys];
int rand = arc4random_uniform([keyArray count]);
return dict[keyArray[rand]];
}

How to access specific column in NSArray using Xcode

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

Resources