iOS Terminating app due to uncaught exceptions when parsing JSON object - ios

This is a new error since I started learning to develop for iOS a week ago and I totally don't have a clue what is causing it and why the app suddenly crushes. There must be something wrong in my code if you may have a look at it and kindly suggest how to fix this run-time bug.
*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (1) beyond bounds (1)'
*** First throw call stack:
(0x2514c49f 0x32902c8b 0x2514c3e5 0x25079a6d 0xd01cb 0x2863f9fb 0x2863f9a1 0x2862a613 0x28747781 0x287fdc6b 0x286041ad 0x286390c1 0x2863899d 0x2860f15d 0x28882ab9 0x2860dbb9 0x25112d57 0x25112167 0x251107cd 0x2505e3c1 0x2505e1d3 0x2c45c0a9 0x2866dfa1 0xa3911 0x32e82aaf)
libc++abi.dylib: terminating with uncaught exception of type NSException
Here is my code snippet
- (IBAction)changeIns:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *) sender;
NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;
if (selectedSegment == 0) {
//toggle the correct view to be visible
NSLog(#"Clicked");
jsonData = [tArray objectAtIndex:0];
self.displayInsurer.text=jsonData[#"insurerName"];
}
else if (selectedSegment == 1) {
//toggle the correct view to be visible
jsonData = [tArray objectAtIndex:1];
self.displayInsurer.text=jsonData[#"insurerName"];
}
else if (selectedSegment == 2) {
//toggle the correct view to be visible
}
else if (selectedSegment == 3) {
//toggle the correct view to be visible
}
else if (selectedSegment == 4) {
//toggle the correct view to be visible
}
else if (selectedSegment == 5) {
//toggle the correct view to be visible
}
else if (selectedSegment == 6) {
//toggle the correct view to be visible
}
else if (selectedSegment == 7) {
//toggle the correct view to be visible
}
else if (selectedSegment == 8) {
//toggle the correct view to be visible
}
}
-(void)setVariableFromNetwork
{
// NSInteger success = 0;
#try {
NSString *post =[[NSString alloc] initWithFormat:#"uid=%#&tag=getVehicleInfo",[[NSUserDefaults standardUserDefaults] stringForKey:#"userID"]];
NSLog(#"PostData: %#",post);
NSURL *url=[NSURL URLWithString:#"URL"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
//[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Response code: %ld", (long)[response statusCode]);
if ([response statusCode] >= 200 && [response statusCode] < 300)
{
NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Response ==> %#", responseData);
NSError *error = nil;
tArray = [NSJSONSerialization JSONObjectWithData:urlData options:kNilOptions error:&error];
NSLog(#"objects %#", [tArray description]);
NSLog(#"first object %#", [tArray objectAtIndex:0]);
NSDictionary *jsonData = [tArray objectAtIndex:0];
NSLog(#"dictionary %#", [jsonData description]);
NSLog(#"vehicle %#", jsonData[#"vehicleMake"]);
NSLog(#"Vehicle Number %#", jsonData[#"vehicleRegNo"]);
int count = [tArray count];
NSMutableArray *mySegments = [[NSMutableArray alloc] initWithCapacity:count];
for (int i = 0; i<count; i++) {
jsonData = [tArray objectAtIndex:i];
//NSString * desc = jsonData[#"vehicleMake"],"-", jsonData[#"vehicleMake"];
[mySegments addObject:jsonData[#"vehicleMake"]];
[mySegments addObject:jsonData[#"vehicleRegNo"]];
}
[self.carSegment removeAllSegments];
self.carSegment = [self.carSegment initWithItems:mySegments];
}
}
#catch (NSException * e) {
NSLog(#"Exception: %#", e);
[self alertStatus:#"Sign in Failed." :#"Error!" :0];
}
}

Your array only has 1 item (at index 0) and you're trying to access an item at index 1 here:
jsonData = [tArray objectAtIndex:1];

So, as KerrM's answer points out, this exception is happening because we're trying to access an index which doesn't exist in our array.
jsonData = [tArray objectAtIndex:1];
This is exactly what the bolded part of the exception you put in the question is saying.
So what should we do to fix it? Well, I don't find the other answers that offer solutions to be particularly that great. In all of them, we're still accessing a hard-coded array index. Sure, we're putting a check in to make sure it exists, but very, very rare should it be that you actually need to directly access an array index that you can hardcode.
Instead, there are these solutions:
Any time we need to access the first object in an array, we can safely do so using the firstObject method, which will always return the object at index 0, unless the array is empty, in which case it will return nil. If you access an array's 0th index when it is empty, you still get the index out of bounds exception.
[myArray firstObject];
Any time we need to access the last object in an array, we can safely do so using the lastObject method. This is the same as firstObject, except it looks at the last index of the array. No matter how many objects in the array, this will return the last one. And if it's an empty array, it will safely return nil.
[myArray lastObject];
And finally, the scenario most applicable to your situation, when we need to loop over all the elements in an array, we should do so using some form of fast enumeration. The easiest to use and most common way of doing this which will work in most scenarios is simply to use a forin loop. There are several advantages to using a forin loop. For a start, they're faster than a regular for loop. But there are other advantages too. We're not accessing our array by index (which helps make the loop faster) and that means we can't have an index out of bounds exception. Finally though, it just looks a whole lot cleaner and more readable than a regular for loop.
for (NSDictionary *jsonData in tArray) {
[mySegments addObject:jsonData[#"vehicleMake"]];
[mySegments addObject:jsonData[#"vehicleRegNo"]];
}
In terms of answering the question of how come tArray only has one object in it, you'll have to look at the JSON data itself. In fact, you should have already done this. There's no guarantee that the JSON data is an array of dictionaries. Most JSON or XML data I see typically has a dictionary as the root object. But the point is that the method signature looks like this:
+ (id)JSONObjectWithData:(NSData *)data
options:(NSJSONReadingOptions)opt
error:(NSError **)error
The return type is id. When Apple released Swift and iOS 8, they also went through Objective-C and eliminated nearly all uses of id, replacing most with instancetype. They're moving away from the use of id. But this one remains. Why? Because it must. In this case, we're using id because we can't use instancetype. We're using id because the return value could be an NSArray, or it could be an NSDictionary. (It can probably also be an NSNumber or NSString object, perhaps.)
So we should definitely be clear on what the expected JSON looks like before we write the code to grab data out of it...

You must first check the number of items in NSArray before accessing them:
if (tArray.count > count) {
jsonData = [tArray objectAtIndex:count-1];
self.displayInsurer.text=jsonData[#"insurerName"];
}
like this!!! It will never crash then...
All the best...

You have an array and you have 1 element in it. Now you are trying to extract 2nd element from it, [0] is first, and [1] is second.
Error-->> jsonData = [tArray objectAtIndex:i];
Check First wether it contains items are more than one
if([tArray count]== 1 && selectedSegment == 0){
jsonData = [tArray objectAtIndex:0];
else if ([tArray count]> 1 && selectedSegment == 1) {
//toggle the correct view to be visible
jsonData = [tArray objectAtIndex:1];
self.displayInsurer.text=jsonData[#"insurerName"];
}

Related

Corruption of NSString or encoding issue in Objective C

Please see code below:
+ (void)splashDataFromJSON:(NSData *)objectNotation error:(NSError **)error
{
NSError *localError = nil;
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
if (localError != nil) {
*error = localError;
}
NSMutableArray* btms = [[NSMutableArray alloc] init];
NSMutableDictionary* btmManufacturerResolutionDictionary = [[BTMCache sharedManager] btmManufacturerResolutionDictionary];
NSArray *results = [parsedObject valueForKey:#"results"];
NSLog(#"Count %d", parsedObject.count);
NSString* imageBaseUrl = [[parsedObject valueForKey:#"general"] valueForKey:#"image_base_url"];
imageBaseUrl = [imageBaseUrl stringByAppendingString:#"hdpi/"];
NSString* splashImageName = [[[parsedObject valueForKey:#"general"] valueForKey:#"splash"] valueForKey:#"img"];
NSString* splashAdvertiserURL = [[[[parsedObject valueForKey:#"general"] valueForKey:#"splash"] valueForKey:#"url"] copy];
NSMutableString* appendedString = [[NSMutableString alloc] init];
for(int i =0 ;i<[splashAdvertiserURL length]; i++) {
char character = [splashAdvertiserURL characterAtIndex:i];
printf(&character);
sleep(0.1);
if (character != "!")
{
[appendedString appendFormat:#"%c", character];
}
}
[[SplashData sharedManager] setSplashAdvertiserURL:appendedString];
[[SplashData sharedManager] setSplashImageName:splashImageName];
splashAdvertiserURL = [[SplashData sharedManager] splashAdvertiserURL];
}
The point of interest is in splashAdvertiserURL. When I receive this data and print it out using po, it comes out as "https://radar.com/ref/go/84/". This is fine and what was expected. When I look at the incoming data in JSONLint it looks like this:
"general": {
"image_base_url": "https:\/\/radar.com\/img\/manufacturers\/",
"splash": {
"img": "image1.png",
"url": "https:\/\/radar.com\/ref\/go\/84\/"
}
},
As you can see, further on I put the NSString into a singleton with an NSString property. Nothing abnormal here. I then proceed to retrieve it to see that all is ok. Further to this the program continues. In another class I wish to retrieve this information, and when I try and do that, it throws EXC_BAD_ACCESS. There appears to be garbage in there.
I then put in a loop in the code as you can see to print out the characters one at a time. Very curiously, when I print that out using po I get:
https://
r
a
d
ar.com/ref/go/8 4!/"
Exactly in that format. If I then proceed to hardcode the string https://radar.com/ref/go/84/ - including escape characters and everything, then all works fine. No issues. If I handle a normal string incoming without escape characters it stores fine in the singleton as well, no issue. enter code here
I am pretty stumped here as to what is going on. Can someone assist?
Thank you
For URL you received as string you need to encode before use it to in your app. Have a look at below code:
NSString *sampleUrl = #"https:\/\/radar.com\/ref\/go\/84\/";
NSString *encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];

Dictionary initialized in AppDelegate has nil value in UIViewController

I am using open weather API to get live weather data and displaying it in a UIViewController. However I make the http request in AppDelegate. So I made the API request in AppDelegate in a method called weatherForcast(), converted the JSON response to a NSDictionary object, and printed the object to the console just to make sure everything worked fine, and it did.
NSString *urllink = [NSString stringWithFormat:#"http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&appid=%#&units=metric", lat, lng, WEATHERAPIKEY];
NSURL *jsonURL = [NSURL URLWithString:[self urlEncodeValue:urllink]];
NSString *jsonDataString = [[NSString alloc]initWithContentsOfURL:jsonURL];
NSData *jsonData = [jsonDataString dataUsingEncoding:NSUTF16StringEncoding];
NSLog(#"This is jsonURL:%#", jsonURL);
NSError *err = nil;
if(jsonData == nil)
{
NSLog(#"Error laoding jsonData");
}
else
{
self.weatherInfo = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &err];
NSLog(#"This is weatherInfo dictionary:%#", self.weatherInfo);
}
The dictionary is perfect.
Then in the UIViewController in viewDidLoad I call the method weatherForecast() and then call a method UpdateTemperature() which sets all the texts of the labels to data in the dictionary. Here is the code in the method UpdateTemperature:
NSLog(#"This is the weatherInfo dictionary: %#", appDel.weatherInfo);
if([appDel.weatherInfo count] > 0 && appDel.isNetworkAvailable)
{
NSLog(#"Went into weatherInfo.count > 0");
lblCondition.text = [NSString stringWithFormat:#"condition:%#", [[[appDel.weatherInfo valueForKey:#"weather"] objectAtIndex:0] valueForKey:#"description"]];
lblHumidity.text = [NSString stringWithFormat:#"humidity:%#", [[appDel.weatherInfo valueForKey:#"main"] valueForKey:#"humidity"]];
lblTemperature.text = [NSString stringWithFormat:#"%# Celsius", [[appDel.weatherInfo valueForKey:#"main"] valueForKey:#"temp"]];
imgWeather.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#", WEATHERCONDITIONIMGURL, [appDel.weatherInfo valueForKey:#"icon"]]]]];
lblDegree.hidden = FALSE;
[getTemp stopAnimating];
}
else
{
lblDegree.hidden = TRUE;
}
All the labels will only be set if the dictionary has at least one object within it, which it should. But it turned not not too. So I printed the dictionary, and got nil.
In AppDelegate when I printed the dictionary it was fine, but than in viewDidLoad when I printed the same dictionary it turned out to be nil. What is happening?
It's likely that when viewDidLoad gets called, weatherInfo has not been initialized yet. If it requires an http call the data may have not returned yet and therefore when you access it in viewDidLoad there is no object to access. You might want to try reconfiguring where you make your http request and create weatherInfo.
when you create object of appdelegate then all variable of appdelegate is reinitialized so it return nil. Just put your code into a fuction and simply return a dictionary
plz try this,
-(NSDictionary *) getWeatherInfo
{
NSString *urllink = [NSString stringWithFormat:#"http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&appid=%#&units=metric", 10.0, 10.0, #"api"];
NSURL *jsonURL = [NSURL URLWithString:[self urlEncodeValue:urllink]];
NSData *jsonData = [NSData dataWithContentsOfURL:jsonURL];
NSLog(#"This is jsonURL:%#", jsonURL);
NSError *err = nil;
NSDictionary *weather_info=[NSDictionary dictionary];
if(jsonData == nil)
{
NSLog(#"Error laoding jsonData");
}
else
{
weather_info = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &err];
NSLog(#"This is weatherInfo dictionary:%#", weather_info);
}
return weather_info;
}

iOS - Converting UTF8 data from backend and displaying incorrectly

I am writing an iOS application that receives data from the backend. I parse the NSData object (objectNotation) as below.
Everything works fine until I receive a special character in the one entity, which is:
"Test já"
When I receive this and I debug parsedObject, it shows "type" to be "Test j\U00e1"
So this is obviously some Unicode/UTF8 issue. I then proceeded to look all over stack overflow, and found various potential solutions to this and tried them all, to no avail.
NSString *stringTest = [[NSString alloc] initWithData:objectNotation
encoding:NSUTF8StringEncoding]; --> does not work
NSString * test2 = [NSString
stringWithCString:[stringTest cStringUsingEncoding:NSUTF8StringEncoding]
encoding:NSASCIIStringEncoding]; --> does not work
I have tried every single encoding that Obj has to offer, and it either returns the character as \U00e1, or nil, or a bunch of garbage.
I have battled with this for hours so it is a good time to post now. I appreciate any assistance. Thank you.
Code is below:
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
NSMutableArray *btms = [[NSMutableArray alloc] init];
NSArray *results = [parsedObject valueForKey:#"results"];
NSLog(#"Count %d", results.count);
NSLog(#"Count %d", parsedObject.count);
[parsedObject enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
BTM *btm = [[BTM alloc] init];
NSLog(#"%# => %#", key, value);
btm.number = key;
btm.latitude = [value valueForKey:#"lat"];
btm.longitude = [value valueForKey:#"long"];
NSString* temp = [value valueForKey:#"type”];
}
Set "application/x-www-form-urlencoded; charset=UTF-8" as 'Content-Type' while receiving data from the backend.
[requestUrl setValue:#"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];

getting "*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber compare:]: nil argument'"

Though we have lot of people asked same question , none of the answers are helping to fix my issue. So here is my code ,
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *text = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Response: %#", text);
//The NSJSONSerialization method to transform the NSData responseObject into a dictionnary does work
NSJSONSerialization *jsonResponse = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];
//This NSLog makes the app crash with an unrecognized selector sent error
NSLog(#"JSON: %#",jsonResponse);
NSArray *result1=(NSArray *)[jsonResponse valueForKeyPath:#"result"];
NSLog(#"result1: %#",result1);
NSMutableString *shipPrice =[[NSMutableString alloc]init];
NSMutableString *freeLimitString =[[NSMutableString alloc]init];
if(result1!=Nil && ![result1 count]==0)
{
for (int i=0; i<result1.count; i++)
{
NSNumber *totalShippingPrice = [[result1 objectAtIndex:i] valueForKeyPath:#"totalShippingPrice"];
if( totalShippingPrice != nil && totalShippingPrice && [totalShippingPrice isEqualToNumber:0]&& [totalShippingPrice intValue]==0) // ISSUE LINE
{
shipPrice = (NSMutableString*)#"FREE";
} } } }
I kept breakpoint and exactly its happening in this above line. Im new to AFNetworking. Im not sure how to fix it. Help me with working code sample :) Thanks
You need to use this:
[totalShippingPrice isEqualToNumber: [NSNumber numberWithInt:0]]
In the line that crashes.
You need to compare the object with another one of the same type, if you use 0 is the same as if you were sending nil to it, so you need to create a NSNumber as I wrote.
Or just do:
[totalShippingPrice intValue] == 0

iOS - App crash without error during loop process

during a loop process, my App crash without error. The array count is equal to 175260. With profiler I don't have leaks, so I don't know why the App exit, maybe the CPU usage 100% during a lot of time?
Thank you for your help.
Just this code following crash the App :
for(unsigned int i = 0; i <14;i++)
{
if(findSensor[i]==YES)
{
for(unsigned int j = 1; j <[array count];j++)
{
#autoreleasepool {
if([[[[array objectAtIndex:j] componentsSeparatedByString:#";"] objectAtIndex:0] isEqualToString:[NSString stringWithFormat:#"%d",10*(i+1)]])
{
//Code here
}
}
}
}
}
The full code is :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:#"%#/%#",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase];
NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:fileName];
NSFileHandle *output = [NSFileHandle fileHandleForReadingAtPath:[NSString stringWithFormat:#"%#/%#10",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase]];
if(output == nil)
{
NSManagedObjectContext *context = [self managedObjectContext];
_recordlocal = [NSEntityDescription insertNewObjectForEntityForName:#"RECORD" inManagedObjectContext:context];
_recordlocal.date = [ibNavSettings interfaceSettings].selectedFileToDataBase;
NSData *inputData = [NSData dataWithData:[fh readDataToEndOfFile]];
NSString *inputString = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];
NSArray *array = [[NSArray alloc] initWithArray:[inputString componentsSeparatedByString:#"\n"]];
for(unsigned int i = 0; i <14;i++)
{
if(findSensor[i]==YES)
{
[[NSFileManager defaultManager] createFileAtPath:[NSString stringWithFormat:#"%#/%#%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)] contents:nil attributes:nil];
NSMutableString *saveString = [[NSMutableString alloc] init];
int count = 0;
for(unsigned int j = 1; j <[array count];j++)
{
#autoreleasepool {
if([[[[array objectAtIndex:j] componentsSeparatedByString:#";"] objectAtIndex:0] isEqualToString:[NSString stringWithFormat:#"%d",10*(i+1)]])
{
[saveString appendString:[array objectAtIndex:j]];
[saveString appendString:#"\n"];
if(i == 0)
count++;
progress++;
pourcent = progress/total;
load = pourcent*100;
if(load%5==0)
[self performSelectorInBackground:#selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];
}
}
}
[saveString writeToFile:[NSString stringWithFormat:#"%#/%#%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)] atomically:YES encoding:NSUTF8StringEncoding error:nil];
if(i == 0)
_recordlocal.count = [[NSNumber alloc] initWithInt:(count/50)];
}
}
_recordlocal.load = [[NSNumber alloc] initWithBool:YES];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Core data error %#, %#", error, [error userInfo]);
abort();
}
I would guess that your app is crashing without a readable exception because it is running out of available RAM, especially since you indicated that it is running through a large number of iterations.
For a test, I would recommend doing what Rikkles suggests with the autorelease pool. In addition, since the value of i (and as a result the comparison string) rarely changes, I would create that string outside the j loop as well. This would avoid the creation of a lot of extra strings laying around.
Beyond that, since it appears that you are looking for a string at the beginning of a string that is delimited by a semicolon, I would recommend instead of doing componentsSeparatedByString and then examining element zero that you use the NSString method hasPrefix to check for the condition you are looking for.
Here is an example:
for(unsigned int i = 0; i <14;i++)
{
NSString *searchString = [NSString stringWithFormat:#"%d;", 10*(i+1)];
if(findSensor[i]==YES)
{
for(unsigned int j = 1; j <[array count];j++)
{
if([[array objectAtIndex:j] hasPrefix:searchString])
{
//Code here
}
}
}
}
(I hope this compiles and runs, if it doesn't it should require more than minor tweaks. I am away from my Mac right now.)
If this doesn't help, then something going on inside //Code here must be the culprit.
Why are you creating [array count] autoreleasepools? What's the point of creating so many of them? It could crash because of that. Put the #autoreleasepool outside the for loop.
The only reason I could think that you would do that is if you create so many transient objects inside each iteration of the for loop that you'd want to get rid of them as soon as you got out of the iteration. But there are other ways to do that, including reusing those objects within each iteration.
First suggestion
Just use fast enumeration for the inner loop, you aren't actually using the index 'j' for anything
https://developer.apple.com/library/mac/documentation/General/Conceptual/DevPedia-CocoaCore/Enumeration.html
Second suggestion
Put some NSLog's in place, it will slow everything down, but you need to figure out what point you are failing at. That will help point everyone in the right direction.
Third suggestion
Actually use NSError objects and output their value if an error is thrown:
NSError *writeError = nil;
[saveString writeToFile:[NSString stringWithFormat:#"%#/%#%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)]
atomically:YES
encoding:NSUTF8StringEncoding
error:&writeError];
if(error != nil) NSLog(#"error writing file: %#", [[writeError userInfo]description]);
Fourth suggestion
You appear to try to be updating the UI from a background thread. This will not work or will cause a crash. UI code can only be called from a main thread. So dont do this:
[self performSelectorInBackground:#selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];
If you are already on a background thread this will probably crash because you are creating threads on threads on threads. You instead would want to call:
[self performSelectorOnMainThread:#selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];
Fifth suggestion
You may be going over the maximum length for NSString (it's big but I did it once on accident before). You should probably just be appending the file on each iteration of the loop instead, so you don't have an ever growing NSMutableString:
NSString *path = [NSString stringWithFormat:#"%#/%#%d",documentsDirectory,[ibNavSettings interfaceSettings].selectedFileToDataBase,10*(i+1)]
NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:filePath];
NSData *newLine = [#"\n" dataUsingEncoding:NSUTF8StringEncoding];
for(NSString *rowString in array)
{
if([[[rowString componentsSeparatedByString:#";"] objectAtIndex:0] isEqualToString:[NSString stringWithFormat:#"%d",10*(i+1)]])
{
NSData *stringData = [rowString dataUsingEncoding:NSUTF8StringEncoding];
[fh truncateFileAtOffset:[fh seekToEndOfFile]];
[fh writeData:stringData];
[fh truncateFileAtOffset:[fh seekToEndOfFile]];
[fh writeData:newLine];
if(i == 0)
count++;
progress++;
pourcent = progress/total;
load = pourcent*100;
if(load%5==0)
[self performSelectorOnMainThread:#selector(changeUI:)withObject:[NSNumber numberWithFloat:(pourcent)]];
}
}
}
And this has the added benefit of helping you ditch the autoreleasepools
This was invalid
If your array does in fact have 175260 rows, that is probably your issue. You are looping using unsigned int as your index var. Unsigned ints in c only have a max value of 65535. Use an unsigned long int, max 4294967295.

Resources