Adding Custom Objects to NSMutableArray - ios

I mainly program in Java and can't understand why this isn't working. I'm trying to create a temporary object "Judge" in my for loop. I then want to add that object to an NSMutableArray so in the end I have an array filled with different Judge objects. After the for loop I run through all the objects in the Array and they're all the last Judge Object.
The NSLog shows that "JudgeTemp" object is being assigned the right values while in the for loop. My guess is that it's not creating a new object called JudgeTemp every time but referencing the old already created JudgeTemp.
NSMutableArray *Judges = [NSMutableArray arrayWithCapacity:30];
for (int i=0; i<[courtinfoarray count]; i++) {
Judge1= [[courtinfoarray objectAtIndex:i] componentsSeparatedByString:#"|"];
Judge *JudgeTemp=[[Judge alloc]init];
[JudgeTemp setName:[Judge1 objectAtIndex:0] picture:[Judge1 objectAtIndex:1] courtroom:[Judge1 objectAtIndex:2] phone:[Judge1 objectAtIndex:3] undergrad:[Judge1 objectAtIndex:4] lawschool:[Judge1 objectAtIndex:5] opdasa:[Judge1 objectAtIndex:6] career:[Judge1 objectAtIndex:7] judgecode:[Judge1 objectAtIndex:8]];
NSLog(#"%#",[JudgeTemp getName]);
[Judges addObject:JudgeTemp];
NSLog(#"%#",[[Judges objectAtIndex:i]getName]);
}
Judges Class
#implementation Judge
NSString *name;
NSString *picture;
NSString *courtroom;
NSString *phone;
NSString *undergrad;
NSString *lawschool;
NSString *opdasa;
NSString *career;
NSString *judgecommentcode;
-(void) setName:(NSString *)n picture:(NSString *) p courtroom:(NSString *)c phone:(NSString *)ph undergrad: (NSString *) u lawschool: (NSString *)l opdasa: (NSString *) o career: (NSString *)ca judgecode: (NSString *)jcode{
name = n;
picture = p;
courtroom = c;
phone = ph;
undergrad = u;
lawschool = l;
opdasa = o;
career = ca;
judgecommentcode = jcode;
}
-(NSString*) getName{
return name;
}

The problem is with your Judge class. When you define variables directly in your #implementation they have global scope and are not instance variables. What you need to do is put those variable declarations in your #interface instead:
#interface Judge : NSObject {
NSString *name;
NSString *picture;
NSString *courtroom;
NSString *phone;
NSString *undergrad;
NSString *lawschool;
NSString *opdasa;
NSString *career;
NSString *judgecommentcode;
}
// ...
#end
Edit: Apparently you can declare them in your #implementation, you just have to wrap them in { }. See: Instance variables declared in ObjC implementation file

Related

Get NSDictionary with variable names as keys

Say I have n variables
NSNumber* A = #(1);
NSNumber* B = #(2);
NSNumber* C = #(3);
NSNumber* D = #(4);
NSNumber* E = #(5);
...
I need a dictionary like
{#"A":#(1), #"B":#(2), #"C":#(3), #"D":#(4), ... }
One can imagine a more cumbersome example that would be tedious to type out
I think saw a C style function for it but I can't remember. Something like NSDictionaryForVariables()
The C preprocessor macro (not a function) you're looking for is NSDictionaryOfVariableBindings. However, outside of Auto Layout (and, debatably, even there), it's not really a great idea to be setting up dependencies between runtime and compile-time identifiers like that.
Depending on what you're trying to actually accomplish, Key-Value Coding might be a better solution.
It's not a good approach you may find another way to solve your issue but if you want to have an idea about your requested solution here here my try
Our properties
#interface TestyViewController ()
#property (nonatomic) NSNumber* a;
#property (nonatomic) NSNumber* b;
#property (nonatomic) NSNumber* c;
#property (nonatomic) NSNumber* d;
#end
Set the values
- (void)viewDidLoad {
[super viewDidLoad];
self.a=#(1);
self.b=#(2);
self.c=#(3);
self.d=#(4);
}
Get our instance variables
-(NSArray *)propertyNames{
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList([self class], &propertyCount);
NSMutableArray * propertyNames = [NSMutableArray array];
for (unsigned int i = 0; i < propertyCount; ++i) {
objc_property_t property = properties[i];
const char * name = property_getName(property);
[propertyNames addObject:[NSString stringWithUTF8String:name]];
}
free(properties);
return propertyNames;
}
Create the dictionary
- (IBAction)buttonClicked:(id)sender
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
for (NSString* varName in [self propertyNames])
{
[dict setObject:[self valueForKey:varName] forKey:varName];
}
NSLog(#"%#",dict);
}
result
2015-07-15 20:30:56.546 TestC[879:27973] {
a = 1;
b = 2;
c = 3;
d = 4;
}

isEqualToString always returns False

A little background here before I get started, basically we are looking to compare a UDP response with a string stored in Parse's database for our app. This issue is that I can't seem to get the strings to be considered equal by the isEqualToString function. Here's the code I have running now, I have tried a few work-arounds I've seen in other questions but it still doesn't work.
- (BOOL) onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
{
if(tag == TAG_SINGLE_GRILL)
{
NSString *grillId = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(grillId.length > 11)
{
grillId = [grillId substringToIndex:11];
}
grillId = [NSString stringWithFormat:#"%#", grillId];
if([grillId hasPrefix:#"GMG"])
{
for(int i = 0; i < [parseGrills count]; i++)
{
NSString *parseGrillId = [[parseGrills objectAtIndex:i] grillId];
parseGrillId = [NSString stringWithFormat:#"%#", parseGrillId];
//If we match the id, add it to found grills
if([grillId isEqualToString:parseGrillId])
{
//do stuff
}
}
}
NSLog(#"Grill ID : %#", grillId);
}
return TRUE;
}
parseGrills is an NSMutableArray with a very basic Grill object, I use synthesize for the properties, otherwise the .m file is essentially empty.
#import <Foundation/Foundation.h>
#interface Grill : NSObject
#property (nonatomic) NSString* grillId;
#property (nonatomic) NSString* ipAddress;
#end
Here's a screen shot of the debugger after it returns false
Any help would be greatly appreciated. Thanks.
I guess that they are of different encoding.
I have run this experiment and see that if the encoding is different, it will return NO. So, try converting parseGrillId to utf8 with the code below.
NSString *s1 = [NSString stringWithCString:"HELLO123" encoding:NSUTF8StringEncoding];
NSString *s2 = [NSString stringWithCString:"HELLO123" encoding:NSUTF16StringEncoding];
NSString *s3 = [NSString stringWithUTF8String:s2.UTF8String];
if ([s1 isEqualToString:s2]) {
NSLog(#"s1 == s2");
}
if ([s1 isEqualToString:s3]) {
NSLog(#"s1 == s3");
}
Will print s1 == s3.

Using NSMutableArray to keep Objects

I think that I'm missing some fundamental knowledge on Xcode Objective C programming standards. Unfortunately I couldn't find the appropriate solution to my problem.
The problem is that when I try to keep data in an array of objects it becomes impossible to keep them separately. Adding new objects overwrites the previous objects in array. Here is some code about that:
CustomObject.m file:
#import "CustomObject.h"
NSString * title;
NSString * detail;
#implementation CustomObject
- (void) initCustomObjectWithValues : (NSString *) iTitle : (NSString *) iDetail {
title = [NSString stringWithString:iTitle];
detail = [NSString stringWithString:iDetail];
}
- (NSString *) getTitle {
return title;
}
- (NSString *) getDetail {
return detail;
}
#end
viewDidLoad function in ViewController.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
myMutableArray = [[NSMutableArray alloc] init];
for (int i=0; i<10; i++) {
NSString * tempTitle = [#"title " stringByAppendingString:[NSString stringWithFormat:#"%d",i]];
CustomObject * myCustomObject = [[CustomObject alloc] init];
[myCustomObject initCustomObjectWithValues :[NSString stringWithFormat:#"%#",tempTitle]
:[#"detail " stringByAppendingString:[NSString stringWithFormat:#"%d",i]]];
[myMutableArray addObject:myCustomObject];
}
for (int i=0; i<10; i++) {
NSLog(#"%#",[[myMutableArray objectAtIndex:i] getTitle]);
NSLog(#"%#",[[myMutableArray objectAtIndex:i] getDetail]);
NSLog(#"----------------------------");
}
}
Here, myMutableArray is defined at the top of the ViewController.m file. (To make it global and can be used in other functions in future)
Here what I've got in the logs:
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
title 9
detail 9
----------------------------
As far as I understand each new added object overwrites the olds. First I thought that they are referring to same allocated memory but in debug tool myMutableArray seems like this:
Printing description of myMutableArray:
<__NSArrayM 0x8d8cb60>(
<CustomObject: 0x8d8e990>,
<CustomObject: 0x8d8dd40>,
<CustomObject: 0x8d8d2e0>,
<CustomObject: 0x8d8d470>,
<CustomObject: 0x8d8d350>,
<CustomObject: 0x8d8ddf0>,
<CustomObject: 0x8d8df00>,
<CustomObject: 0x8d8df40>,
<CustomObject: 0x8d8dff0>,
<CustomObject: 0x8d8e0c0>
)
Does anyone have an idea about the solution. It should be something very basic but I can't catch the problem.
Thank you all in advance
using
NSString * title;
NSString * detail;
outside of the #interface part creates global variables. When you assign a variable to title or detail you don't set an instance variable of your object, you change those global variables. And since they are global, they are the same for all objects that reference them.
Turn those global variables into instance variables, or even better use #property.
Your code is bad objective-c overall.
You should not use get in getters that return variables. You should not have methods that start with init and don't return self. You should only call init in [[Foo alloc] init...] situations. You should avoid unnamed parameters in your methods.
And there is no need to create strings from strings from strings.
Here is how I would write it:
// CustomObject.h
#interface CustomObject : NSObject
#property (copy, nonatomic) NSString * title;
#property (copy, nonatomic) NSString * detail;
- (id)initWithTitle:(NSString *)title detail:(NSString *)detail
#end
// CustomObject.m
#import "CustomObject.h"
#implementation CustomObject
- (id)initWithTitle:(NSString *)title detail:(NSString *)detail {
self = [super init];
if (self) {
// use stringWithString: to create #"" strings when title is nil
// if nil is a valid value for those variables you should use
// _title = [title copy];
_title = [NSString stringWithString:title];
_detail = [NSString stringWithString:detail];
}
return self;
}
#end
for (int i=0; i<10; i++) {
NSString *tempTitle = [NSString stringWithFormat:#"title %d",i];
NSString *tempDetail = [NSString stringWithFormat:#"detail %d",i];
CustomObject * myCustomObject = [[CustomObject alloc] initWithTitle:tempTitle detail:tempDetail];
[myMutableArray addObject:myCustomObject];
}
for (int i=0; i<10; i++) {
CustomObject *object = myMutableArray[i];
NSLog(#"%#", object.title);
// or NSLog(#"%#", [object title]); if you don't like dot-notation.
NSLog(#"%#", object.detail);
NSLog(#"----------------------------");
}

Generate MD5 hash from Objective-C object [duplicate]

This question already has answers here:
MD5 algorithm in Objective-C
(5 answers)
Closed 9 years ago.
I'd like to generate an MD5 hash for an NSObject:
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * type;
#property (nonatomic, retain) NSString * unit;
#property (nonatomic, retain) NSArray * fields;
What is the best way to do so? I've seen examples for hashing from a dictionary or an array, but not from an entire NSObject.
To generate a MD5 hash for an NSObject or a subclass of NSObject, you need to convert it into something that's easily hashable but still represents the state of the instance. A JSON string is one such option. The code looks like this:
Model.h
#import <Foundation/Foundation.h>
#interface Model : NSObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * type;
#property (nonatomic, retain) NSString * unit;
#property (nonatomic, retain) NSArray * fields;
- (NSString *)md5Hash;
#end
Model.m
#import <CommonCrypto/CommonDigest.h>
#import "Model.h"
#implementation Model
- (NSString *)md5Hash
{
// Serialize this Model instance as a JSON string
NSDictionary *map = #{ #"name": self.name, #"type": self.type,
#"unit": self.unit, #"fields": self.fields };
NSError *error = NULL;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:map
options:NSJSONWritingPrettyPrinted
error:&error];
if (error != nil) {
NSLog(#"Serialization Error: %#", error);
return nil;
}
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// Now create the MD5 hashs
const char *ptr = [jsonString UTF8String];
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(ptr, strlen(ptr), md5Buffer);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
#end
Then you can easily retrieve the MD5 hash just by calling the md5Hash method
Model *obj = [Model new];
obj.name = #"...";
obj.type = #"...";
obj.unit = #"...";
obj.fields = #[ ... ];
NSString *hashValue = [obj md5Hash];
You can convert the object into a dictionary if you already have code for creating the hash:
NSDictionary *dict = [myObject dictionaryWithValuesForKeys:#[#"name", #"type", #"unit", #"fields"]];
Or you could implement <NSCoding> on your class, archive it and hash the resulting data.

Access a variable outside the method in objective-c

I have this function that is storing the contents of an array in three different variables. My question is how can I access to the contents stored in _company.address from another function in the same class.
-(NSArray *) csvArray2CompaniesArray:(NSArray *) csvArray
{
int i=0;
NSMutableArray *ma = [[NSMutableArray alloc] init];
for (NSArray * row in csvArray)
{
if (i>0)
{
Company *_company = [[Company alloc] init];
_company.name = [row objectAtIndex:0];
_company.address = [row objectAtIndex:1];
_company.telephone = [row objectAtIndex:2];
[ma addObject:_company];
}
i++;
}
return (NSArray *) ma;
}
Thank you in advance.
You cannot the accessibility of an object is private in a function.Either you declare it as global or declare it in class's scope.Better in .h file
You can use the functios value as :-
YourViewControllerWithFunction *accessFunc=[[YourViewControllerWithFunction alloc]]init];
Company *_company=[accessFunc csvArray2CompaniesArray:youInputArray];
[_company objectAtIndex:intVallue];//Use in loop
You should correct the return value of your function to NSMutableArray or make a copy to get the NSArray of the NSMutableArray you created.
After that, you can access the contents of your array from anywhere inside your class like:
for (Company *c in [self csvArray2CompaniesArray:csvarray])
{
NSLog(#"%#", c.address);
}

Resources