Printing array inside array - iphone

I have class Building in which i have one class member NSMutableArray *subnode.I have declared one more array buildingArray which stores the element of type Building.I have tried to print Building class object as shown in following code.But goes in only first for loop.
Second for loop of subnode array is not executing . Is this proper way of printing the object having the array as a one of its class member.
code:
for(Building *b in buildingArray)
{
NSLog(#"inside building array");
for(NSString *str in b.subnode)
{
NSLog(#"inside subnode array");
}
}

If this is for debugging purposes, I would recommend trying the following: Every object that inherits from NSObject inherits its description method.
Add this to Building.m:
#implementation Building
- (NSString *)description {
NSMutableString *description = [NSMutableString stringWithString:[super description]];
// add the following lines for any relevant properties
// [description appendFormat:#", materials == %#", materials];
// then have the subnode print itself:
[description appendFormat:#", subnode == %#", subnode];
return description;
}
#end
You can then print the entire buildingArray by simply calling the following code:
NSLog(#"buildingArray == %#", buildingArray);

for(Building *b in buildingArray)
{
NSLog(#"inside building array");
NSMutableArray *temp = [NSMutableArray arrayWithArray:b.subnode]
for(id *str in temp)
{
NSLog(#"inside subnode array");
}
}
this should work. happy coding :)

Your code seems to be ok. Just check if the array (subnode) is allocated and initialized. Also check if it has some values in it. I have used similar code and it works for me.

Change following code. I don't know what do you mean buy Building . So i just used id instead of Building to avoid any type of confusion.
for(id b in buildingArray)
{
NSLog(#"inside building array");
NSArray *temp = b;
for(NSString *str in temp)
{
NSLog(#"inside subnode array");
}
}
Hope, this will help you;

Related

How to display Xpath on the iPhone

I'm trying to extract the weather information from here using Xpath on the iPhone. As of now it parses all the data but I'm stuck on how to extract the content and display it in a table.
This is what I have so far:
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[ #"http://aviationweather.gov/adds/metars/?station_ids=1234&std_trans=translated&chk_metars=on&hoursStr=most+recent+only&submitmet=Submit"stringByReplacingOccurrencesOfString:#"1234" withString:self.title]]];
TFHpple * doc = [[TFHpple alloc] initWithHTMLData:data];
NSArray * elements = [doc searchWithXPathQuery:#"//table[1]//tr"];
NSLog(#"%#", elements);
TFHppleElement * element = [elements objectAtIndex:0];
[element content]; // Tag's innerHTML
[element tagName]; // "a"
[element attributes]; // NSDictionary of href, class, id, etc.
[element objectForKey:#"href"]; // Easy access to single attribute
If anybody needs to see what its outputting so far, let me know.
Thanks,
Andrew
I had the same issue I got to the point your at and didn't no where to go but I end up implementing this code. Hope it helps there is still little bits need to make it work correctly but do to the nature of the app I have developed this is all I can give you. its not much more its just the actual implementation into your code that you need really.
#import "XPathQuery.h"
NSMutableArray *weatherArray = [[NSMutableArray arrayWithArray:0]retain]; // Initilize the NSMutableArray can also be done with just an NSArray but you will have to change the populateArray method.
NSString *xPathLookupQuery = #"//table[1]//tr"; // Path in xml
nodes = PerformXMLXPathQuery(data, xPathLookupQuery); // Pass the data in that you need to search through
[self populateArray:weatherArray fromNodes:nodes]; // To populate multiple values into array.
session = [[self fetchContent:nodes] retain]; // To populate a single value and returns value.
- (void)populateArray:(NSMutableArray *)array fromNodes:(NSArray *)nodes
{
for (NSDictionary *node in nodes) {
for (id key in node) {
if ([key isEqualToString:#"nodeContent"]) {
[array addObject:[node objectForKey:key]];
}
}
}
}
You only need either the above code or below code unless you want both.
- (NSString *)fetchContent:(NSArray *)nodes
{
NSString *result = #"";
for (NSDictionary *node in nodes) {
for (id key in node) {
if([key isEqualToString:#"nodeContent"]) {
result = [node objectForKey:key];
}
}
}
return result;
}

How do I find (not remove) duplicates in an NSDictionary of NSArrays?

The title pretty much says it all, but just to clarify: I have an NSMutableDictonary containing several NSMutableArrays. What I would like to do is find any value that is present in multiple arrays (there will not be any duplicates in a single array) and return that value. Can someone please help? Thanks in advance!
Edit: For clarity's sake I will specify some of my variables:
linesMutableDictionary contains a list of Line objects (which are a custom NSObject subclass of mine)
pointsArray is an array inside each Line object and contains the values I am trying to search through.
Basically I am trying to find out which lines share common points (the purpose of my app is geometry based)
- (NSValue*)checkForDupes:(NSMutableDictionary*)dict {
NSMutableArray *derp = [NSMutableArray array];
for (NSString *key in [dict allKeys]) {
Line *temp = (Line*)[dict objectForKey:key];
for (NSValue *val in [temp pointsArray]) {
if ([derp containsObject:val])
return val;
}
[derp addObjectsFromArray:[temp pointsArray]];
}
return nil;
}
this should work
If by duplicates you mean returning YES to isEqual: you could first make an NSSet of all the elements (NSSet cannot, by definition, have duplicates):
NSMutableSet* allElements = [[NSMutableSet alloc] init];
for (NSArray* array in [dictionary allValues]) {
[allElements addObjectsFromArray:array];
}
Now you loop through the elements and check if they are in multiple arrays
NSMutableSet* allDuplicateElements = [[NSMutableSet alloc] init];
for (NSObject* element in allElements) {
NSUInteger count = 0;
for (NSArray* array in [dictionary allValues]) {
if ([array containsObject:element]) count++;
if (count > 1) {
[allDuplicateElements addObject:element];
break;
}
}
}
Then you have your duplicate elements and don't forget to release allElements and allDuplicateElements.

NSMutable Array: Getting "out of scope" Status After Mutable Copying

I have a SOAP service and I generated classes and functions on SudzC.com.
So I'm using the soap functions they generated, it returns an NSMutableArray with objects that are inherited by my custom class(which is generated by them, too).
So far everything's good. My values are getting into the array and I could see any property of any object with one condition: Only inside of the function that's handling the service.
Just to make it clear, here is the code:
- (void)viewDidLoad
{
SDZGeneratedWebService* service = [SDZGeneratedWebService service];
service.logging = YES;
[service callMyData:self action:#selector(callMyDataHandler:) dataId: 1];
[super viewDidLoad];
}
- (void) callMyDataHandler: (id) value {
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the NSMutableArray* result
NSMutableArray *result = (NSMutableArray *)value;
MyCustomClass *myObject = [result objectAtIndex:0];
NSLog(#"%#", myObject.myProperty); //Works Great
}
Like I said, so far everything's perfect. But I need to use the data outside of this function.
So in my .h file, I created an array like NSMutableArray *myDataArray;
When I intend to copy the result array to myDataArray, it copies the objects(I can see that the myDataArray.count value is equal to result array's) but all the objects are "out of scope". So I cannot use them.
I also tried to copy all objects by indexes in a for loop, nope, the objects are getting their values, but when I "addObject" to myDataArray, same, out of scope.
What is wrong here? Can't I generate an array of a custom class this way?
Edit: The code I'm generating myDataArray:
myDataArray = [[NSMutableArray alloc] init];
[myDataArray removeAllObjects];
for (int i=0; i<((NSMutableArray *)result).count; i++) {
MyCustomClass *myObject = [result objectAtIndex:i];
[myDataArray addObject:myObject];
[myObject release];
}
[self.tableView reloadData];
} //(End of callMyDataHandler function)
I before tried this way, too:
[myDataArray removeAllObjects];
duyurular = [result mutableCopy];
} //(End of callMyDataHandler function)
You can copy objects from one array to another using this method:
NSArray *source;
NSArray *dst = [[NSArray alloc] initWithArray:source];
In your code you should remove line: [myObject release]; and I would better call [((NSMutableArray *)result) count] rather then using dot notation.

EXC_BAD_ACCESS error in during fetching data from custome objects

I had stored custom objects data in Array. I am fetching data from Array of custom objects in a function. when I am calling function for first time it is working good but When I am calling it again and again I am getting EXC_BAD_ACCESS.
Here is function details.
-(void) facebookDisplayFunction:(int)atIndex {
FacebookWallData *wall = (FacebookWallData *)[facebook_wallDataArray objectAtIndex:atIndex];
NSString *friendID= wall.actor_id;
NSString *linkFetch= wall.permalink;
NSString* postID=wall.postId;
NSNumber *countNumber;
NSString *friendName=#"";
NSString* profileThumImage=#"";
for(int i=0; i< [facebook_LikesArray count];i++) {
FacebookLikes* countValues=[[FacebookLikes alloc]init];
countValues=[facebook_LikesArray objectAtIndex:i];
// NSLog(#" postId_wall %# LikePostId = %#",postID,countValues.PostID);
if([postID isEqualToString:countValues.PostID]) {
countNumber=countValues.Count;
if(countNumber>0)
friendID=countValues.Friends;
[countValues release];
break;
}
[countValues release];
}
for(int i=0;i< [facebook_FreindsArray count];i++) {
FacebookFreinds* friendsRecord=[[FacebookFreinds alloc]init];
friendsRecord=[facebook_FreindsArray objectAtIndex:i];
if([friendID isEqualToString:friendsRecord.UID]) {
friendName=friendsRecord.name;
profileThumImage=friendsRecord.pic_smal;
[friendsRecord release];
break;
}
[friendsRecord release];
}
// Adding values in table //
[imageData addObject:#"facebook.png"];
[tableList addObject:wall.messages];
[profileUserName addObject:friendName];
[linksOfFacebookData addObject:linkFetch];
[RetweetAndLikeData addObject:#"5"];
[favedProfileThumb addObject:profileThumImage];
[twitterPostID addObject:#""];
[eachPostUID addObject:friendID];
[wall release];
}
And here I am calling function.
[self facebookDisplayFunction:0];
[self facebookDisplayFunction:0]; // EXC_BAD_ACCESS error here.
Why are you allocating an object like this FacebookLikes* countValues=[[FacebookLikes alloc]init] and then assigning to this same variable the instance inside the array with this code countValues=[facebook_LikesArray objectAtIndex:i] and later on you release it with this [countValues release]? You don't know what you are doing.
Try changing this:
FacebookLikes* countValues=[[FacebookLikes alloc]init];
countValues=[facebook_LikesArray objectAtIndex:i];
to this
FacebookLikes* countValues = [facebook_LikesArray objectAtIndex:i];
and remove all occurrences of [countValues release]. Do the same for the friendsRecord in the second for-loop. Also, what is the [wall release]? Remove it!
You should not allocate any of these objects because you are actually obtaining them from that array, and not creating a new instance. That just creates a leak in your code. You should not release any of these objects because they are retained by the array, and it is responsible for releasing them whenever they are removed from the array or after the array is destroyed/deallocated. Please, rtfm
If you get the error on the line:
[self facebookDisplayFunction:0];
it seems to me that most likely the object pointed by self has been deallocated. So, the problem would not be in facebookDisplayFunction...
Could you review how you create the object pointed by self, or post the code if you need more help?

How does Fast Enumeration (looping) work in Objective-C? (ie: for (NSString *aString in aDictionary)...)

I'm working on implementing a customized searchBar for a fairly complex table and have come across this code pattern AGAIN. This is a sample from the Beginning iPhone Development book:
- (void)handleSearchForTerm:(NSString *)searchTerm
{
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init];
[self resetSearch];
for (NSString *key in self.keys)
{
NSMutableArray *array = [self.names valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array)
{
if ([name rangeOfString:searchTerm
options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
[self.keys removeObjectsInArray:sectionsToRemove];
[sectionsToRemove release];
[table reloadData];
}
The part I'm curious about is the "for (NSString *name in array)" section. What is this doing exactly? It seems to create a string for every item in the array. Also, how does this work with dictionaries?
Thanks!
This construct is a different kind of for loop that runs over items in an Objective-C collection, rather than a C array. The first part defines an object that is being set to one element in the collection each run of the loop, while the second part is the collection to enumerate. For example, the code:
NSArray *array = [NSArray arrayWithObjects:#"foo", #"bar", nil];
for(NSString *string in array) {
NSLog(string);
}
would print:
foo
bar
It's defining an NSString *string that, each run of the loop, gets set to the next object in the NSArray *array.
Similarly, you can use enumeration with instances of NSSet (where the order of objects aren't defined) and NSDictionary (where it will enumerate over keys stored in the dictionary - you can enumerate over the values by enumerating over keys, then calling valueForKey: on the dictionary using that key).
It's extremely similar to the construct in C:
int array[2] = { 0, 1 };
for(int i = 0; i < 2; i++) {
printf("%d\n", array[i]);
}
which prints:
0
1
It's just a syntactical way of making the code more readable and hiding some of the fancy enumeration that goes into listing objects in an NSArray, NSSet, or NSDictionary. More detail is given in the Fast Enumeration section of The Objective-C 2.0 Programming Language document.
This is called fast enumeration. It loops through the array, setting key to each item. It's the same, functionally, as doing this:
NSString *key;
for ( NSInteger i = 0; i < [[ self keys ] count ]; i++ ) {
key = [[ self keys ] objectAtIndex:i ];
NSMutableArray *array = [self.names valueForKey:key];
NSMutableArray *toRemove = [[NSMutableArray alloc] init];
for (NSString *name in array)
{
if ([name rangeOfString:searchTerm
options:NSCaseInsensitiveSearch].location == NSNotFound)
[toRemove addObject:name];
}
if ([array count] == [toRemove count])
[sectionsToRemove addObject:key];
[array removeObjectsInArray:toRemove];
[toRemove release];
}
It's a for loop with one iteration for each key in the dictionary.
The for..in construct is called Fast enumeration. You can read more about it in Objective-C 2.0 Programming Guide.
How it works with an object depends on it's implementation of the NSFastEnumeration protocol. The NSDictionary class reference describes how it works with dictionaries:
On Mac OS X v10.5 and later, NSDictionary supports the NSFastEnumeration protocol. You can use the for…in construct to enumerate the keys of a dictionary, as illustrated in the following example.