NSArray With NSString Is This Even Possible? - iphone

I am trying to build a Grouped Sectioned View. I want to set an array as an object in the dictionary but I came across the empty array Issues.
Is this Even possible????? Is There a trick ????
#import "RootViewController.h"
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Get the specific Node for this row.
Nodes *nodes = (Nodes *)[nodesMArray objectAtIndex:indexPath.row];
// Create the Details View Controller and initialize it.
nodesDetailView *viewController = [[nodesDetailView alloc] initWithStyle:UITableViewStyleGrouped ];
[[self navigationController] pushViewController:viewController animated:YES];
// Set the title of the view to the nodes name
viewController.title = [nodes computer_name];
//Information
//Network Data
viewController.ipaddress= [nodes ipaddress];
viewController.subnet_mask= [nodes subnet_mask];
viewController.gateway= [nodes gateway];
viewController.domain_name= [nodes domain_name];
}
#import "nodesDetailViewController. h
#interface nodesDetailView : UITableViewController{
//Network Data
NSString *ipaddress;
NSString *subnet_mask;
NSString *gateway;
NSString *domain_name;
//Grouped
NSMutableArray *Keys;
NSMutableDictionary *Contents;
}
#property (nonatomic, retain) NSMutableArray *Keys;
#property (nonatomic, retain) NSMutableDictionary *Contents;
#property (nonatomic, retain) NSString *ipaddress;
#property (nonatomic, retain) NSString *subnet_mask;
#property (nonatomic, retain) NSString *gateway;
#property (nonatomic, retain) NSString *domain_name;
#end
#import "nodesDetailViewController. m
#synthesize .......
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
NSMutableArray *keys = [[NSMutableArray alloc] init];
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
NSString *network = #"Network Data";
NSString *product = #"Product Details";
//IS THIS POSSIBLE ??????? Because I get An Empty array
[contents setObject:[NSArray arrayWithObjects: ipaddress,subnet_mask, gateway, domain_name, nil] forKey:network];
return self;
}
Thank You In Advance.

All of those strings that you are adding to the array haven't even been allocated/initialized yet. That's why the array is empty. You can't just go: NSString *emptyString; and then go: [myArray addObject:emptyString];. Your strings are all empty.

