Parsed TouchXML XML file crashes when reading NSString - objective-c

I'm able to successfully parse the contents of a XML file using TouchXML, but when I try to read an individual NSString, from the NSMutableArray that stores the parsed content, the iPhone app crashes.
My NSLog shows me that the file has been parse as it should, giving this output:
(
{
href = "mms://a19349.l412964549958.c41245496.f.lm.akamaistream.net/D/194359/4125596/v0001/reflector:49944";
},
{
href = "mms://a4322.l4129624350471.c414645296.a.lm.akamaistream.net/D/473432/4129566/v0001/reflector:546441";
} )
Here is the code I'm using to do the parsing:
NSMutableArray *res = [[NSMutableArray alloc] init];
.... Parsing happens here ....
Then I try to retrieve the string from the NSMutableArray, using this code (and the app crashes when trying to read this line of code, posted below NSMutableString *string1 = [NSMutableString stringWithString:url];
NSString *url = [[NSString alloc] init];
url = [res objectAtIndex:0];
NSMutableString *string1 = [NSMutableString stringWithString:url];
[string1 deleteCharactersInRange: [string1 rangeOfString: #"href = "]];
[string1 deleteCharactersInRange: [string1 rangeOfString: #";"]];
NSLog(#"Clean URL: %#", string1);
Please, how can I solve this problem? Thank you!

TouchXML returns you an array of NSDictionaries. In order to extract string you need to take value from this NSDictionary:
NSString *url = [[res objectAtIndex:0] objectForKey:#"href"];

Related

Objective-C Split a String and get last item

I have a string like so:
NSString *path = #"\\fake\aaa\bbb\ccc\ddd\eee.pdf";
and I split the string into an array like so:
NSArray *array = [path componentsSeparatedByString:#"\"];
Now there are two things I need here.
I need a string with everything except eee.pdf
I need the last item in the array as a string (eee.pdf)
How would I do this?
Just for fun, there is a little-known way to get an NSURL with its benefit from a windows file path
NSString *path = #"\\\\fake\\aaa\\bbb\\ccc\\ddd\\eee.pdf";
NSURL *url = CFBridgingRelease(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)path, kCFURLWindowsPathStyle, false));
NSString *fileName = url.lastPathComponent;
NSString *parentDirectory = url.URLByDeletingLastPathComponent.path;
Finally you have to convert parentDirectory back to windows path style (backslashes).
But if you mean POSIX paths used in OS X, it's much easier
NSString *path = #"/fake/aaa/bbb/ccc/ddd/eee.pdf";
NSURL *url = [NSURL fileURLWithPath:path];
NSString *fileName = url.lastPathComponent;
NSString *parentDirectory = url.URLByDeletingLastPathComponent.path;
I think you're trying to get the filepath and filename from a full path. There are better ways of doing that. But since you simply asked for the question, here's my answer. Please note that this is not the best approach. In addition, you have to escape the backslashes by using a preceding backslash.
NSString *path = #"\\fake\\aaa\\bbb\\ccc\\ddd\\eee.pdf";
NSArray *array = [path componentsSeparatedByString:#"\\"];
NSMutableArray *removedArray = [[NSMutableArray alloc] init];
for(int i=0; i< array.count -1; i++){
[removedArray addObject:[array objectAtIndex:i]];
}
NSString *joinedString =[removedArray componentsJoinedByString:#"\\"];
NSString *fileName = [array lastObject];
NSLog(#"Path: %#", joinedString);
NSLog(#"Filename: %#", fileName);
For the last element use the lastObject property of the NSArray.
For a string without the last element use subarrayWithRange: using array.count-1 for the NSRange length.
Then join the remaining array with componentsJoinedByString:.
NSString *fileName = [array lastObject];
NSArray *newArray = [array subarrayWithRange:NSMakeRange(0, array.count-1)];
NSString *directoryPath = [newArray componentsJoinedByString:#"\\"];

How to convert NSData which contains a line break to a NSString

The following code works perfectly to convert the NSData that I got from a URL/JSON file to a NSString, EXCEPTION MADE by the cases that data contains line breaks!
What's wrong with my code?
My Code:
NSError *errorColetar = nil;
NSURL *aColetarUrl = [[NSURL alloc]initWithString:#"http://marcosdegni.com.br/petsistema/teste/aColetar3.php"];
NSString *aColetarString = [NSString stringWithContentsOfURL:aColetarUrl encoding:NSUTF8StringEncoding error:&errorColetar];
NSLog(#"NSString: %#", aColetarString);
if (!errorColetar) {
NSData *aColetarData = [aColetarString dataUsingEncoding:NSUTF8StringEncoding];
self.arrayAColetar = [NSJSONSerialization JSONObjectWithData:aColetarData options:kNilOptions error:nil];
}
NSLog(#"arrayAColetar %#", self.arrayAColetar);
Log Results:
**NSString**: [{"id_atendimento":"2","observacoes":"ABC-Enter-->
DEF-Enter-->
GFH-END"},{"id_atendimento":"1","observacoes":"123Enter-->
345Enter-->
678End"}]
**arrayAColetar** (null)
As you can see my bottom line is an empty array :(
Thanks in advance!
By checking the error message hidden under 'error:nil' I found a "Unescaped control character around character" issue and implemented the code below from Unescaped control characters in NSJSONSerialization
and got a new 'cleaned' string.
- (NSString *)stringByRemovingControlCharacters: (NSString *)inputString {
NSCharacterSet *controlChars = [NSCharacterSet controlCharacterSet];
NSRange range = [inputString rangeOfCharacterFromSet:controlChars];
if (range.location != NSNotFound) {
NSMutableString *mutable = [NSMutableString stringWithString:inputString];
while (range.location != NSNotFound) {
[mutable deleteCharactersInRange:range];
range = [mutable rangeOfCharacterFromSet:controlChars];
}
return mutable;
}
return inputString;
}

Conversion from decrypted NSData to NSDictionary fails

I have to encrypt and scramble a NSDictionary and then unscramble and decrypt in another method. I have followed the instructions from Securely storing keys in iOS Application except that I'm not using a PLIST file to fill the NSDictionary values, but NSString values that are being inputed in the program and I'm doing this targeting OSX
The program can be divided in 3 parts:
Encryption: Encrypts the NSDictionary and returns a base64encoded NSString
Scramble: Scrambles the base64encoded key among the values of the previous NSString
Unscramble and Decryption
My problem is in the last decryption. The unscramble works just fine, but the decryption seems to produce NSData that can't be convertible into the original NSDictionary
Encryption
What I'm doing for encryption is:
Initialising a NSDictionary
Converting it to NSData via NSPropertyListSerialization and format NSPropertyListXMLFormat_v1_0
Encrypting this data using RNCryptor and a key
Returning the base64 representation of this NSData as NSString
The code for this part is:
+(NSString *)encrypt:(NSString *)firstValue secondValue:(NSString *)secondValue andKey:(NSString *)key;
{
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:[[NSArray alloc] initWithObjects:firstValue, secondValue, nil] forKeys:[[NSArray alloc] initWithObjects:#"first", #"second", nil]];
NSData *data = [NSPropertyListSerialization dataFromPropertyList:dictionary format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];
NSData *encryptData = [RNEncryptor encryptData:data withSettings:kRNCryptorAES256Settings password:key error:nil];
return [encryptData base64EncodedString];
}
Scramble
The second part of the process is to scramble the key in base64 among the characters of the data, I'm doing this by:
Converting the key to NSData using -(NSData *)dataUsingEncoding:
Converting this NSData to a base64encoded NSString
Inserting char of this NSString into a NSMutadedString in a particular order
Returning NSString from this NSMutadedString to be decrypted later
Here's the code for the scramble part:
+(NSString *)scrambleStrings:(NSString *)firstValue secondValue:(NSString *)secondValue andKey:(NSString *)key;
{
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
key = [keyData base64EncodedString];
// String from the first method
NSString *encrypt = [self encrypt:firstValue secondValue:secondValue andKey:key];
NSArray *myOrder = [self mySortAlgorithm:key];
NSMutableString *mutableEncrypt = [NSMutableString stringWithString:encrypt];
for(int i=0; i<[myOrder count];i++)
{
unichar c = [key characterAtIndex:i];
int index = [[myOrder objectAtIndex:i] intValue];
[mutableEncrypt insertString:[NSString stringWithCharacters:&c length:1] atIndex:index];
}
return [NSString stringWithString:mutableEncrypt];
}
Decryption
The third part consists of testing if I can decrypt and unscramble it to the original NSDictionary and NSString key. It basically consists of:
Retrieve the scrambled NSString from the second method
Separating the scrambled key from the dictionary NSData from the previous NSString
Decode the base64encode key (Works for sure 'till here)
Decode the base64encoded dictionary data
Decrypt the previous data using RNCryptor using the decoded key
Initialising a NSDictionary using the data from the last step
Output the NSDictionary values via NSLog
And Here's the code for this last part:
+(BOOL)testScrambleWithFirstValue:(NSString *)firstValue secondValue:(NSString *)secondValue andKey:(NSString *)key;
{
NSString *scrambledAndEncryptedKeys = [self scrambleFirstValue:firstValue secondValue:SecondValue andKey:key];
NSArray *myOrder = [self mySortAlgorithm:key];
NSMutableString *encryptedDictionary = [[NSMutableString alloc] init];
NSMutableString *encryptedKey = [[NSMutableString alloc] init];
for (int i=0; i<scrambledAndEncryptedKeys.length; i++) {
char c = [scrambledAndEncryptedKeys characterAtIndex:i];
if ([myOrder doesContain:[NSNumber numberWithInt:i]]) {
[encryptedKey appendFormat:#"%c", c];
} else {
[encryptedDictionary appendFormat:#"%c",c];
}
}
NSString *decryptedKey = [[NSString alloc] initWithData:[NSData dataFromBase64String:[NSString stringWithString:encryptedKey]] encoding:NSUTF8StringEncoding];
NSString *base64DataStr = [[NSString alloc] initWithData:[NSData dataFromBase64String:[NSString stringWithString:encryptedDictionary]] encoding:NSUTF8StringEncoding];
NSData *decryptedData = [RNDecryptor decryptData:[base64DataStr dataUsingEncoding:NSUTF8StringEncoding] withPassword:decryptedKey error:nil];
NSPropertyListFormat xmlFormat;
NSDictionary *decryptedDictionary = [NSPropertyListSerialization propertyListWithData:decryptedData options:NSPropertyListImmutable format:&xmlFormat error:nil];
//Outputs NULL
NSLog(#"decryptedDictionary:%#", decryptedDictionary);
//Just to simplify I'm returning YES here
return YES;
}
The problem is, that the last NSLog outputs a NULL value. Which makes me think that the NSData is not being decrypted.
I've been hammering my head over this since yesterday morning, so all the help is appreciated. Thanks in advance

Objective-C - Works with strings, find a substring with NSRange

I'm working with the strings and i have a little problem that i'm not understanding. In fact, i have a string like this: "ALAsset - Type:Photo, URLs:assets-library://asset/asset.JPG?id=168BA548-9C81-4B08-B69C-B775E5DD9341&ext=JPG" and i need to find the string between "URLs:" and "?id=" . For doing this, i'm trying to create a new string using the NSRange. In this mode i give the first index and the last index that i need, but it seems not working.
Here there is my code:
NSString *description = [asset description];
NSRange first = [description rangeOfString:#"URLs:"];
NSRange second = [description rangeOfString:#"?id="];
NSString *path = [description substringWithRange: NSMakeRange(first.location, second.location)];
It return to me this kind of string: "URLs:assets-library://asset/asset.JPG?id=168BA548-9C81-4B08-B69C-B775E5DD9341&ext=JPG". Is it correct? I'm expecting to obtain "assets-library://asset/asset.JPG" string.
Where i'm doing wrong? Is there a better way to do this?
I have followed this url for help: http://www.techotopia.com/index.php/Working_with_String_Objects_in_Objective-C
Thanks
Try this range:
NSMakeRange(first.location + first.length, second.location - (first.location + first.length))
Don't parse the ALAsset description string! If the description ever changes your code breaks. Use the methods ALAsset and NSURL provide you. First, get the dictionary of URLs (mapped by asset type) through the valueForProperty: method. Then, for each URL, get the absoluteString and remove the query string from it. I got the string you were looking for by placing the following code in the application:didFinishLaunchingWithOptions: method from the single-view iPhone app template.
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
NSDictionary *URLDictionary = [asset valueForProperty:ALAssetPropertyURLs];
for (NSURL *URL in [URLDictionary allValues]) {
NSString *URLString = [URL absoluteString];
NSString *query = [URL query];
if ([query length] > 0) {
NSString *toRemove = [NSString stringWithFormat:#"?%#",query];
URLString = [URLString stringByReplacingOccurrencesOfString:toRemove withString:#""];
NSLog(#"URLString = %#", URLString);
}
}
}];
} failureBlock:^(NSError *error) {
}];
NSRange first = [description rangeOfString:#"URLs:"];
gives you the position of the U, so you need to take first.location+5 to get the start position of assets-library.
NSRangeMake(loc,len) takes a starting location loc and a length, so you need to use second.location-first.location-5 to get the length you are looking for.
Adding it all up, replace the last line with:
NSRange r = NSMakeRange(first.location+5, second.location-first.location-5);
NSString *path = [description substringWithRange:r];

Converting array of xml elements to an array of floats?

I have the following problem:
I am parsing a XML file, that contains a few "chas" elements. I save them in an array - arrayBegin. How to convert every object of the array to float ? I am a newbie, so I am really sorry for the dumb question. Thanks in advance! Here is my code:
NSString *dayToString = [NSString stringWithFormat:#"http://pik.bg/TV/bnt1/02.04.2013.xml"];
NSURL *url = [NSURL URLWithString:dayToString];
NSData *webData = [NSData dataWithContentsOfURL:url];
// every <chas> element from the xml file
NSString *xPathQueryBegin = #"//elem/chas";
TFHpple *parserBegin = [TFHpple hppleWithXMLData:webData];
NSArray *arrayBegin = [parserBegin searchWithXPathQuery:xPathQueryBegin];
NSLog (#"%d", [arrayBegin count]);
By this:
NSMutableArray *floatArray=[NSMutableArray new];
for(NSString *string in arrayBegin){
floatArray[floatArray.count]=#([string floatValue]);
}