Delete characters in a string in Objective-C - objective-c

I've an NSOpenPanel called oPanel. From it, I get the path of a folder. As I use URLs (instead of the deprecated filenames) I want to get rid of the beginning (file://localhost).
But I have the following error that I can't understand:
2011-07-29 18:01:45.587 RedimV3[12857:407] -[NSURL length]: unrecognized selector sent to instance 0x1023543d0
2011-07-29 18:01:45.588 RedimV3[12857:407] -[NSURL length]: unrecognized selector sent to instance 0x1023543d0
Here is the code:
NSArray *files = [oPanel URLs];
NSLog(#"before: %#", [files objectAtIndex:0]);
NSMutableString *temp = [[NSMutableString alloc] initWithString:[files objectAtIndex:0]];
[temp deleteCharactersInRange:NSMakeRange(0,15)];
NSLog(#"after: %#",temp);
The first NSLog works, the second doesn't.
I will be glad if you can help me, thanks.

[files objectAtIndex:0] is probably an NSURL, not an NSString. Try using [[files objectAtIndex:0] path] instead. In fact, if you use -path you won't even have to worry about the file:// part.

If you just want the file name then you would do as #jtbandes said with a minor correction to use the lastPathComponent instance method of NSString
Quick and dirty version
NSArray *files = [oPanel URLs];
NSLog(#"before %#",[files objectAtIndex:0]);
NSString *fileName = [[[files objectAtIndex:0] path] lastPathComponent];
NSLog(#"after :%#",fileName);
More readable code version
NSArray *files = [oPanel URLs];
NSURL *file = [files objectAtIndex:0];
NSLog(#"before %#",file);
NSString *localPath = [file path];
NSString *fileName = [localPath lastPathComponent];
NSLog(#"after :%#",fileName);

You need to turn the NSURL into a string...
NSURL *myURL = [files objectAtIndex:0];
NSMutableString *string = [NSMutableString stringWithString:[myURL absoluteString]];
[string deleteCharactersInRange:NSMakeRange(0,15)];
NSLog(#"after: %#", string);

Related

how to edit a plist programmatically in xcode 5 iOS 7?

how can I edit or change a value string from:
in this plist I need change or Set "NO" in Enabled Value from Item 2, I see a lot examples, but not working, or are deprecated, or don't use ARC, any idea or example code? please help guys
EDIT#1: I try this (not work)
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
path = [path stringByAppendingPathComponent:#"List.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:CONTENT_DEFAULT ofType:PLIST];
[fileManager copyItemAtPath:sourcePath toPath:path error:nil];
}
NSArray* newContent = [[NSArray alloc]initWithContentsOfFile:path];
NSDictionary *Dict = [[NSDictionary alloc]initWithDictionary:[newContent objectAtIndex:2]];
[Dict setValue:#"NO" forKey:#"Enabled"];
[Dict writeToFile:path atomically:YES];
NOTE: not work, it crashes send me:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSDictionaryI 0x15de7ff0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key Enabled.', or Im wrong in something?
EDIT #2 new Try
NSString *path = [[NSBundle mainBundle] pathForResource:#"List" ofType:#"plist"];
NSString *savingPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSArray* newContent = [[NSArray alloc]initWithContentsOfFile:path];
NSMutableDictionary *Dict = [[NSMutableDictionary alloc]initWithDictionary:[newContent objectAtIndex:2]];
[Dict setValue:#"NO" forKey:#"Enabled"];
savingPath = [savingPath stringByAppendingPathComponent:#"Modified.plist"];
[Dict writeToFile:savingPath atomically:YES];
NSLog(#"newContent:%#",newContent);
NSArray *newnew = [[NSArray alloc]initWithContentsOfFile:savingPath];
NSLog(#"newnew:%#",newnew);
NOTE: now print me a crash:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (3) beyond bounds (2)'
All you have to do is to use NSMutableDictionary instead of a regular dictionary to modify stuff. You have to always check that the object you are editing is there.
To get the right path for the plist you created in Xcode you need to use:
NSString *path = [[NSBundle mainBundle] pathForResource:#"List" ofType:#"plist"];
You might actually want to save that file into the app's document directory. So you would use the following path for saving the content:
NSString *savingPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
savingPath = [savingPath stringByAppendingPathComponent:#"Modified.plist"];
[Dict writeToFile:savingPath atomically:YES];
Well, in your case the solution would be the following (when you have Dictionary as a member of Array):
NSString *path = [[NSBundle mainBundle] pathForResource:#"List" ofType:#"plist"];
NSArray *newContent = [[NSArray alloc]initWithContentsOfFile:path];
//iterating through all members since all of them has the string "YES" which should be replaced, otherwise, you will need to create a separate dictionary for each member
for ((i = 0; i < [newContent count]; i++)){
//here you take the member (dictionary) of the array
NSDictionary *dictOfArray = [newContent objectAtIndex:i];
[dictOfArray objectForKey:#"Enabled"]=#"NO";
}
//if you update the same pList you can use the same path (otherwise use another path)
[newContent writeToFile:path atomically:YES];
So, it works now.

write NSString to file

I'm trying to write a string to a file and store that in the applicationSupport folder within my app. But my NSLog() statement doesn't log anything in the debugger. I have tried to go through it with the debugger, and i can see that the content is nil, so i'm guessing that's why it's not outputting anything, but i don't know why it's set to nil. Can anybody see my mistake?
NSString *document = [[[[[[[[description stringByAppendingString:#" "]stringByAppendingString:focus]stringByAppendingString:#" "]stringByAppendingString:level]stringByAppendingString:#" "]stringByAppendingString:equipment]stringByAppendingString:#" "]stringByAppendingString:waterDepth];
//NSLog(#"%#", document);
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *supportDirectory = [paths objectAtIndex:0];
//filename
NSString *filename = [NSString stringWithFormat:[_nameTextField.text stringByAppendingString:#".txt"], supportDirectory];
[document writeToFile:filename atomically:NO encoding:NSStringEncodingConversionAllowLossy error:nil];
NSString *content = [[NSString alloc]initWithContentsOfFile:filename usedEncoding:nil error:nil];
NSLog(#"%#", content);
filename is wrong. It should have the following format: "directory/file.extension". You can use the methods stringByAppendingPathComponent and stringByAppendingPathExtension to construct such a string.
NSString *filename = [supportDirectory stringByAppendingPathComponent:[_nameTextField.text stringByAppendingPathExtension:#"txt"]];
Also, as a side note, the first line should be rewritten using stringWithFormat like this:
NSString *document = [NSString stringWithFormat:#"%# %# %# %# %#", description, focus, level, equipment, waterDepth];
You have wrong initialize filename. It should be:
NSString *filename = [NSString stringWithFormat:#"%#/%#", supportDirectory,[_nameTextField.text stringByAppendingString:#".txt"]];
it will works! Good luck:)
The
NSString *filename = [NSString stringWithFormat:[_nameTextField.text stringByAppendingString:#".txt"], supportDirectory];
is wrong. It should be:
NSString *filename = [NSString stringWithFormat:"%#%#",[_nameTextField.text stringByAppendingString:#".txt"], supportDirectory];

NSMutabel 2 dimensional array not working

i'm pulling a 2 dimensional array from a remote server:
- (NSMutableArray*)qBlock{
NSURL *url = [NSURL URLWithString:#"http://wsome.php"];
NSError *error;
NSStringEncoding encoding;
NSString *response = [[NSString alloc] initWithContentsOfURL:url
usedEncoding:&encoding
error:&error];
const char *convert = [response UTF8String];
NSString *responseString = [NSString stringWithUTF8String:convert];
NSMutableArray *sample = [responseString JSONValue];
return sample;
}
and putting them into:
NSMutableArray *qnBlock1 = [self qBlock];
NSString *answer1 = [NSString stringWithFormat:[[qnBlock1 objectAtIndex:0]objectAtIndex:1]];
answer = [[NSMutableDictionary alloc]init];
[answer setObject:answer1 forKey:#"1"];
question1.text = [[qnBlock1 objectAtIndex:0] objectAtIndex:0];
label1a.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:2];
label1b.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:3];
label1c.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:4];
label1d.text = [[qnBlock1 objectAtIndex:0]objectAtIndex:5];
I received this error during runtime
-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6c179502012-04-30 09:43:50.794 AppName[371:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6c17950'
Is this due to syntax issue for 2 dimensional array?
You're not getting back a multi-dimensional array. You're getting back an array of NSDictionary objects. The error you got indicates that you're trying to send the message objectAtIndex: to an NSDictionary object, which fails since it has no such selector.
Update:
After chatting on the side, it became apparent that the following was true:
The user was using the SBJson library to parse the return value from his php web service.
The return value was either:
An NSDictionary with each key being the text representation of its (non-index-based) location in the list (#"1", #"2", etc...) and each value being an NSArray of NSString objects, or
An NSArray of NSString objects (seems to be the way a single "answer" returns)
Here's the code I supplied to let him iterate through his return value:
NSURL *url = [NSURL URLWithString:#"{his url}"];
NSError *error;
NSStringEncoding encoding;
NSString *response = [[NSString alloc] initWithContentsOfURL:url usedEncoding:&encoding error:&error];
const char *convert = [response UTF8String];
NSString *responseString = [NSString stringWithUTF8String:convert];
NSLog(#"%#", responseString);
SBJsonParser *parser = [[SBJsonParser alloc] init];
id sample = [parser objectWithString:responseString];
if ([sample isKindOfClass:[NSDictionary class]]) {
for (id item in sample) {
NSLog(#"%#", [item description]);
NSArray *subArray = [sample objectForKey:item]; // b/c I know it's an array
for (NSString *str in subArray) {
NSLog(#"item: %#", str);
}
}
} else if ([sample isKindOfClass:[NSArray class]]) {
for (NSString *str in sample) {
NSLog(#"item: %#", str);
}
}
Hope it helps, J!
I think from your error message, you're sending objectAtIndex to a dictionary. NSDictionary doesn't have such a method. You should use objectForKey instead.

Memory leak in NSMutableArray, can't autorelease

I am having trouble releasing tempArray below... tempArray is a leak and I have tried return [tempArray autorelease] and it causes a crash. Does anyone know how to get rid of the memory leak in tempArray?
+(NSMutableArray*) returnTheArray:(NSString*)thePath forTheKey:(NSString*)theKey {
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSString *plistPath;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
NSString *testString = [thePath stringByAppendingString:#".plist"];
plistPath = [rootPath stringByAppendingPathComponent:testString];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle mainBundle] pathForResource:thePath ofType:#"plist"];
}
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization
propertyListFromData:plistXML
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&errorDesc];
if (!temp) {
CCLOG(#"Error reading plist: %#, format: %d", errorDesc, format);
}
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithArray:[temp objectForKey:theKey]];
return tempArray;
}
Well, the problem is that returnTheArray is not a name that the Analyzer will recognize as returning a retained value -- this is why it complains. So either you rename the method or return an autoreleased value. But if the latter you need to make sure that the "consumer" of the returned value appropriately deals with it -- retaining it if the value must persist beyond the next autorelease pool drain operation.
try:
NSMutableArray *tempArray = [NSMutableArray arrayWithArray:[temp objectForKey:theKey]];

Objective-C file i/o error

- (IBAction)sendMessage:(id)sender
{
NSString* conversationFile = [#"~/" stringByAppendingPathComponent:#"conversation.txt"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:conversationFile];
if (fileExists == FALSE)
{
[self doShellScript:#"do shell script \"cd ~/; touch conversation.txt\""];
}
NSString *conversationContent = [[NSString alloc] stringWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];
NSString *myMessage = [[messageBox stringValue]copy];
NSString *combinedContent = [NSString stringWithFormat:#"%# \r\n %#", conversationContent, myMessage];
[[[myConversationBox textStorage] mutableString] setString: combinedContent];
[combinedContent writeToFile:#"~/conversation.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}
The above code presents the following error
2011-07-07 21:38:08.703
iMessages[86493:903]
-[NSPlaceholderString stringWithContentsOfFile:encoding:error:]:
unrecognized selector sent to instance
0x100111690
2011-07-07 21:38:08.704
iMessages[86493:903]
-[NSPlaceholderString stringWithContentsOfFile:encoding:error:]:
unrecognized selector sent to instance
0x100111690
stringWithContentsOfFile:encoding:error: is a class method of NSString, not an instance method, so you don't need to (shouldn't) alloc it first.
NSString *conversationContent = [NSString stringWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];
Use initWithContentsOfFile in place of stringWithContentsOfFile or remove the alloc call. So have:
NSString *conversationContent = [[NSString alloc] initWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];
or
NSString *conversationContent = [NSString stringWithContentsOfFile:#"~/conversation.txt" encoding:NSUTF8StringEncoding error:NULL];