get value of class property (NSMutableArray) - ios

I'm new to objective-c and have already released the first version of my app in the App Store but I want to improve my app because in the current version, I can only enter 4 player names.
In my new iOS app, I have a table view that lists all names that a user can enter in another view controller.
When the user presses play, I want to display a UIAlertView with the name of a random person.
at this moment, I would like to display all names in the NSLog, but I can't figure out how to do that. with my current code, the app keeps crashing.
I have a class, Zoep, which is a subclass of NSObject. and has the following properties:
#property (strong, nonatomic) NSString *playername;
#property BOOL *checked;
In the tableview controller, I have the following code to display items in the NSMutableArray and to display all names in NSLog. I think i'm that i'm almost doing it right now:
- (IBAction)play:(id)sender {
NSString *aantal = [NSString stringWithFormat: #"%ld", (long)[self.zoepers count]];
NSLog(#"array count: %#", aantal);
for (int i = 0; i < 2; ++i) {
NSLog(#"Naam: %lu", (unsigned long)[self.zoepers indexOfObject:[i]]);
}
}
with the above code, i'm still getting the following error and can't compile:
Expected identifier
Could someone point me in the right direction? When you have any tips for me, I would also like to know them.
Thanks a lot in advance!

NSString is an object and can be print with %# and not %lu. Update your code and you're with your name.
for (int i = 0; i < 2; ++i) {
Zoep *player = (Zoep *)[self.zoepers objectAtIndex:i];
NSLog(#"Naam: %#", player. playername);
}
Conclusion: You're storing Zoep class object into your zoepers array, so at the time of accessing zoepers you would first make reference of Zoep class object and then can access properties of that class.
BTW, indexOfObject: takes an object and will return index (position in array).

Change ur code as below..
indexOfObject refers to Object of type id..Actually u are passing int instead of object..
U can get the value of some property of object using (.) like obj.propertyname..
for (int i = 0; i < 2; ++i)
{
Zoep *zoepObj=[self.zoepers objectAtIndex:i];
NSLog(#"Naam: %#",zoepObj.playename);
}
Hope it helps u..

Related

How can I make NSObject that is created in runtime key value coding-compliant

First of all I want to point out that yes there are a lot of questions on this subject on stack overflow but none that was of any help. I also tried asking the owners of these for advice but was unable to get in touch with any of them.
Here is my scenario. I'm receiving data from an API which is an array of objects. These object are all the same structure but they change dynamically from API end point. When I made an NSArray of NSDictionary and tried to set my grid data source with the value of the provided array. It didn't work. When I looked at the documentation IGGridViewDataSourceHelper I found out the following piece of information "As of right now, the data must be of a derivation of NSObject and have at least one property". So I started thinking of a way to create an NSObject at run time. I was able to find some resource on Apple Developers documentation to make that.
Given that the variable dictionary is given in a function
Kindly check the following
- (NSArray *)getRecrodsFromDictionary: (NSDictionary*)dictionary {
// the following include the array that I want to turn into objects
NSArray * response = [self parseKey:#"responseDetails" fromDictionary:dictionary];
NSMutableArray * rows = [[NSMutableArray alloc] init];
if ([response count] != 0) {
// 1. get all NSDictionary keys
NSDictionary * temp = response[0];
NSArray * keys = [temp allKeys];
// 2. create a class
Class ModelClass = objc_allocateClassPair([NSObject class], "WidgetDetailsModel", 0);
// 3. all class variables with the same name as key retrieved from NSDictionary
for (NSString * key in keys) {
NSString * currkey = [key capitalizedString];
const char * name = [currkey UTF8String];
class_addIvar(ModelClass, name, sizeof(id), rint(log2(sizeof(id))), #encode(NSString));
}
// 4. register a class to be used
objc_registerClassPair(ModelClass);
for (NSDictionary * curr in response) {
// create object
id MC = [[ModelClass alloc] init];
for (NSString * key in keys) {
// set values
const char * name = [key cStringUsingEncoding:NSASCIIStringEncoding];
Ivar CurrVar = class_getInstanceVariable(ModelClass, name);
NSString * newValue = [curr objectForKey: key];
object_setIvar(MC, CurrVar, newValue);
}
// add object to array
[rows addObject:MC];
}
}
return [rows copy];
}
Once I get the return value and try to set it to data source data variable I get the following run time error.
[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key AssetsClass.
I can't find any thing on how to make the created in runtime NSObject key value coding-compliant. How can I make it key value coding-compliant?
Edit 1:
I managed to bypass the runtime error by making the fields names capitalized.
Now the table is being populated with empty data (same number of rows as the data but empty text in it) which was the correct thing to happen because the values of the iVar is not retained. How Can I retain it?
Edit 2:
I'm still not able to retain the iVar value so I changed the location of the function to the same UIView class which then it did retain it for the short period of time I had to set the grid data source data value.
I'm curious to know if there is a way to make the iVar retained or set one of its attribute to be strong/retain to mark it for the deallocation process.
After long search on Google, StackOverFlow and other iOS related forums and research. Here is the conclusion that I was able to find. Ivar in objective-c will always be weak reference. In other words there is no way (that I can find) that makes the Ivar strong reference. This can only be achieved throw property with setting the attribute of each property made.

Access property using a variable path

I'm not sure I formed the title correctly since Google keeps silence on it.
I want to access a property (or an object, or an instance) by using path, consisting of known path + variable path. Let's say there are 5 properties: pr1, pr2... pr5. For rehearsal them I use:
for (int i = 1; i <=5; i++) {...}
Next I want to get the property, using i. Something like this: self.pr+i;. What is the correct way to do it in Objective C?
for (NSInteger i = 1; i <=5; i++)
{
// access read
id property = [self valueForKey:[NSString stringWithFormat:#"pr%ld",(long)i]];
// write
id someValue;
[self setValue:someValue forKey:[NSString stringWithFormat:#"pr%ld",(long)i]];
// remember pr1 must be a self property.
}
Generally, though you don't describe the exact case, you can use KVC:
id myVar = [self valueForKey:myVarName];
so once you know that you just need to create the string:
NSString *myVarName = [NSString stringWithFormat:#"pr%d", i];

Not using NSMutableArray correctly

Im trying to inset data in to the array (temp) but for some reason it saves the same data over an over. I all ready checked the _singleSeismicInfo to verify that it was handling different data(you can see it in the double "/" printData method). So i know the problem is with the MutableArray.
Im new to iOS so if theres something Im not doing right let me know.
NSMutableArray *temp = [[NSMutableArray alloc] init];
[_httpContent getTextFromHTTP];
for (int index = 0; index < 10; index++) {
NSString *line = _httpContent.lines[index];
[_singleSeismicInfo fillSeismicInfo:line];
//[_singleSeismicInfo printData];
[temp addObject:_singleSeismicInfo];
}
You're adding _singleSeismicInfo over and over without ever reassigning a new object to the variable as far as I can see. So it's the same object over and over because that's what you add.

sorting through an array - objective C/iOS

so I'm creating a contact list app and I'm storing everything into an NSMutableArray. I've managed to get add function working perfectly. But I'm struggling with the Previous/Next functions.
I can get it to go back one object in the array when pressing previous, but i Can't get it to go back any further? here's my code: I have two extra classes, PhoneBookEntry which is a subclass of the Person class. These classes contain three strings, Firstname,lastname and studentID
- (IBAction)addPerson:(id)sender {
PhonebookEntry *person = [[PhonebookEntry alloc] init];
NSLog(#"%#",self.firstName.text);
person.firstName = self.firstName.text;
person.lastName = self.lastName.text;
person.phoneNumber = self.phoneNumber.text;
[self.entries addObject:person];
Here's my Previous button:
int length;
length = [self.entries count];
if (length > 0) {
int index;
index = [self.entries count] - 1;
NSLog (#"%d the index is", index);
NSLog(#"object %#", [self.entries objectAtIndex:index]);
} else {
NSLog (#"No contacts have been entered. No");
}
//NSLog(#"%d is the length - 1 hopefully", length);
//NSLog (#"index at %d is ", length);
I've tried removing the - 1 here:
index = [self.entries count] - 1;
and changing then on the next line putting index--; but nothing seems to work. it just goes back once.
I understand that length is getting the amount of objects in the index, and then -1 but shouldnt i-- at the end of the count / - 1 keep removing it everytime its pressed??
Any ideas? Cheers
You're going to keep hitting the same index with that piece of code - you need to store the state somewhere. Who is going to hold onto what the current index is? With a good designed system the model should really take care of this.
You are best off storing the current index into an ivar and updating that every time the button is pressed.
#interface OKAClass ()
#property (nonatomic, assign) NSInteger currentIndex;
#end
//... initialise the property with a default value
self.currentIndex = [self.entries count] - 1;
//... when the button is pressed decrement the index (you might want some min / max validation or use modulus to loop over and start from the top again)
NSLog(#"%#", self.entries[self.currentIndex--]);

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

Resources