In my app I will use the PSCollectionView, but it doesn't call the delegate method. I made so:
I read a JSON file
I parse this JSON to obtain name and image url
I connect the device to the image url to obtain width and height with the code you find at the end of this question
After this operation I need to call delegate method to obtain number of PSCollectionViewCell, to define the height of each cell and to fill the cell with image and name.
I implemented the delegate method, but it doesn't execute them. I guess my problem is because that when it want to create and define the characteristic of the cell the array who contains the information to fill the cell is still empty. How I can solve this?
CODE:
- (void) loadImageFromWeb:(NSString *)urlImg forName:(NSString*)name {
NSURL* url = [NSURL URLWithString:urlImg];
//NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSString *authCredentials =#"reply:reply";
NSString *authValue = [NSString stringWithFormat:#"Basic %#",[authCredentials base64EncodedStringWithWrapWidth:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
image = [[UIImage alloc] initWithData:data];
imageWidth = image.size.width;
imageHeight = image.size.height;
imgWidth = [NSString stringWithFormat:#"%f", imageWidth];
imgHeight = [NSString stringWithFormat:#"%f", imageHeight];
self.dictWithDataForPSCollectionView = #{#"title": name,
#"width": imgWidth,
#"height": imgHeight};
[self.arrayWithData addObject:self.dictWithDataForPSCollectionView];
NSLog(#"DATA ARRAY: %#", self.arrayWithData);
} else {
NSLog(#"ERRORE: %#", error);
}
}];
}
Can anyone help me to fix this issue? Thank you!
your problem is that the delegate and the datasourse is called before that you set the array for fix your issue you have to reload the data when you set you array like that:
-(void)setArrayWithData:(NSArray *)arrayWithData{
if(_arrayWithData != arrayWithData){
_arrayWithData = arrayWithData;
}
[_yourCollectionView reloadData];
}
Make sure you connect the collectionview to your view controller by either doing myCollectionView.delegate = self;
OR
Control drag in interface builder from collectionview to view controller
Related
I have a problem with my application.It freeze for several second when I tap the sidebar menu.
What happen when I tapped menu is I pass string that gonna be url for json data fetch in my mainviewcontroller.Then it freeze because I fetch the data and populating data in tableview.
However I really new to ios programming,I wonder how can I remove the freeze?.
thanks in advance
here is my code snippet for the mainviewcontroller:
Don't use dataWiyhContentsOfURL:, or at least not directly on the main thread. If you block the main thread then the whole app stops working (as you see).
You need to learn about background threads and callback blocks, and look at using NSURLSession to download your data and then process it.
Instead of using dataWithContentsOfURL (which will block the main thread and so the UI) you need to start an asynchronous connection. In the IF ELSE change the two requests to something like below. The completionHandler (Block) is executed when done, the data parsed, HUD removed and table Updated.
You can even (and in fact must) do this within your cellForRowAtIndexPath for each of the images, however, I would use SDWebImage as it has a cache and is very easy to use.
There are also other methods if this is not right for you such as NSURLSession.
Some other points;
I have also noted that the HUD is stopped on every iteration of the FOR and probably should be outside.
I also can not see how your data is being loaded so I added a [myTable reloadData];
I can not see that the "dictionary" object is needed as it can be added directly to the array (see code)
// If you have the status bar showing
// [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[HUD showUIBlockingIndicatorWithText:#"Please wait. . ."];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:kategori]];
[request setTimeoutInterval: 10.0];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if (data != nil && error == nil)
{
//All Worked
id jsonObjects = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
for (NSDictionary *dataDict in jsonObjects)
{
NSString *title_data = [dataDict objectForKey:#"title"];
NSString *thumbnail_data = [dataDict objectForKey:#"thumb"];
NSString *author_data = [dataDict objectForKey:#"creator"];
NSString *link_data = [dataDict objectForKey:#"link"];
[myObject addObject:[[NSDictionary alloc]initWithObjectsAndKeys:
title_data, title,
thumbnail_data, thumbnail,
author_data,author,
link_data,link,
nil]];
}
[HUD hideUIBlockingIndicator];
[myTableView reloadData];
}
else
{
// There was an error
}
}];
For the images something like (this is not tested). I am not sure what format your images are in but you should be able to just add it, this may need tweeking;
cell.imageView.frame = CGRectMake(0, 0, 80, 70);
__block UIImageView *cellImage = cell.imageView;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[tmpDict objectForKey:thumbnail]]];
[request setTimeoutInterval: 10.0];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if (data != nil && error == nil)
{
//All Worked
cellImage.image = [[UIImage alloc]initWithData:data];
[cellImage layoutIfNeeded];
}
else
{
// There was an error
}
}];
You can start activity indicator and call fetch data method after few time...
- (void)viewDidLoad{
[activityIndicator startAnimating];
[self performSelector:#selector(fetchData) withObject:nil afterDelay:0.5];
}
- (void)fetchData{
Fetch your data over here
}
Or ideally you have to load data Asynchronous
For loading data Asynchronously check out the following link-
iphone-synchronous-and-asynchronous-json-parse
I Prefer MBProgressHUD.
Here is the link for 3rd Party API.
https://github.com/jdg/MBProgressHUD
Just copy these two files in your app.
MBProgressHUD.h
MBProgressHUD.m
I'm very new to developing in Objective C and am trying to figure out why I'm getting an error with my NSDictionary when trying to apply it to a table view. I'm getting the error "Expected method to read array element not found on object of type 'NSDictionary*". Does anyone know what that means, or how I would go about fixing it? I've included the model where I'm having the issue.
UPDATED:
The statement getting flagged is:
NSDictionary *conversation = self.data[indexPath.row];
Thanks!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ConversationTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"conversationCell" forIndexPath:indexPath];
// Get data from array at position of the row
NSDictionary *conversation = self.data[indexPath.row];
// Apply the data to each row
cell.conversationRecipients.text = [conversation valueForKey:#"recipients"];
cell.conversationPreview.text = [conversation valueForKey:#"last_message"];
cell.conversationTime.text = [conversation valueForKey:#"last_thread_post_short"];
//Set conversation thumbnail
[cell.conversationThumbnail sd_setImageWithURL:[conversation valueForKey:#"sender_avatar"]];
return cell;
}
Here's where I'm setting self.data:
// Successful Login
// Create the URL from a string.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"URLISHERE"]];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];
[request setHTTPMethod:#"GET"];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// Prepare for the response back from the server
NSHTTPURLResponse *response = nil;
NSError *error = nil;
// Send a synchronous request to the server (i.e. sit and wait for the response)
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSError *serializeError;
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&serializeError];
// Get response
self.data = json;
NSLog(#"%#", self.data);
// Reload data after Get
[self.tableView reloadData];
self.data needs to be of type NSArray not NSDictionary then it will work.
Hey I'm new to iPhone and I have been trying to display image icons on table view cell in offline mode.
Using NSUserDefault i am storing array objects locally in Online mode. I am using a method that creates a NSURLRequest, and sends that request with the NSURLConnection method sendAsynchronousRequest:queue:completionHandler:. Sometimes I am not getting any response using this method, so completionHandler is not calling. So i am not getting any image icon on table. Does anyone know how to fix this?
here is my code :
QuickLinksTab *quickLinksmenu = [[QuickLinksTab alloc] init];
quickLinksmenu = [arrayLinks objectAtIndex:indexPath.row];
cell.lblName.text = quickLinksmenu.title;
NSString *strQuickLink = [NSString stringWithFormat:#"http://%#",quickLinksmenu.iconImage];
NSURL* url = [NSURL URLWithString:strQuickLink];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (error)
{
NSLog(#"ERROR CONNECTING DATA FROM SERVER: %#", error.localizedDescription);
}
else{
UIImage* image = [[UIImage alloc] initWithData:data];
// do whatever you want with image
if (image) {
cell.imageIcon.image = image;
}
else{
cell.imageIcon.image = [UIImage imageNamed:#"DefaultPlace.png"];
}
}
}];
QuickLinksTab is my entity class, i am storing quickLinksmenu.title and quickLinksmenu.iconImage locally in my app. I am getting Error message - `
ERROR CONNECTING DATA FROM SERVER:
The Internet connection appears to be offline.
Thanks in Advance.
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.
I have a global NSObject class where I added an ASIHTTPRequest function to update my application. I have set the UIProgressView on a ViewController class. The NSObject class looks like so:
+(void)updateAllWithCategory:(NSMutableArray *)categories{
for(NSMutableArray *item in categories) {
NSString *urlString = [NSString stringWithFormat:#"http://mywebsite.com/%#.xml", item];
NSURL *url = [[NSURL alloc]initWithString:urlString];
__block __weak ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setShowAccurateProgress:YES];
[request setDownloadProgressDelegate:self];
[request setTimeOutSeconds:20];
[request setCompletionBlock:^{
//download all data and show alert
}];
[request setFailedBlock:^{
//display all errors
}];
[request startAsynchronous];
}}
float bytesReceived = 0;
float totalSize = 0;
float estimate = 0;
+(void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes {
bytesReceived = bytesReceived + (float)bytes;
float dlSize = (float)[request contentLength];
totalSize = totalSize + dlSize;
estimate = (bytesReceived / (totalSize * 1.0f) * 100);
//write estimate in plist with value estTime
}
Then on my view controller I use the said function like so:
-(void)updateChecker {
//get estTime from plist
[GlobalClass updateAllWithCategory:myArray]
progressbar.hidden = NO;
[progressbar setProgress:estTime animated: YES];
progressbar.progress = estTime;
}
updateChecker is called via a NSTimer set on viewDidLoad. Neither setProgress:animated: nor .progress worked. My progress bar does not move even a little. So my question is, how exactly do you implement a progress bar for an ASIHTTPRequest that's called from a global NSObject class?
You need to create a UIProgressView.
UIProgressView *progressView = [UIProgressView alloc] init];
and then replace this
[request setDownloadProgressDelegate:self];
with this
[request setDownloadProgressDelegate:progressView];