parsing txt from array to UILabel - objective-c

I'm actually starting to loose the will to live, this piece of code is driving me nuts!
I'm trying to get the content of mathspractice.txt into *myLabel
I'm using an array which is:
-(void)loadText
{
NSArray *wordListArray = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#”mathspractice” ofType:#”txt”]
encoding:NSMacOSRomanStringEncoding error:NULL] componentsSeparatedByString:#”\n”]];
self.theMathsPractice = wordListArray;
[wordListArray release];
}
and then I'm trying to pass it into *myLabel
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,100,960,40)];
myLabel.text = *theMathsPractice;
[myScrollView addSubview:myLabel];
[myLabel release];
}
Can anyone help?

It looks on quick inspection that your theMathsPractice is an NSArray, not an NSString, which is what you'd want to assign to the label's text property. You should at least format that array back into a string of some sort before assigning it to the label.
(Also not sure why you're dereferencing it with the * in the assignment-- I would think that would throw a compiler error, since naked non-reference Objective-C objects are not really allowed.)

I would use the following:
myLable.text = [theMathsPractice componentsJoinedByString:#" "]);

Related

NSMutableDictionary won't save data

hope someone can help me with a problem I've been wrestling with...
Using MapBox to develop a map-based app, and I want to attach an NSMutableDictionary to each of the map annotations to store additional data. I had it working but XCode kept throwing me warning about some of my data/object types, so I went through and tidied those up, and now it's broken. The idea is that on ViewDidLoad, the program runs through a set of plist dictionaries to set up each annotation correctly - that's still running okay, because my initial anno markers pop up with their correct settings. However rather than run back to the plist every time, I want to attach a dictionary to each annotation's userinfo property, which I can then use for toggling selection data and other functions. Here's my code:
NSDictionary *ExploreSteps = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"ExploreSteps" ofType:#"plist"]];
for (NSString *key in [ExploreSteps allKeys])
{
//Loop through keys for each anno
NSDictionary *thisStep = [ExploreSteps objectForKey:key];
NSNumber *annoIndex = [thisStep objectForKey:#"Index"];
NSNumber *isLive = [thisStep valueForKey:#"isLive"];
NSString *annoTitle = [thisStep objectForKey:#"Title"];
NSString *annoText = [thisStep objectForKey:#"Text"];
NSString *imagefile = [thisStep objectForKey:#"Imagefile"];
double longitude = [[thisStep objectForKey:#"Longitude"] doubleValue];
double latitude = [[thisStep objectForKey:#"Latitude"] doubleValue];
NSString *pagefile = [thisStep objectForKey:#"Pagefile"];
NSString *audiofile = [thisStep objectForKey:#"Audiofile"];
CLLocationCoordinate2D annoCoord = CLLocationCoordinate2DMake(latitude, longitude);
RMAnnotation *annotation = [[RMAnnotation alloc] initWithMapView:mapView coordinate:annoCoord andTitle:annoTitle];
annotation.annotationIcon = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:imagefile ofType:#"png"]];
annotation.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:annoIndex, #"index", isLive, #"isLive", annoTitle, #"annoTitle", annoText, #"annoText", imagefile, #"imagefile", pagefile, #"pagefile", audiofile, #"audiofile", nil];
NSLog(#"Title: %#",[annotation.userInfo objectForKey:#"annoTitle"]);
[mapView addAnnotation:annotation];
}
The NSLog should spit out the annoTitle string, but instead it's giving me a null every time, and the behaviour of the rest of the app also shows that info stored in the dictionary simply isn't "getting through".
Any ideas? Thanks in advance!
ETA: Modified code for initializing the dictionary (not that it seems to make any difference to the problem!):
NSMutableDictionary *myUserInfo = [[NSMutableDictionary alloc] initWithObjectsAndKeys:annoIndex, #"index", isLive, #"isLive", annoTitle, #"annoTitle", annoText, #"annoText", imagefile, #"imagefile", pagefile, #"pagefile", audiofile, #"audiofile", nil];
annotation.userInfo = myUserInfo;
NSLog(#"Title: %#",[annotation.userInfo objectForKey:#"annoTitle"]);
NSLog(#"Length: %u",[[annotation.userInfo allKeys] count]);
(Title now returns "(null)", while Length returns "1", if that's at all helpful...)
Almost certainly one of your objects is nil. You mention that allKeys] count] returns 1 so I can go further and say that your value for isLive is nil. Hence your original line:
[NSMutableDictionary dictionaryWithObjectsAndKeys:annoIndex, #"index", isLive, #"isLive", annoTitle, #"annoTitle", annoText, #"annoText", imagefile, #"imagefile", pagefile, #"pagefile", audiofile, #"audiofile", nil];
Acts exactly the same as:
[NSMutableDictionary dictionaryWithObjectsAndKeys:annoIndex, #"index", nil, #"isLive", annoTitle, #"annoTitle", annoText, #"annoText", imagefile, #"imagefile", pagefile, #"pagefile", audiofile, #"audiofile", nil];
And the dictionary takes annoIndex to be the final key-value pair.
I'd suggest that probably you want to take a mutable copy of thisStep and strip out the keys you don't want, then pass it along as the userInfo.
It's the way you are creating the NSMutableDictionary for userInfo. Take a look at this Difference between [[NSMutableDictionary alloc] initWithObjects:...] and [NSMutableDictionary dictionaryWithObjects:...]?
"
+dictionaryWithObjects: returns an autoreleased dictionary
-initWithObjects: you must release yourself
if you want the dictionary to persist as a instance variable, you should create it with an init method or retain an autoreleased version, either way you should be sure to release it in your dealloc method
"

not sure how I would do this with objectAtIndex [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
how to convert nsstring to uicolor?
not an objective-c programmer but am not sure if I can't do something like this. I know I'm returning a string value but just want a terse way of getting at these values:
NSMutableArray *colorsArray=[[NSMutableArray alloc] init];
[colorsArray addObject:#"whiteColor"];
[colorsArray addObject:#"blueColor"];
// val5 is either 0 or 1
[view setBackgroundColor:[UIColor [colorsArray objectAtIndex:val5]]];
Is this possible?
thx in advance
Why don't you store directly colors instead of NSString?
NSMutableArray *colorsArray=[[NSMutableArray alloc] init];
[colorsArray addObject:[UIColor whiteColor]];
[colorsArray addObject:[UIColor blueColor]];
if (val5 < colorsArray.count) // Doesn't hurt any to be safe, and this way you won't get a crash if something messes up your val5 at some point
{
// val5 is either 0 or 1
[view setBackgroundColor:[colorsArray objectAtIndex:val5]];
}
else
{
NSLog(#"Error - Color not expected - leaving color the way it is.")
}
You code as it is doesn't compile, syntax is invalid since you are trying to do [UIColor #"whiteColor"] which is not a valid syntax. You could use performSelector: but this is senseless unless you really need to store colors as strings.
Or if you must use NSString instances in the array:
NSMutableArray *colorsArray=[[NSMutableArray alloc] init];
[colorsArray addObject:#"whiteColor"];
[colorsArray addObject:#"blueColor"];
SEL colorSelector = NSSelectorFromString([colorsArray objectAtIndex:val5]);
[view setBackgroundColor:[UIColor performSelector:colorSelector]];
NSMutableArray *colorsArray = [[NSMutableArray alloc] init];
[colorsArray addObject:#"whiteColor"];
[colorsArray addObject:#"blueColor"];
UIColor *color = [UIColor performSelector:NSSelectorFromString([colorsArray objectAtIndex:1])];
view.backgroundColor = color;

Object name from String in Objective-C

i want to set the name of an object like UIButton from a string.
NSString *buttonName = [[NSString alloc] initWithString:#"someString"];
My goal is:
UIButton *someString = [[UIButton buttonWithType:UIButtonTypeCustom]retain];
how can i solve this?
You can't - variable names are resolved by the compiler well before any Objective-C code is executed. What you can do is maintain a map of strings to objects like buttons etc. using NSMutableDictionary:
NSString *string = #"someString";
[buttonMap setObject: [UIButton buttonWithType:UIButtonTypeCustom] forKey: string];
//...time passes...
[[buttonMap objectForKey: #"someString"] setEnabled: YES];

NSString EXC_BAD_ACCESS

I'm stuck with the following bit of code.
NSString *gridRef = [[NSString alloc] initWithFormat: #"%#", [converter LatLongToOSGrid: latLong]];
NSLog(#"Grid Ref: %#", gridRef);
self.answerLabel.text = [[NSString alloc] initWithFormat: #"%#", gridRef];
When I log gridRef, it displays the correct result. However, the line setting answerLabel.text causes an EXC_BAD_ACCESS error and the program crashes. IB is connected to the correct label, what is the problem?
Thanks
I've updated the code as follows:
- (IBAction)convertLatLong {
NSArray *latLong = [[NSArray alloc] initWithObjects: latTextField.text, longTextField.text, nil];
GridRefsConverter *converter = [[GridRefsConverter alloc] init];
NSString *gridRef = [[NSString alloc] initWithFormat: #"%#", [converter LatLongToOSGrid: latLong]];
NSLog(#"Grid Ref: %#", gridRef);
NSLog(#"Label: %#", self.answerLabel.text);
answerLabel.text = #"Yippy";
self.answerLabel.text = gridRef;
[gridRef release];
[converter release];
[latLong release];
}
answerLabel is initialised through #property #synthesize when the view controller is pushed onto the stack. (I don't know how it gets init'd apart from it's one of the magical things IB does for you. Or so I assume. I've used exactly the same method in other view controllers and have not had this issue.
I've found the culprits - the question is, how do I go about releasing them?
NSString *eString = [[NSString alloc] initWithFormat: #"%f", e];
NSString *nString = [[NSString alloc] initWithFormat: #"%f", n];
eString = [eString stringByPaddingToLength: (digits/2) withString: #"0" startingAtIndex: 0];
nString = [nString stringByPaddingToLength: (digits/2) withString: #"0" startingAtIndex: 0];
NSString *theGridRef = [letterPair stringByAppendingString: eString];
theGridRef = [theGridRef stringByAppendingString: nString];
[eString release];
[nString release];
return theGridRef;
and:
NSArray *gridRef = [[NSArray alloc] init];
gridRef = [gridRef arrayByAddingObject: [NSNumber numberWithDouble: E]];
gridRef = [gridRef arrayByAddingObject: [NSNumber numberWithDouble: N]];
gridRef = [gridRef arrayByAddingObject: [NSNumber numberWithInteger: 8]];
NSString *theGridRef = [[NSString alloc] initWithFormat: #"%#", [self gridRefNumberToLetter: gridRef]];
[gridRef release];
[theGridRef autorelease];
return theGridRef;
}
You should enable zombie detection by setting the environment variable NSZombieEnabled to YES, so you can see which object causes the bad access (don't forget to remove this again when you found the bug).
Also you can use Instruments to find the location where the object actually gets released. For this start a new Instruments session and use the "Allocations" instrument. In the instrument settings check "Enable NSZombie detection" and "Record reference counts". When running the session you will break where the error occurs and you see a record of all retains/releases.
One place where you can have a quick look if your object is incorrectly freed is in the -viewDidUnload method, where you should release the outlet and set it to nil. If you forget the latter and you access the outlet somehow, it will result in a EXC_BAD_ACCESS.
Edited to match your update:
The problem is that you are assigning eString (and nString) a new string which was alloc/init-ed. Then you override those in the next statements, because -stringByPaddingToLength: (as well as all the other -stringBy... methods) return a new and autoreleased string object. So you lost the reference to the old string which means that there is a memory leak. Additionally at the end you release the already autoreleased objects explicitly which causes your bad access.
Instead you should create autoreleased strings from the beginning ([NSString stringWithFormat:...]) and don't release them at the end.
Check if asnwerLabel is actually non-null. You should also change this line:
self.answerLabel.text = [[NSString alloc] initWithFormat: #"%#", gridRef];
To:
self.answerLabel.text = [NSString stringWithFormat: #"%#", gridRef];
Otherwise, you will end up with a memory leak in that line.
Maybe the label is not inited at that point in your code, try to check it. Why are you allocating a new NSString?
Just do:
self.label.text = gridRef;
[gridRef release];
how is answerLabel created? You might need to retain that. Or you possibly need to release some things (gridRef)?
I can't see any other issues with your code.
You can (and probably should) set your
answerLabel.text = gridRef;
gridRef is already an NSString, so you don't need to alloc it again.
EXC_BAD_ACCESS is usually a memory thing related to your retain/release count not balancing (or in my extensive experience of it :p).
Okay, the problem was trying to release NSStrings, so I've stopped doing that and the problem has been solved.
Can someone clarify how strings are retained and released. I was of the impression that:
string = #"My String"; is autoreleased.
NSString *string = [[NSString alloc] init...]; is not autoreleased and needs to be done manually.

Adding an object to an array read from a file

There is nothing in the file, but I add row1 to my array right after. NSLog tells me that the array is empty. Why isn't row1 added to the array? All of my other code is fine as far as I can tell. My app worked when I put hard values into the array. Now that I'm loading from a file, it doesn't work.
- (void)viewDidLoad {
//array value
//NSMutableArray *array;
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSMutableArray *array/*array*/ = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
NSDictionary *row1 = [[NSDictionary alloc] initWithObjectsAndKeys:#"Study", #"Task", #"2 hours", #"Length", #"4", #"Hours", #"0", #"Minutes", #"15", #"Tiredness", nil];
[array addObject: row1];
self.tasks = array;
NSLog(#"The contents of the array (file exists) is %#", array);
[array release];
[myTableView reloadData];
}
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification
object:app];
[super viewDidLoad];
}
Please help!
Thanks in advance,
Matt
Two possibilities I see:
The object containing this code is not correctly set up as the table's datasource.
A file exists at the path you're looking at, but its contents cannot be parsed as an array. In this case, you would hit the first branch of the if-clause, but initWithContentsOfFile: would return nil. You could easily diagnose this by checking for nil after calling that method.
make sure the tableview delegate and datasource is set properly
It is difficult to answer your question. Here are two suggestions:
When you post code here, clean it up. Remove comments and format it nicely.
Show all your code. In your code there could be many things wrong. Maybe the self.tasks property is not correct. Maybe you did not correctly setup the dataview. Maybe you did not implement the correct table view delegate methods. It is hard to tell.
Also, try ruling out the most basic things. For example if you are in doubt whether that array is setup correctly, then simply print it:
NSLog(#"The contents of the array is %#", array);