UICollectionView didSelectItemAtIndexPath crash in IOS - ios

Please guide me something about path.
NSIndexPath *index = [[self.collectionView indexPathsForSelectedItems]objectAtIndex:0];
_assetVersion = assetVer;
_bookPosition = [[bookList objectAtIndex:index.row]bookPosition];
_bookId = [[bookList objectAtIndex:index.row]bookID];
bookPath = [[bookList objectAtIndex:index.row]bookPath];
_downloadURLbook = [[bookList objectAtIndex:index.row]downloadURL];
NSLog(#"%#",_bookPosition);
cell.bookId = _bookId;
NSLog(#"%#",bookPath);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *stringURL = [NSString stringWithFormat:#"http://powershelf-dev.3viewsolution.com/dhl/webservice/book_extract.php?main_menu=%#&language=%#&id=%#",_checkType,_checkLang,(_bookPosition)];
NSURLResponse *response = nil;
NSError *error = nil;
NSURL *url = [NSURL URLWithString:stringURL];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *urlConnection = [[NSURLConnection alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
[self connection:urlConnection didReceiveResponse:response];
[self connection:urlConnection didReceiveData:data];
dispatch_async(dispatch_get_main_queue(), ^{
//code for check data
});
});
I don't know this one why alway crash like this
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[DownloadedBookDetail bookPosition]: unrecognized selector sent to instance 0x146cf4a0'
But when i go with image from web service it's work. if i use bookIndex = indexPath; without code
NSIndexPath *index = [[self.collectionView indexPathsForSelectedItems]objectAtIndex:0];
_assetVersion = assetVer;
_bookPosition = [[bookList objectAtIndex:index.row]bookPosition];
_bookId = [[bookList objectAtIndex:index.row]bookID];
bookPath = [[bookList objectAtIndex:index.row]bookPath];
_downloadURLbook = [[bookList objectAtIndex:index.row]downloadURL];
it's will work also. But i need to use data from database check data with Web service.
I need to use bookIndex = indexPath; with web service
I'm go check with this
if([db isDownloaded:bookName bookVersion:[bookVersion floatValue]]){
[self performSegueWithIdentifier:#"reader" sender:self];
}
else{
[self startDownload];
}
Thanks for any Idea.

Related

XML Parser blocking main thread and dispatch_async crashing app

i am developing an application and in this app i am loading xml data in a uitableview and that table view call parse method after every 5 secs and reload uitable to load new data. Everything was working fine but app got stuck when parsing starts after 5 sec so i decided to implement dispatch_async in parse method but after that application is crashing like after 5 sec whenever app reload uitable. here is my code.
- (void) Parse{
previusCount = rssOutputData.count;
rssOutputData = [[NSMutableArray alloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *post =[[NSString alloc] initWithFormat:#"https://messages_%#.xml",[[NSUserDefaults standardUserDefaults] stringForKey:#"xmls_id"]];
NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:post]];
xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
[xmlParserObject setDelegate:self];
dispatch_async(dispatch_get_main_queue(), ^{
[xmlParserObject parse];
[messageList reloadData];
if (previusCount != rssOutputData.count) {
NSInteger bottomRow = [rssOutputData count] - 1; // this is your count's array.
if (bottomRow >= 0) {
///////getting to latest msg/////////////
NSIndexPath *indexPathnew = [NSIndexPath indexPathForRow:bottomRow inSection:0];
[self.messageList scrollToRowAtIndexPath:indexPathnew atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
});
});
}
Method through which i am sending a message to the xml data file.
- (IBAction)sendClicked:(id)sender {
[messageText resignFirstResponder];
if ( [messageText.text length] > 0 ) {
NSString *rawStr;
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"userType"] == 1) {
rawStr = [NSString stringWithFormat:#"data=%#&user_id=%#&session_id=%#", messageText.text, [[NSUserDefaults standardUserDefaults] stringForKey:#"therapist_id"],[[NSUserDefaults standardUserDefaults] stringForKey:#"xmls_id"]];
} else{//////In case of Patient
rawStr = [NSString stringWithFormat:#"data=%#&user_id=%#&session_id=%#", messageText.text, [[NSUserDefaults standardUserDefaults] stringForKey:#"patient_id"],[[NSUserDefaults standardUserDefaults] stringForKey:#"xmls_id"]];
}
NSData *data = [rawStr dataUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:#"http://do_add_message.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:data];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSLog(#"responseData: %#", responseData);
//////////////////////
[self Parse];
}
messageText.text = #"";
}
And the Error which i am getting is:
Print your array. Check it twice. I think you are getting an empty array. Print every object in the console which you get from server and which you parse. So you will get idea.
Update:
Just reload the table data on the main thread and don't parse data on it. like:
dispatch_async(dispatch_get_main_queue(), ^{
[messageList reloadData];
});
Put the other code outside the main thread.

My app is crashing when updating my table view

I am doing a database based application. My app needs to update a database table and simultaneously it needs to update the table view i.e. generated based on that particular database table.
Here's is the code i have written
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.courses.count;
}
-(void)viewWillAppear:(BOOL)animated {
self.usernameLBL.text = [NSString stringWithFormat:#"Welcome, %#", self.del.username];
[self loadCourses];
// NSLog(#"The courses count is %d", self.courses.count);
}
-(void)loadCourses {
NSString * stringUrl = [NSString stringWithFormat:"Some URL";
NSURL * uRL = [NSURL URLWithString:[stringUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:uRL];
NSError * error;
NSData * results = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
self.courses = [NSJSONSerialization JSONObjectWithData:results options:0 error:&error];
NSLog(#"The courses array count is %d", self.courses.count);
[self.tableView reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSDictionary * dict = self.courses[indexPath.row];
cell.textLabel.text = dict[#"name"];
cell.detailTextLabel.text = dict[#"id"];
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.courses = [[NSMutableArray alloc] init];
self.del = [[UIApplication sharedApplication] delegate];
NSString * strURL = [NSString stringWithFormat:"Some URL";
// NSLog(#"The username is %#", self.del.username);
NSURL * url = [NSURL URLWithString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSError * error;
NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
// NSLog(#"The data is %#", data);
NSDictionary * result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
// NSLog(#"The error is %#", error);
// NSLog(#"The value returned is %#", result[#"image"]);
if(![result[#"image"] isEqualToString:#"empty"]){
NSString * urlLocation = result[#"image"];
self.adminIMG.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[urlLocation stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]]];
}
// Do any additional setup after loading the view.
}
- (IBAction)addNewCourse:(id)sender {
NSString * strURL = [NSString stringWithFormat:"Some URL";
NSURL * url = [NSURL URLWithString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSError * error;
NSData * results = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:results options:0 error:&error];
if([dict[#"response"] isEqualToString:#"success"]) {
NSLog(#"New course added");
UIAlertView * success = [[UIAlertView alloc] initWithTitle:#"New course added successfully" message:#"You successfully added a new course" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[success show];
}else {
NSLog(#"Course not added");
}
[self.courses removeAllObjects];
[self viewDidLoad];
[self viewWillAppear:YES];
}
And i got this error.
Error: Evaluation[13335:60b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray objectForKeyedSubscript:]: unrecognized selector sent to instance 0xb7d26d0'
I tried many solutions available on the internet but those are not working for me. Anyone can help me, please. Thanks in advance :)
your issue might be here
[self.courses removeAllObjects];
[self viewDidLoad];
[self viewWillAppear:YES];
you don't have to clear your array, try this:
function:
- (void)addCourse{
NSString * strURL = [NSString stringWithFormat:"Some URL";
NSURL * url = [NSURL URLWithString:
[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSError * error;
NSData * results = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:&error];
NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:results
options:0 error:&error];
if([dict[#"response"] isEqualToString:#"success"]) {
NSLog(#"New course added");
UIAlertView * success = [[UIAlertView alloc]
initWithTitle:#"New course added successfully"
message:#"You successfully added a new course"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[success show];
}else {
NSLog(#"Course not added");
}
}
Your IBAction keep it simple there you don't want to fire off life cycle event from an IBAction instead call the methods you need not to mention that it is not a good idea to call viewDidLoad before viewWillAppear Method...
- (IBAction)addNewCourse:(id)sender {
[self addCourse];
[self loadCourses];
}
first you check the array data it valid or not .(put break point and check it)
and i think u got error because u still not convert integer to string .
i replace this line in to tableview cellForRowAtIndexPath:
cell.detailTextLabel.text = dict[#"id"];
to replace
cell.detailTextLabel.text =[NSString stringWithFormat:#"%d",dict[#"id"]];
Its may be very helpful to you Thanks.
I think your problem is here.. your targeting AppDelegate as self.delegate
self.del = [[UIApplication sharedApplication] delegate];
And AppDelegate runs onetime at start of application only that's why your are getting error

How to Check Web service data with button?

I need to know something about button and web service ,normally I'm use Uicollectionview for show data from web service by indexPath.item but if I don't use Uicollectionview It's possible? to pass and get data from web service.
Here's code
-(IBAction)ttButton:(id)sender
{
bookName = #"test";
bookVersion = [[bookList objectAtIndex:indexPath.row]bookVersion];// when I use this it's will crash.
_bookPosition = [[bookList objectAtIndex:indexPath.row]bookPosition];
bookId = #"1";
bookPath = #"test001";
pageAmount = 2;
mainMenu = #"test";
// downloadURL = [[bookList objectAtIndex:indexPath.row]downloadURL];
// pageAmount = [[bookList objectAtIndex:indexPath.row]pageAmount]; I want to go like this. but indexPath I can use only in collection view
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *stringURL = [NSString stringWithFormat:#"http://tlf/testdata/webservice/book_extract.php?main_menu=test&language=en&id=%#",(_bookPosition)];
NSURLResponse *response = nil;
NSError *error = nil;
NSURL *url = [NSURL URLWithString:stringURL];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *urlConnection = [[NSURLConnection alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
[self connection:urlConnection didReceiveResponse:response];
[self connection:urlConnection didReceiveData:data];
[db saveAssetVersion:_assetVersion];
if([db isDownloaded:bookId bookVersion:[bookVersion floatValue]]){
[self performSegueWithIdentifier:#"test" sender:self];
}
else{
[self startDownload];
}
});
});
}
Please Advice for any Idea. Thank you very very much.
I dont think you code to get the data is even being called in the case of Button. Anyway, you need to set the delegate of your NSURLConnection class to the class where fetching code is.
Essentially, there is no difference at all using UICollectionView or UIButton. That is just the difference of how user interacts with the system. The code to download and update should be seperate and should be called by both similarly.

Why does my array get cleared out by GCD dispatch to main queue?

I have an app that has a tableviewcontroller with this viewDidLoad:
- (void)viewDidLoad{
[super viewDidLoad];
// begin animating the spinner
[self.spinner startAnimating];
[SantiappsHelper fetchUsersWithCompletionHandler:^(NSArray *users) {
self.usersArray = [NSMutableArray array];
for (NSDictionary *userDict in users) {
[self.usersArray addObject:[userDict objectForKey:#"username"]];
}
//Reload tableview
[self.tableView reloadData];
}];
}
The Helper Class method is this:
+(void)fetchUsersWithCompletionHandler:(Handler)handler {
NSString *urlString = [NSString stringWithFormat:#"http://www.myserver.com/myApp/fetchusers.php"];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];
[request setHTTPMethod: #"GET"];
__block NSArray *usersArray = [[NSArray alloc] init];
//A
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Peform the request
NSURLResponse *response;
NSError *error = nil;
NSData *receivedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error) {
// Deal with your error
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"HTTP Error: %d %#", httpResponse.statusCode, error);
return;
}
NSLog(#"Error %#", error);
return;
}
NSString *responseString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
usersArray = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSASCIIStringEncoding] options:0 error:nil];
if (handler){
dispatch_async(dispatch_get_main_queue(), ^{
handler(usersArray);
});
}
});
}
The above code was suggested to me and it makes sense from what I know about GCD. Everything runs on the main queue, but before it dispatches to a background queue before the NSURLConnection synchronous call. After it gets the data it fills the usersArray and should return it to the main queue. The usersArray is populated and when it tests for if handler, it moves to the dispatch_asynch(dispatch_get_main_queue () line. But when it returns to the main queue to process the array dictionaries, the NSArray *users is empty. The app crashes with this error:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
If I comment out the dispatch_async(dispatch_get_main_queue() code to look like this:
if (handler){
//dispatch_async(dispatch_get_main_queue(), ^{
handler(usersArray);
//});
}
It works fine...well kinda, its a little sluggish. Why is this failing?
Replacing
dispatch_async(dispatch_get_main_queue(),
With:
dispatch_sync(dispatch_get_main_queue(),
REASON:
dispatch_sync will wait for the block to complete before execution

AFJSONRequestOperation Crash data parameter is nil

I'm experiencing a strange issue that only happens intermittently when I run my app. I'm attempting to pull down JSON from two different sources, using AFNetworking. Occasionally, when the operations are running, the app will crash with *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil' landing on json_request_operation_processing_queue.
I'm hoping this isn't a problem with AFNetworking, and I'm just doing something incorrectly. Here are my methods that I think are relavent (JSONManager extends AFHTTPClient):
+ (JSONManager *) sharedJSONManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedJSONManagerInsance = [[JSONManager alloc] initWithBaseURL:[NSURL URLWithString:sourceUrl1]];
});
return _sharedJSONManagerInsance;
}
- (void) loadOperations {
_sharedJSONManagerInsance.operations = [NSMutableArray arrayWithCapacity:2];
[_sharedJSONManagerInsance.operations addObject:[self fetchJSON:sourceUrl1]];
[_sharedJSONManagerInsance.operations addObject:[self fetchJSON:sourceUrl2]];
}
- (void) executeOperations {
[_sharedJSONManagerInsance loadOperations];
_sharedJSONManagerInsance.fetchedStories = [[NSMutableArray alloc] init];
[self enqueueBatchOfHTTPRequestOperations:operations
progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
NSLog(#"Finished %d of %d", numberOfFinishedOperations, totalNumberOfOperations);
}
completionBlock:^(NSArray *operations) {
[[CoreDataManager sharedManager] persistFetchedStories:_sharedJSONManagerInsance.fetchedStories];
_sharedJSONManagerInsance.operations = nil;
NSLog(#"All operations finished");
}];
}
- (AFHTTPRequestOperation *)fetchJSON:(NSString*)requestUrl {
NSURL* jsonUrl = [NSURL URLWithString:requestUrl];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:jsonUrl];
AFJSONRequestOperation *operation = nil;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
if([requestUrl isEqualToString:sourceUrl1]) {
NSArray* arr = [[JSON valueForKeyPath:#"data"] valueForKey:#"children"];
for (NSDictionary *item in arr) {
FetchedStory* fs = [[FetchedStory alloc] init];
fs.title = [[item valueForKey:#"data"]valueForKey:#"title"];
fs.url = [[item valueForKey:#"data"]valueForKey:#"url"];
fs.score = [[item valueForKey:#"data"]valueForKey:#"score"];
fs.source = #"source1";
[self.fetchedStories addObject:fs];
}
}
else if([requestUrl isEqualToString:sourceUrl2]) {
NSArray* arr = [JSON valueForKeyPath:#"items"];
for (NSDictionary *item in arr) {
FetchedStory* fs = [[FetchedStory alloc] init];
fs.title = [item valueForKey:#"title"];
fs.url = [item valueForKey:#"url"];
NSString* scoreString = [item valueForKey:#"score"];
if(scoreString != nil && [scoreString length]!=0) {
NSRange spaceRange = [scoreString rangeOfString:#" "];
scoreString = [scoreString substringToIndex:spaceRange.location];
fs.score = [NSDecimalNumber decimalNumberWithString:scoreString];
fs.source = #"source2";
[self.fetchedStories addObject:fs];
}
}
}
} failure:nil];
return operation;
}
The crash happens before "All operations finished" logs to the console. Again, this only happens some of the time.
It looks like this is a bug with AFJSONRequestOperation's responseJSON method. I added a nil check and that seems to be a good bandaid.
Actually you forget to set HTTP Method Parameter it should be like this:
[request setHTTPMethod:#"get"]; // post, patch ....

Resources