Check the values u are passing from the table view. They maybe nil. I just used this much of data and i m getting correct NSLog.
NSMutableDictionary *contents = [[NSMutableDictionary alloc] init];
NSString *my = #"kk";
NSString *my1 = #"polko";
[contents setObject:[NSArray arrayWithObjects: my1,my, nil] forKey:#"o"];
NSLog(#"%#" , contents);

For Those Who are wondering: Problem Solved My code was fine. the problem was :
it was in the wrong place.
The Code Supposed to be in - (void)viewDidLoad and not in - (id)initWithStyle:
I want to thank everybody who took the time to look in to it.
I have no idea why i put the code there to begin with.
Thanx Again

Related

Leaky Custom Object for storing data from a plist

I have made a very simple custom object pictureData.
Here is the .h file
#import <Foundation/Foundation.h>
#interface pictureData : NSObject {
NSString *fileName;
NSString *photographer;
NSString *title;
NSString *license;
}
#property (nonatomic, retain) NSString *fileName;
#property (nonatomic, retain) NSString *photographer;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *license;
+(pictureData*)picDataWith:(NSDictionary*)dictionary;
#end
The .m file
#import "pictureData.h"
#implementation pictureData
#synthesize fileName;
#synthesize photographer;
#synthesize title;
#synthesize license;
+ (pictureData*)picDataWith:(NSDictionary *)dictionary {
pictureData *tmp = [[[pictureData alloc] init] autorelease];
tmp.fileName = [dictionary objectForKey:#"fileName"];
tmp.photographer = [dictionary objectForKey:#"photographer"];
tmp.title = [dictionary objectForKey:#"title"];
tmp.license = [dictionary objectForKey:#"license"];
return tmp;
}
-(void)dealloc {
[fileName release];
[photographer release];
[title release];
[license release];
}
#end
I then set up these objects in an array, like so:
NSString *path = [[NSBundle mainBundle] pathForResource:#"pictureLicenses" ofType:#"plist"];
NSArray *tmpDataSource = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *tmp = [[NSMutableArray alloc] init];
self.dataSource = tmp;
[tmp release];
for (NSDictionary *dict in tmpDataSource) {
pictureData *pic = [pictureData picDataWith:dict];
NSLog(#"%#", pic.title);
[self.dataSource addObject:pic];
}
Everything works smashingly. I have a table view which loads the proper picture images, and information, no problem. Upon running Instruments for leaks, I see that my pictureData object is leaks with every allocation.
I would assume that with having my object autoreleased I would not have to worry about manually allocating and deallocating them.
Perhaps is my issue that I use autorelease, which the autoReleasePool keeps a retain count of +1 and then when I add a pictureData object to my array, that also retains it? Thank you all for your time!
edit: Don't forget to call super! Thank you Sam!
Change dealloc to:
-(void)dealloc {
[fileName release];
[photographer release];
[title release];
[license release];
[super dealloc];
}
(call [super dealloc])
In your function, change the return value to include autorelease, like
+ (pictureData*)picDataWith:(NSDictionary *)dictionary
{
...
...
return [tmp autorelease];
}
When you add pictureData object to dataSource, you increase the retain count, so you should autorelease it while returning.
Hope it helps.

EXC_BAD_ACCESS on a NSMutableArray that contains a custom class

I receive I EXC_BAD_ACCESS but i can't understand why.
this is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
TDBadgedCell *cell = [[[TDBadgedCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
SubscriptionArray * element =[reader.subscriptions objectAtIndex:[indexPath row]];
[cell.textLabel setText:element.title]; // <--- error at this line of code
return cell;
}
reader.subscritions is NSMutableArray that contains 81 elements ( I'm sure verificated with a NSLog) but when I try to get set the title I have this error... why?
SubscritionArray is a custom class that contains 3 string and 1 int.
Custom class:
header
#import <Foundation/Foundation.h>
#interface SubscriptionArray : NSObject{
NSString *title;
NSString *source;
NSString *htmlUrl;
NSInteger count;
}
#property (nonatomic,retain) NSString *title;
#property (nonatomic,retain) NSString *source;
#property (nonatomic,retain) NSString *htmlUrl;
#property (nonatomic) NSInteger count;
#end
implementation:
#import "SubscriptionArray.h"
#implementation SubscriptionArray
#synthesize title,source,htmlUrl,count;
-(void)dealloc{
[title release];
[source release];
[htmlUrl release];
}
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super init]) {
title = [[decoder decodeObjectForKey:#"title"] retain];
source = [[decoder decodeObjectForKey:#"source"] retain];
htmlUrl = [[decoder decodeObjectForKey:#"htmlUrl"] retain];
//count = [decoder decodeIntForKey:#"count"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
if (title) [encoder encodeObject:title forKey:#"title"];
if (source) [encoder encodeObject:source forKey:#"source"];
if (htmlUrl) [encoder encodeObject:htmlUrl forKey:#"htmlUrl"];
//if (count) [encoder encodeInteger:count forKey:#"count"];
}
#end
EDIT
Tha's what I get
* -[__NSArrayM objectAtIndex:]: message sent to deallocated instance 0xe5a8260
And that's how I set the NSMutableArray
subscriptions = [[NSMutableArray alloc]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the
//documents directory:
NSString *fullFileName = [NSString stringWithFormat:#"%#/subscriptions", documentsDirectory];
[subscriptions removeAllObjects];
subscriptions = [NSKeyedUnarchiver unarchiveObjectWithFile:fullFileName];
I'd venture to say that your array of subscription elements isn't matching up with your row indexes (just a guess). Suggest that you set a debugger breakpoint immediately after you've declared 'element' and before you attempt to set the label. You should be able to see if you have actually obtained one of your SubscriptionArray objets...
The mutable array in reader.subscriptions is getting deallocated before you attempt to reference it in tableView:cellForRowAtIndexPath:. Make sure that the subscriptions array is properly retained or copied by the reader, and that you're not overreleasing it by sending an extra release or autorelease message somewhere. It might help to post the relevant code from the class of the reader instance.

Objective-C error while implementing class?

I have this class
#import <Foundation/Foundation.h>
#interface SubscriptionArray : NSObject{
NSString *title;
NSString *source;
NSString *htmlUrl;
}
#property (nonatomic,retain) NSString *title;
#property (nonatomic,retain) NSString *source;
#property (nonatomic,retain) NSString *htmlUrl;
#end
and the implementation file is this one:
#import "SubscriptionArray.h"
#implementation SubscriptionArray
#synthesize title,source,htmlUrl;
-(void)dealloc{
[title release];
[source release];
[htmlUrl release];
}
#end
When I use the class like in this example I get an EXEC_BAD_ACCESS error:
for (NSDictionary *element in subs){
SubscriptionArray *add;
add.title=[element objectForKey:#"title"]; //ERROR Happens at this line
add.source=[element objectForKey:#"htmlUrl"];
add.htmlUrl=[element objectForKey:#"id"];
[subscriptions addObject:add];
}
Can someone help me?
P.S. Subscriptions is a NSMutableArray
You need to allocate your SubscriptionArray object like so: SubscriptionArray *add = [[SubscriptionArray alloc] init];
Your for loop will therefore look something like this:
for (NSDictionary *element in subs){
SubscriptionArray *add = [[SubscriptionArray alloc] init];
add.title=[element objectForKey:#"title"];
add.source=[element objectForKey:#"htmlUrl"];
add.htmlUrl=[element objectForKey:#"id"];
[subscriptions addObject:add];
[add release];
}
You need to initialize your SubscriptionArray. i.e.
SubscriptionArray *add = [SubscriptionArray new];

Complex JSON as NSArray Datasource for a UITableView iOS

I tried almost everything before posting (google, Apple Dev Doc etc.). I hope I did not miss anything before posting..
I already built a working JSON <-> Webservice <-> iPhone login.
with the following code:
NSString *responseString = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]autorelease];
NSDictionary *jsonDict = [responseString JSONValue];
NSString *loginResult = [jsonDict valueForKey:#"LoginResult"];
loginResult is the name of the employee: e.g "Henning Wenger"
The corresponding JSON looks like this:
{"LoginResult":"S:00000412"}
Now I have a more complex task which I can´t manage to figure a way through:
I´m getting the following JSON from the webservice:
{"GetTeamPresentStatusResult"[
{"Firstname":"Steffen","Id":"00000456","IsPresent":"true","Lastname":"Polker"},
{"Firstname":"Erich","Id":"00000455","IsPresent":"true","Lastname":"Welter"},
{"Firstname":"Titus","Id":"00000454","IsPresent":"true","Lastname":"Sommerbeck"}, {"Firstname":"Ruediger","Id":"00000453","IsPresent":"true","Lastname":"Oelmann"},{"Firstname":"Heinz","Id":"00000452","IsPresent":"true","Lastname":"Radelfs"},{"Firstname":"Franz","Id":"00000451","IsPresent":"true","Lastname":"Wippermann"},{"Firstname":"Klaus-Dieter","Id":"00000450","IsPresent":"true","Lastname":"Just"},{"Firstname":"Alan","Id":"00000412","IsPresent":"true","Lastname":"Turing"},{"Firstname":"Konrad","Id":"00000138","IsPresent":"true","Lastname":"Zuse"},{"Firstname":"Marius","Id":"00000112","IsPresent":"true","Lastname":"Sandmann"}]}
My code for handling this starts with:
NSDictionary *jsonDict = [responseString JSONValue];
NSArray *teamStatus = [jsonDict objectForKey:#"GetTeamPresentStatusResult"];
[self BuildDataSource: nil :teamStatus];
teamStatus now contains 10 key/value pairs.
Here is how I tried to build up the datasource for my table:
- (void)BuildDataSource: (id) sender: (NSArray*)teamStatusData{
teamStatusMutableArray = [[NSMutableArray alloc]init];
teamStatusDataSection = [[NSArray alloc]initWithArray:teamStatusData];
teamStatusDictSectionOne = [NSDictionary dictionaryWithObject:teamStatusDataSection forKey:#"OrgUnits"];
[teamStatusMutableArray addObject:teamStatusDictSectionOne];
[tblView reloadData];
}
I can not manage to figure out which way to go from here to get the data how I need it.
Do I need different Arrays where one contains the firstname/value and another one that contains lastname/value? If yes, how do I do that?
Here are some lines I´ve tried so far which did not have helped:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
//First get the dictionary object
NSDictionary *dictionary = [teamStatusMutableArray objectAtIndex:indexPath.section];
NSString *testString = [dictionary valueForKey:#"Firstname"];
NSArray *testarray = [dictionary objectForKey:#"OrgUnits"];
NSString *test = [testarray JSONRepresentation];
test = [test stringByReplacingOccurrencesOfString:#"[" withString:#""];
test = [test stringByReplacingOccurrencesOfString:#"]" withString:#""];
NSDictionary *jsonDict = [test JSONValue];
}
What I need is to have a Datasource with the Employee Names that I can bind to a Table. From there I think I can make my way without additional help.
I´m coming from the .NET (C#) world and maybe this confuses me too much.
Thank you so much..
Henning
If you need further details please ask!
Details for SPtail:
Here is the .h file:
#import <UIKit/UIKit.h>
#import "RootViewController.h"
#import "EmployeeDetails.h"
#interface OrgUnitAA:NSObject {
NSString *FirstName;
NSString *Id;
NSString *IsPresent;
NSString *LastName;
}
#property (nonatomic, retain) NSString *FirstName;
#property (nonatomic, retain) NSString *Id;
#property (nonatomic, retain) NSString *IsPresent;
#property (nonatomic, retain) NSString *LastName;
#end
#interface TeamStatusView : UIViewController {
UITableView *tblView;
NSMutableArray *teamStatusMutableArray;
NSArray *teamStatusDataSection;
NSDictionary *teamStatusDictSectionOne;
UIViewController *EmployeeDetails;
UIViewController *RootViewController;
NSMutableData *responseData;
}
#property (nonatomic, retain) IBOutlet UITableView *tblView;
#property (nonatomic, retain) NSArray *teamStatusMutableArray;
#property (nonatomic, retain) NSMutableArray *dummyMutableArrayTimeQuota;
#property (nonatomic, retain) NSArray *teamStatusDataSection;
#property (nonatomic, retain) NSDictionary *teamStatusDictSectionOne;
#property (nonatomic, retain) IBOutlet UIViewController *RootViewController;
#property (nonatomic, retain) IBOutlet UIViewController *EmployeeDetails;
- (void)GetTeamStatus: id;
- (void)BuildDataSource: id: (NSArray*)teamStatusData;
#end
Hey the array returned by the web service contains dictionaries, which is obvious.
Instead of using different arrays for each property, you can create a class which extends NSObject and convert each dictionary so that you will have the objects inside an array instead of dictionaries. In this case:
#interface OrgUnit:NSObject {
NSString *FirstName;
NSNumber *Id;
bool IsPresent;
NSString *LastName;
}
//And all the properties here
After this you can convert dictionaries into object by using
OrgUnit *unit = [[OrgUnit alloc] init];
[unit setValuesForKeysWithDictionary:dictionary];
PS: The variable names in the object should be same as that of the keys in dictionary
I´ve found a solution.
This is the way I get to the data:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
NSDictionary *dictionary = [teamStatusMutableArray objectAtIndex:indexPath.section];
NSArray *teamStatus = [dictionary objectForKey:#"OrgUnits"];
NSEnumerator *e = [teamStatus objectEnumerator];
id object;
int i = 0;
while (object = [e nextObject]) {
if(i == indexPath.row)
{
NSString *firstname = [object valueForKey:#"Firstname"];
NSString *lastname = [object valueForKey:#"Lastname"];
NSString *fullname = [NSString stringWithFormat:#"%#%#%#", lastname, #", ", firstname];
cell.textLabel.text = fullname;
bool isPresent = [object valueForKey:#"IsPresent"];
if(isPresent == true)
{
cell.imageView.image = [UIImage imageNamed:#"GreenBall.png"];
}
else
{
cell.imageView.image = [UIImage imageNamed:#"RedBall.png"];
}
break;
}
i++;
}
[aiActivity stopAnimating];
self.aiActivity.hidden = true;
return cell;
}
Could be just a typo.
Change this:
teamStatusDictSectionOne = [NSDictionary dictionaryWithObject:teamStatusDataSection forKey:#"OrgUnits"];
To this:
teamStatusDictSectionOne = [NSDictionary dictionaryWithObjects:teamStatusDataSection forKey:#"OrgUnits"];
The change is -dictionaryWithObjects. Plural. Obj-C is kinda finicky about that stuff.
Also, you are referencing indexPath.section when you build the individual cells. I think you should be referencing the row for the cell. The row should correlate to your array index.
NSInteger row = [indexPath row];
NSDictionary *dictionary = [teamStatusMutableArray objectAtIndex:row];

how to sort an NSMutableArray of Arrays?

I'm trying to sort an array of a table view with no luck, this is how I'm trying to do it:
- (void) compare
{
NSMutableArray *temp = [[NSMutableArray alloc] initWithObjects: nil];
[temp addObjectsFromArray:[self displayedObjects]];
int a = [[self displayedObjects] count];
for (int i = 0; i < (a - 1); i++){
for (int j = 0; j <= (i^2); j++) {
NSString *temp1 = [temp objectAtIndex:i];
NSString *temp2 = [temp objectAtIndex:i+1];
if (temp1 > temp2) {
[movieIndex replaceObjectAtIndex:i withObject:temp2];
[movieIndex replaceObjectAtIndex:i+1 withObject:temp1];
}
}
}
[self movieIndex];
[[self tableView] reloadData];
}
displayedObjects is an array of array that the user can add new objects. this objects are movie instances in form of:
The tableview cell has the title of the movie. "in" that title there is a tableview with details about the movie. What i want to do is sort the displayed movies titles in ascending order but my code doesn't seem to work.
displayedObjects is a set of 3 NSStrings and 1 NSNumber. It gets objects form the following class:
#import <Foundation/Foundation.h>
#interface Movie : NSObject
{
NSString *_title;
NSString *_gender;
NSString *_location;
NSNumber *_publicationYear;
}
#property (nonatomic, retain) NSString *location;
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *gender;
#property (nonatomic, retain) NSNumber *publicationYear;
+ (id)movieWithTitle:(NSString *)title
gender:(NSString *)gender
year:(NSUInteger)year
location:(NSString *)location;
- (id)initWithTitle:(NSString *)title
gender:(NSString *)gender
year:(NSUInteger)year
location:(NSString *)location;
#end
Because no one has suggested it yet, and I personally love blocks, I'll suggest the block alternative to the same thing already suggested:
[myArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
...
}];
I made it work by using:
NSSortDescriptor *titleSorter= [[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES];
[movieIndex sortUsingDescriptors:[NSArray arrayWithObject:titleSorter]];