I had a little problem which is I can't properly reload a new data in collectionview whilst scrolling down at the bottom of collectionviewcontroller. The problem I had starting at this code if (indexPath.row == [selectedVideoData count] - 1). Below is my full code for collectionviewcontroller :
#import "PageVideosCVC.h"
#import "facebook.h"
#import "MBProgressHUD.h"
#import <AFNetworking/AFNetworking.h>
#import <AVFoundation/AVFoundation.h>
#import <SDWebImage/UIImageView+WebCache.h>
#interface PageVideosCVC () <UICollectionViewDataSource,UICollectionViewDelegate>
#end
#implementation PageVideosCVC
#synthesize selectedVideoData, selectNextVideoData;
static NSString * const reuseIdentifier = #"Cell";
-(void) viewWillAppear:(BOOL)animated {
UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
[UINavigationBar appearance].barTintColor = [UIColor lightGrayColor];
[self.view addSubview: navBar];
UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithTitle:#"< Back"
style:UIBarButtonItemStylePlain
target:self
action:#selector(backButtonTapped:)];
// UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:#"Done"
// style:UIBarButtonItemStyleBordered
// target:self action:nil];
NSString *selectedPageName = [[NSString alloc] initWithFormat:#"%#", self.pageName];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:selectedPageName];
// navItem.rightBarButtonItem = doneItem;
navItem.leftBarButtonItem = cancelItem;
navBar.items = [NSArray arrayWithObjects: navItem,nil];
[UIBarButtonItem appearance].tintColor = [UIColor blueColor];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
facebook *fb = [[facebook alloc] init];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
NSDictionary *fbVideoParams = #{ #"fields": #"videos.limit(10){source,description,thumbnails.limit(1),length}"};
[fb fetchVideoInformationFromPages:fbVideoParams videoID:self.videoID completionHandler:^(NSDictionary *videoResult) {
if (videoResult != nil) {
selectedVideoData = [videoResult valueForKeyPath:#"videos.data"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
}
}];
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = NO;
// Register cell classes
// [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
// Do any additional setup after loading the view.
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return selectedVideoData.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
// Configure the cell
// This is a last cell, I wanna load next video data from fb.
if (indexPath.row == [selectedVideoData count] - 1) {
NSString *fbToken = [facebook currentFBAccessToken];
NSString *fbNextVideoURL = [NSString stringWithFormat:#"https://graph.facebook.com/v2.5/606246146140197/videos?access_token=%#&pretty=0&fields=source,description,thumbnails.limit(1),length&limit=10&after=ODYxOTA5OTEzOTA3MTUx", fbToken];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[manager GET:fbNextVideoURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
selectNextVideoData = [responseObject valueForKey:#"data"];
NSLog(#"JSON Next Video: %#", selectNextVideoData);
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
// I had a problem setting the right thumbnail here.
UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
NSURL *thumbnailImage = [NSURL URLWithString:[selectNextVideoData valueForKeyPath:#"thumbnails.data"]];
// NSLog(#"JSON Next Video: %#", thumbnailImage);
[imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
[self.collectionView reloadData];
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
} else {
UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
NSURL *thumbnailImage = [NSURL URLWithString:[selectedVideoData valueForKeyPath:#"thumbnails.data.uri"][indexPath.row][0]];
[imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
}
return cell;
}
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
// NSLog(#"videos : %#", selectedVideoData);
// NSLog(#"videos source : %#", [selectedVideoData valueForKeyPath:#"source"][indexPath.row]);
NSURL *videoURL = [NSURL URLWithString:[selectedVideoData valueForKeyPath:#"source"][indexPath.row]];
self.playerController = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
[[self.playerController view] setFrame:[self.view bounds]]; // Frame must match parent view
[self.view addSubview:[self.playerController view]];
self.playerController.movieSourceType = MPMovieSourceTypeStreaming;
self.playerController.controlStyle = MPMovieControlStyleFullscreen;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(doneButtonClick:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
[self.playerController play];
// Play the video using AVPlayer iOS9 above
// AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
// playerLayer.frame = self.view.bounds;
// [self.view.layer addSublayer:playerLayer];
// [player play];
}
-(void)doneButtonClick:(NSNotification*)aNotification{
NSNumber *reason = [aNotification.userInfo objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
if ([reason intValue] == MPMovieFinishReasonUserExited) {
// Your done button action here
// [self dismissViewControllerAnimated:YES completion:nil];
NSLog(#"done button tapped");
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerDidExitFullscreenNotification
object:nil];
[self.playerController stop];
[self.playerController.view removeFromSuperview];
}
}
- (IBAction)backButtonTapped:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Perhaps rather than this approach you can try scrollView Delegate Methods :
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
// NSLog(#"offset: %f", offset.y);
// NSLog(#"content.height: %f", size.height);
// NSLog(#"bounds.height: %f", bounds.size.height);
// NSLog(#"inset.top: %f", inset.top);
// NSLog(#"inset.bottom: %f", inset.bottom);
// NSLog(#"pos: %f of %f", y, h);
float reload_distance = 10;
if(y > h + reload_distance) {
NSLog(#"load more rows");
}
}
Related
In my JSQMessagesViewController, when I load text message bubbles, the arrow direction is always right side.
How to change arrow direction to left for green bubbles??
My Code:
#interface AckChatViewController (){
JSQMessagesBubbleImage *outgoingBubbleImageView;
JSQMessagesBubbleImage *incomingBubbleImageView;
JSQMessagesAvatarImage *currentUserAvatar, *friendAvatar;
NSMutableArray *messages;
}
#end
#implementation AckChatViewController
pragma mark - life cycle methods
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationController.navigationBar.topItem.title = #"";
//initial things for JSQMessageViewController
[self setupBubbles];
messages = [NSMutableArray new];
AllUserDetailsModel *temp = [[AllUserDetailsModel alloc] initWithDictionary:[Neo_Constants getSavedDataFromUserDafaults:USER_INFO_DICTIONARY]];
self.senderId = [NSString stringWithFormat:#"%#",temp.user_id];
self.senderDisplayName = #"";
self.automaticallyScrollsToMostRecentMessage = YES;
//remove attachment button
self.inputToolbar.contentView.leftBarButtonItem = nil;
currentUserAvatar = [JSQMessagesAvatarImage avatarImageWithPlaceholder: [self cropAvatarImages:[UIImage imageNamed:[self defaultImageForGender:temp.userDetails.gender]]]];
friendAvatar = [JSQMessagesAvatarImage avatarImageWithPlaceholder: [self cropAvatarImages:[UIImage imageNamed:[self defaultImageForGender:self.friendUserDetails.userDetails.gender]]]];
NSString *imageUrlString = temp.userDetails.profile_pic;
[self avatarImagesForUrlString:imageUrlString andOnCompletion:^(UIImage *image) {
if(image){
currentUserAvatar.avatarImage = image;
}
}];
[self avatarImagesForUrlString:self.friendUserDetails.userDetails.profile_pic andOnCompletion:^(UIImage *image) {
if(image){
friendAvatar.avatarImage = image;
}
}];
//set profile pic and name on navigation bar
[self setNavigationBarTitleView];
[self loadPreviousChatWithPageCount:0];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
pragma mark - JSQ Setups
-(void)setupBubbles{
JSQMessagesBubbleImageFactory *bubbleImageFactory = [JSQMessagesBubbleImageFactory new];
outgoingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]];
incomingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}
pragma mark Collection view JSQ
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return messages.count;
}
-(id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
return messages[indexPath.item];
}
-(id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
return outgoingBubbleImageView;
}else{
return incomingBubbleImageView;
}
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
[cell.textView setTextColor:[UIColor whiteColor]];
}else{
[cell.textView setTextColor:[UIColor blackColor]];
}
return cell;
}
-(id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
return currentUserAvatar;
}else{
return friendAvatar;
}
}
-(void)collectionView:(JSQMessagesCollectionView *)collectionView header:(JSQMessagesLoadEarlierHeaderView *)headerView didTapLoadEarlierMessagesButton:(UIButton *)sender{
}
//time stamp
-(NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath{
return nil;
}
-(CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath{
return 0;
}
#pragma mark - private functions
-(NSString *)defaultImageForGender:(NSString *)gender{
if([gender isEqualToString:#"M"] || [gender isEqualToString:#""]){
return #"no_image_male";
}else{
return #"no_image_female";
}
}
-(void)setNavigationBarTitleView{
UIView *whole = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width - 100, 100)];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 20, 50, 50)];
[imageView.layer setCornerRadius:25.0f];
[imageView setClipsToBounds:YES];
[imageView setContentMode:UIViewContentModeScaleAspectFill];
if([self.friendUserDetails.userDetails.profile_pic isEqualToString:#""] || [self.friendUserDetails.userDetails.profile_pic isEqual:[NSNull null]]){
if([self.friendUserDetails.userDetails.gender isEqualToString:#"M"]){
[imageView setImage:[UIImage imageNamed:#"no_image_male"]];
}else{
[imageView setImage:[UIImage imageNamed:#"no_image_female"]];
}
}else{
[imageView sd_setImageWithURL:[NSURL URLWithString:self.friendUserDetails.userDetails.profile_pic]];
}
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 20, [UIScreen mainScreen].bounds.size.width, 50)];
[nameLabel setText:self.friendUserDetails.userDetails.fname];
[whole addSubview:nameLabel];
[whole addSubview:imageView];
self.navigationItem.titleView = whole;
}
#pragma mark - Avtar images area
-(void)avatarImagesForUrlString:(NSString *)urlString andOnCompletion:(void(^)(UIImage *image))completion{
if([urlString isEqualToString:#""] || [urlString isEqual:[NSNull null]]){
completion(nil);
}else{
[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:urlString] options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
completion ([self cropAvatarImages:image]);
}];
}
}
-(UIImage *)cropAvatarImages:(UIImage *)image{
if(image){
return [JSQMessagesAvatarImageFactory circularAvatarImage:image withDiameter:48];
}else{
if([self.friendUserDetails.userDetails.gender isEqualToString:#"M"]){
return [UIImage imageNamed:#"no_image_male"];
}else{
return [UIImage imageNamed:#"no_image_female"];
}
}
}
#pragma mark - API calls
-(void)loadPreviousChatWithPageCount:(int)count{
[API fetchChatListOfUserWithParams:paramsDict andOnCompletion:^(NSDictionary *result, NSError *error){
if (!error) {
if ([[result objectForKey:#"status"] intValue]==1) {
NSArray *conversation_data = [result objectForKey:#"conversation_data"];
[messages removeAllObjects];
[conversation_data enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop){
JSQMessage *jsqMsg = [[JSQMessage alloc] initWithSenderId:obj[#"sender_id"] senderDisplayName:#"" date:obj[#"sent_date"] text:obj[#"message_content"]];
[messages insertObject:jsqMsg atIndex:idx];
}];
[self.collectionView reloadData];
}else{
[Neo_Constants showAlert:#"Error" Message:[result objectForKey:#"message"]];
}
}else{
[Neo_Constants showAlert:#"Error" Message:[error localizedDescription]];
}
}];
}
-(void)didPressSendButton:(UIButton *)button withMessageText:(NSString *)text senderId:(NSString *)senderId senderDisplayName:(NSString *)senderDisplayName date:(NSDate *)date{
// [JSQSystemSoundPlayer jsq_playMessageSentSound];
[API sendMessageFromUserWithParams:paramsDict andOnCompletion:^(NSDictionary *result, NSError *error){
if (!error) {
if ([[result objectForKey:#"status"] intValue]==1) {
[self loadPreviousChatWithPageCount:0];
[self.inputToolbar.contentView.textView setText:#""];
}else{
[Neo_Constants showAlert:#"Error" Message:[result objectForKey:#"message"]];
}
}else{
[Neo_Constants showAlert:#"Error" Message:[error localizedDescription]];
}
}];
}
#end
problem is in this code you initialise outgoing and incomming with the same method which is
outgoingMessagesBubbleImageWithColor
try incoming with
incomingMessagesBubbleImageWithColor
and outgoing with this
outgoingMessagesBubbleImageWithColor
this correct one
-(void)setupBubbles{
JSQMessagesBubbleImageFactory *bubbleImageFactory = [JSQMessagesBubbleImageFactory new];
outgoingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]];
incomingBubbleImageView = [bubbleImageFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}
I am using this to display some labels and images by JSON parsing in to tableView but images are not coming at the first launch when scrolling the tableview images are coming and dancing i mean not coming in order format help me with this
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
self.customCellClass = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (self.customCellClass == nil)
{
self.customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
self.customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"name"]; // label
self.customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"region"]; // label
NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:#"summary"] stripHtml]; //label
self.customCellClass.detailLabel.text = stripped;
self.customCellClass.mainImage.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
self.customCellClass.mainImage.image = image;
});
});
return self.customCellClass;
}
Replace below code in UITableView's cellForRowAtIndexPath method :
//Check if cell has image or not
if(!self.customCellClass.mainImage.image)
{
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(q, ^{
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
//Get main queue
dispatch_async(dispatch_get_main_queue(), ^{
/* This is the main thread again, where we set the tableView's image to be what we just fetched. */
self.customCellClass.mainImage.image = image;
});
});
}
Good solution is if you are using AFNetworking then use UIImageView+AFNetworking category
NSURL *imageURL = [NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]
[self.customCellClass.mainImage setImageWithURL:imageURL placeholderImage:nil];
You are assigning image=nil every time when cell is loading and downloading the same image.
You can user following class to do this seamlessly.
AsyncImageView.h
#import <UIKit/UIKit.h>
#interface AsyncImageView : UIView {
NSURLConnection *connection;
NSMutableData *data;
NSString *urlString; // key for image cache dictionary
}
-(void)loadImageFromURL:(NSURL*)url;
-(void)loadBackgroundImage:(UIImage *)image;
-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url;
-(BOOL)getCachedImageWithUrl:(NSString*)url;
#end
and AsyncImageView.m
#import "AsyncImageView.h"
#import "ImageCacheObject.h"
#import "ImageCache.h"
//
// Key's are URL strings.
// Value's are ImageCacheObject's
//
static ImageCache *imageCache = nil;
#define SPINNY_TAG 5555
#implementation AsyncImageView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
- (void)dealloc {
[connection cancel];
}
-(void)loadBackgroundImage:(UIImage *)image
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.layer.masksToBounds=YES;
//imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout];
[self setNeedsLayout];
imageView=nil;
}
-(void)loadImageFromURL:(NSURL*)url
{
if (connection != nil) {
[connection cancel];
connection = nil;
}
if (data != nil) {
data = nil;
}
if (imageCache == nil) // lazily create image cache
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
// NSLog(#"Value of the url here = %#",url);
urlString = [[url absoluteString] copy];
UIImage *cachedImage = [imageCache imageForKey:urlString];
if (cachedImage != nil)
{
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.layer.masksToBounds=YES;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
return;
}
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.tag = SPINNY_TAG;
spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
spinny.center = self.center;
[spinny startAnimating];
[self addSubview:spinny];
[self bringSubviewToFront:spinny];
spinny=nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(BOOL)getCachedImageWithUrl:(NSString*)url
{
BOOL isIamgeCached=NO;
if (imageCache == nil)
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
UIImage *cachedImage = [imageCache imageForKey:url];
if (cachedImage != nil)
{
isIamgeCached=YES;
}
return isIamgeCached;
}
-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url
{
if (connection != nil)
{
[connection cancel];
connection = nil;
}
if (data != nil)
{
data = nil;
}
if (imageCache == nil) // lazily create image cache
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
// NSLog(#"Value of the url here = %#",url);
urlString = [[url absoluteString] copy];
UIImage *cachedImage = [imageCache imageForKey:urlString];
if (cachedImage != nil)
{
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
return cachedImage;
}
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.tag = SPINNY_TAG;
spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
//spinny.center = self.center;
[spinny startAnimating];
[self addSubview:spinny];
[self bringSubviewToFront:spinny];
spinny=nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
return cachedImage;
}
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)incrementalData {
if (data==nil)
{
data = [[NSMutableData alloc] initWithCapacity:2048];
}
[data appendData:incrementalData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
connection = nil;
UIView *spinny = [self viewWithTag:SPINNY_TAG];
[spinny removeFromSuperview];
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImage *image = [UIImage imageWithData:data];
[imageCache insertImage:image withSize:[data length] forKey:urlString];
UIImageView *imageView = [[UIImageView alloc]
initWithImage:image];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
data = nil;
}
#end
You use dispatch_async to load image from remote, that means the images to be displayed in tableview cells are loaded asynchronously. And you use a instance variable to record current cell, which cause the problem you met.
After a image being loaded finished (may take few minutes), it want to be displayed in a cell (written in this code),
dispatch_sync(dispatch_get_main_queue(), ^(void) {
self.customCellClass.mainImage.image = image;
});
only to find that the self.customCellClass points to a wrong cell (the - (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath was called several times during the image being loaded, and each calling changes the pointing of self.customCellClass to other cell).
So, the order of images is wrong.
Try this:
Use a locality variable to keep the cell get from dequeueReusableCellWithIdentifier. Like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
CellCustom *customCellClass = (CellCustom *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (customCellClass == nil)
{
customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"name"]; // label
customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"region"]; // label
NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:#"summary"] stripHtml]; //label
customCellClass.detailLabel.text = stripped;
customCellClass.mainImage.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
customCellClass.mainImage.image = image;
});
});
return customCellClass;
}
Besides, take a look at the difference between - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier and - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath.
I have a problem
When I click the tabcontoller uıcollectionviewflowlayout position is changing :(
The following code does not work
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.myCollectionView.collectionViewLayout;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
}
before image:
When I click the tabcontoller
after image:
please help me
other image upload
updated:
Remove
UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.myCollectionView.collectionViewLayout;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
from viewWillAppear and put it back in viewDidLoad.
- (void)viewDidLoad
{
[self.myCollectionView registerNib:[UINib nibWithNibName:PhotoCellIdentifier bundle:[NSBundle mainBundle]]
forCellWithReuseIdentifier:PhotoCellIdentifier];
self.myCollectionView.delegate=self;
self.myCollectionView.dataSource=self;
[self.myCollectionView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[self yukle];
}
-(void) storkontrol:(NSArray*)skulist{
[[RMStore defaultStore] requestProducts:[NSSet setWithArray:skulist] success:^(NSArray *products, NSArray *invalidProductIdentifiers) {
if (products.count ==0)
{
self.eserList = nil;
[self sitedeveriyokbilgi];
} else
{
NSMutableArray *ll = [[NSMutableArray alloc] init];
int i =0;
// satın alışverişte alınan ürünelr geliyor
// NSLog(#"RMStore dan ürünler bekleniyor..");
for (SKProduct*urun in products) {
// NSLog(#"ürün : %#",urun.productIdentifier);
for (EserFiles*eser in self.eserList) {
if ([urun.productIdentifier isEqualToString:eser.eser.eserstokkod])
{
eser.eser.product = urun;
[ll insertObject:eser atIndex:i];
i++;
}
}
}
// NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"eser.esersayi" ascending:NO selector:#selector(compare:)];
// [ll sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
self.eserList = ll;
// [HesapViewController setEserListVitrin: ll];
// [AyarlarViewController setEserListVitrin: ll];
[global setEserListVitrin: ll];
// NSLog(#"RMStore dan ürün çekme işlemi bitti");
[self.myCollectionView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
_productsRequestFinished = YES;
[spinnerorta stopAnimating];
}
} failure:^(NSError *error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[spinnerorta stopAnimating];
NSLog(#"failure:^(NSError *error urunlist %#",error.localizedDescription);
}];
}
-(void)sitedeveriyokbilgi{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 270)];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor grayColor];
label.numberOfLines = 0;
label.text = #"Listelenecek eser bulunamadı";
[self.view addSubview:label];
NSLog(#"Listelenecek eser bulunamadı");
[spinnerorta stopAnimating];
}
-(void)yukle{
spinnerorta = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinnerorta.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
spinnerorta.center = self.view.center;
[spinnerorta startAnimating];
[self.view addSubview: spinnerorta];
//eğer kategoriden geliyorsa hiç bir zamanön bellekleme olmayacak
__block NSArray *arry ;
NSMutableArray *skulist = [[NSMutableArray alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//ana sayfa ise
if (self.gelenviewid==1)
{
if ([[global getEserList] count] ==0 )
{
// NSLog(#"yeni liste alınıyor.......");
NSMutableArray *skulist = [[NSMutableArray alloc] init];
JSONLoader *jsonLoader = [[JSONLoader alloc] init];
arry = [jsonLoader locationsFromJSONFile];
} else{
self.eserList =[global getEserList];
// NSLog(#"ön bellekten doldu....");
[self.myCollectionView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
// [spinnerorta stopAnimating];
return ;
}
} else if(self.gelenviewid==2)
{
arry = [JSONLoader getEserlerToKategory:self.catId];
}
if ([arry count] >0)
{
self.eserList = arry;
for (EserFiles*eserfile in self.eserList) {
// NSLog(#"sayı :%d %#",eserfile.eser.esersayi,eserfile.eser.kisaisim);
[skulist addObject:eserfile.eser.eserstokkod];
}
// dispatch_async( dispatch_get_main_queue(),
// ^{
[self storkontrol:skulist];
// });
} else {
dispatch_async( dispatch_get_main_queue(),^{
[spinnerorta stopAnimating];
[self sitedeveriyokbilgi];
});
}
});
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section {
int count = self.eserList.count;
return count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{
// [collectionView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
EserFiles *esefiles =[self.eserList objectAtIndex:indexPath.row];
Eser *eser = esefiles.eser;
UrunCell *urunCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"UrunCell" forIndexPath:indexPath];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinner.frame = CGRectMake((urunCell.frame.size.width-25)/2, 50, 24, 24);
[spinner startAnimating];
[urunCell.contentView addSubview: spinner];
NSString *title = #"";
if ([eser.kisaisim isKindOfClass:[NSNull class]] || [eser.kisaisim isEqualToString:#""]){
title = eser.isim;
} else title = eser.kisaisim;
urunCell.UrunIsim.text=title;
// NSLog(#"title : %#",title);
[urunCell.UrunImage sd_setImageWithURL:[NSURL URLWithString:eser.kapakYol]
placeholderImage:[UIImage imageNamed:#"placeholder"] options:indexPath.row == 0 ? SDWebImageRefreshCached : 0];
[spinner stopAnimating];
return urunCell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
self.vitrinDetayViewController =[self.storyboard instantiateViewControllerWithIdentifier:#"VitrinDetayViewController"];
EserFiles *esefiles =[self.eserList objectAtIndex:indexPath.row];
self.vitrinDetayViewController.eser = esefiles;
[self.navigationController pushViewController:self.vitrinDetayViewController animated:YES];
}
- (void)viewWillAppear:(BOOL)animated {
// [self.myCollectionView setContentOffset:CGPointZero animated:NO];
[super viewWillAppear:animated];
UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.myCollectionView.collectionViewLayout;
// collectionViewLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
//[self.myCollectionView setContentOffset:CGPointZero animated:NO];
// self.automaticallyAdjustsScrollViewInsets = NO;
[spinnerorta stopAnimating];
}
I am trying to show a UIActivityIndicatorView while my table view is loading data and have it disappear once loading is finished. The loading indicator never appears. What am I doing wrong?
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define storeURL [NSURL URLWithString: #"https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=25&playlistId=PL9DC706DCCCE00188&key=AIzaSyBS4do208_KPGHAhszfVkHadSvtfSgr7Mo"]
#import "BBYoutubeVideosTableViewController.h"
#import "Reachability.h"
#import "TSMessage.h"
#import "TSMessageView.h"
#import "YoutubeCell.h"
#import "KFBYoutubeVideoView.h"
#import "KFBAppDelegate.h"
#interface BBYoutubeVideosTableViewController ()
{
UIActivityIndicatorView *loadingIndicator;
}
#end
#implementation BBYoutubeVideosTableViewController
#synthesize title, videoID, thumbURL, descriptionString, url, titleArray, videoIDArray, thumbArray, descriptionArray;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
UIImageView *backgroundImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"plain_app-background.png"]];
CGFloat width = [[UIScreen mainScreen]bounds].size.width;
CGFloat height = [[UIScreen mainScreen]bounds].size.height;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
loadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(width / 2, height / 2, 37, 37)];
loadingIndicator.center = CGPointMake(width / 2, height / 2 - 37);
}
else
{
loadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(142, 365, 37, 37)];
}
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
loadingIndicator.hidesWhenStopped = YES;
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if(networkStatus == NotReachable)
{
[TSMessage showNotificationWithTitle:#"Network Error" subtitle:#"No active network connection!" type:TSMessageNotificationTypeError];
[loadingIndicator stopAnimating];
}
else {
[self.tableView addSubview:loadingIndicator];
[loadingIndicator startAnimating];
}
self.title = #"Bluegrass & Backroads";
self.tableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStyleGrouped];
self.tableView.backgroundView = backgroundImage;
url = [NSURL URLWithString:#"https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=25&playlistId=PL9DC706DCCCE00188&key=AIzaSyBS4do208_KPGHAhszfVkHadSvtfSgr7Mo"];
dispatch_async(kBgQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:url];
if (data == nil)
{
NSLog(#"data is nil");
}
else
{
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
}
});
}
- (void)viewDidDisappear:(BOOL)animated
{
[loadingIndicator stopAnimating];
}
- (void)fetchedData:(NSData *)responseData
{
NSError *error;
titleArray = [[NSMutableArray alloc]init];
videoIDArray = [[NSMutableArray alloc]init];
thumbArray = [[NSMutableArray alloc]init];
descriptionArray = [[NSMutableArray alloc]init];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSArray *items = [json objectForKey:#"items"];
for (NSDictionary *item in items)
{
NSDictionary *snippet = [item objectForKey:#"snippet"];
title = [snippet objectForKey:#"title"];
videoID = [[snippet objectForKey:#"resourceId"] objectForKey:#"videoId"];
thumbURL = [[[snippet objectForKey:#"thumbnails"] objectForKey:#"default"] objectForKey:#"url"];
descriptionString = [snippet objectForKey:#"description"];
[titleArray addObject:title];
[videoIDArray addObject:videoID];
UIImage *thumbnailImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:thumbURL]]];
[thumbArray addObject:thumbnailImage];
[descriptionArray addObject:descriptionString];
}
[self.tableView reloadData];
[loadingIndicator stopAnimating];
}
- (IBAction)morePressed:(id)sender
{
NSURL *kyfbVideos = [NSURL URLWithString:#"https://www.youtube.com/playlist?list=PL9DC706DCCCE00188"];
[[UIApplication sharedApplication] openURL:kyfbVideos];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [titleArray count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 215;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 60;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIColor *kfbBlue = [UIColor colorWithRed:8.0/255.0f green:77.0/255.0f blue:139.0/255.0f alpha:1];
UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height)];
footerView.backgroundColor = [UIColor clearColor];
CGFloat width = footerView.frame.size.width;
UIButton *moreButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
moreButton.backgroundColor = [UIColor clearColor];
[moreButton setTitle:#"More" forState:UIControlStateNormal];
[moreButton setTitleColor:kfbBlue forState:UIControlStateNormal];
moreButton.titleLabel.textAlignment = NSTextAlignmentCenter;
moreButton.titleLabel.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:25.0];
moreButton.frame = CGRectMake(width / 2 - 25, 0, 50, 50);
moreButton.layer.cornerRadius = 25.0;
moreButton.layer.borderWidth = 2.0f;
moreButton.layer.borderColor = kfbBlue.CGColor;
moreButton.clipsToBounds = YES;
moreButton.backgroundColor = [UIColor clearColor];
[moreButton addTarget:self action:#selector(morePressed:) forControlEvents:UIControlEventTouchUpInside];
[footerView addSubview:moreButton];
return footerView;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIColor *kfbBlue = [UIColor colorWithRed:8.0/255.0f green:77.0/255.0f blue:139.0/255.0f alpha:1];
YoutubeCell *cell = [tableView dequeueReusableCellWithIdentifier:#"youtubeCell"];
if (!cell)
{
NSArray *nibs =[[NSBundle mainBundle] loadNibNamed:#"YoutubeCell" owner:self options:NULL];
cell = [nibs firstObject];
}
cell.videoTitle.text = [titleArray objectAtIndex:indexPath.row];
cell.videoDescription.text = [descriptionArray objectAtIndex:indexPath.row];
cell.videoThumbnail.image = [thumbArray objectAtIndex:indexPath.row];
cell.videoTitle.textColor = kfbBlue;
cell.videoDescription.textColor = kfbBlue;
cell.videoTitle.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:22.0];
cell.videoDescription.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:16.0];
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
KFBYoutubeVideoView *videoView = [[KFBYoutubeVideoView alloc]init];
videoView.videoIDString = [videoIDArray objectAtIndex:indexPath.row];
videoView.videoTitle = [titleArray objectAtIndex:indexPath.row];
videoView.videoDescription = [descriptionArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:videoView animated:YES];
}
else
{
KFBYoutubeVideoView *videoView = [[KFBYoutubeVideoView alloc]initWithNibName:nil bundle:nil];
videoView.videoIDString = [videoIDArray objectAtIndex:indexPath.row];
videoView.videoTitle = [titleArray objectAtIndex:indexPath.row];
videoView.videoDescription = [descriptionArray objectAtIndex:indexPath.row];
NSMutableArray *details = [self.splitViewController.viewControllers mutableCopy];
UINavigationController *detailNav = [[UINavigationController alloc]initWithRootViewController:videoView];
[details replaceObjectAtIndex:1 withObject:detailNav];
KFBAppDelegate *appDelegate = (KFBAppDelegate *)[[UIApplication sharedApplication]delegate];
appDelegate.splitViewController.viewControllers = details;
appDelegate.window.rootViewController = self.splitViewController;
appDelegate.splitViewController.delegate = videoView;
[appDelegate.splitViewController viewWillAppear:YES];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I figured it out. tableView was being initialized after adding loadingIndicator as a subview.
I have a tableview that shows data from an RSS feed and it works fine as long as it is not the root view of my app. I have always shown it by pressing a button but now I'm wanting to have it be the first view the user sees but the activity indicator just keeps spinning and the content never loads. Like I said, when I've pushed it onto the navigation stack from a button, it loads the content so I'm not really sure why it won't load when it's the first view shown.
AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
AgStoriesViewController *rootView = [[AgStoriesViewController alloc] initWithNibName:nil bundle:nil];
WebViewController *wvc = [[WebViewController alloc]init];
[rootView setWebViewController:wvc];
KFBNavControllerViewController *navController = [[KFBNavControllerViewController alloc] initWithRootViewController:rootView];
navController.delegate = rootView;
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
}
TableView with RSS
#import "AgStoriesViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
#import "DTCustomColoredAccessory.h"
#import "UIImage+ImageEffects.h"
#import "UIView+Borders.h"
#import "TSMessage.h"
#import "TSMessageView.h"
#import "ArticleCell.h"
#import "KFBAppDelegate.h"
#import "MenuTableViewController.h"
#implementation AgStoriesViewController
{
UIActivityIndicatorView *loadingIndicator;
}
#synthesize webViewController, blurredView, contentView, menuShown;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
self.navigationController.delegate = self;
}
return self;
}
- (void)viewDidLoad
{
menuShown = NO;
UIImage *background = [UIImage imageNamed:#"sunset"];
UIImageView *backgroundImageView = [[UIImageView alloc]initWithImage:background];
CGFloat width = CGRectGetWidth(self.view.bounds);
CGFloat height = CGRectGetHeight(self.view.bounds);
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
self.tableView.backgroundView = backgroundImageView;
self.title = #"Ag News";
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
UIImage *hamburgerButton = [UIImage imageNamed:#"list_button"];
UIBarButtonItem *listButton = [[UIBarButtonItem alloc]initWithImage:hamburgerButton style:UIBarButtonItemStyleBordered target:self action:#selector(showMenu)];
self.navigationItem.leftBarButtonItem = listButton;
}
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
loadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(width / 2, height / 2, 37, 37)];
loadingIndicator.center = CGPointMake(width / 2, height / 2 - 37);
}
else
{
loadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(142, 365, 37, 37)];
}
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
loadingIndicator.hidesWhenStopped = YES;
[self.tableView addSubview:loadingIndicator];
[loadingIndicator startAnimating];
}
- (void)showMenu
{
if (!menuShown)
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
UIColor *kfbBlue = [UIColor colorWithRed:8.0/255.0f green:77.0/255.0f blue:139.0/255.0f alpha:1];
contentView = [[UIView alloc]initWithFrame:self.tableView.bounds];
contentView.autoresizesSubviews = YES;
contentView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
contentView.backgroundColor = [UIColor clearColor];
blurredView = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight)];
[blurredView setBarStyle:UIBarStyleBlack];
[blurredView setBarTintColor:kfbBlue];
MenuTableViewController *menu = [[MenuTableViewController alloc]initWithNibName:#"MenuTableViewController" bundle:nil];
menu.view.frame = CGRectMake(0, 0, screenWidth, screenHeight - 50);
[self.view addSubview:contentView];
[contentView addSubview:blurredView];
[self addChildViewController:menu];
[contentView addSubview:menu.view];
self.tableView.scrollEnabled = NO;
menuShown = YES;
}
else if (menuShown)
{
[contentView removeFromSuperview];
[blurredView removeFromSuperview];
self.navigationController.navigationBarHidden = NO;
self.tableView.scrollEnabled = YES;
menuShown = NO;
}
}
- (void)closeMenu
{
[contentView removeFromSuperview];
self.navigationController.navigationBarHidden = NO;
self.tableView.scrollEnabled = YES;
}
- (void)viewDidDisappear:(BOOL)animated
{
[loadingIndicator stopAnimating];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"%# found a %# element", self, elementName);
if ([elementName isEqual:#"channel"])
{
channel = [[RSSChannel alloc]init];
[channel setParentParserDelegate:self];
[parser setDelegate:channel];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"channel items %lu", (unsigned long)[[channel items]count]);
return [[channel items]count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 215;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RSSItem *item = [[channel items]objectAtIndex:[indexPath row]];
ArticleCell *cell = [tableView dequeueReusableCellWithIdentifier:#"articleCell"];
if (!cell)
{
NSArray *nibs =[[NSBundle mainBundle] loadNibNamed:#"ArticleCell" owner:self options:NULL];
cell = [nibs firstObject];
}
cell.articleTitle.text = [item title];
cell.articleDescription.text = [item infoString];
cell.articleTitle.textColor = [UIColor whiteColor];
cell.articleDescription.textColor = [UIColor whiteColor];
cell.articleTitle.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:22.0];
cell.articleDescription.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:16.0];
cell.backgroundColor = [UIColor clearColor];
return cell;
}
- (void)fetchEntries
{
xmlData = [[NSMutableData alloc]init];
NSURL *url = [NSURL URLWithString:#"http://kyfbnewsroom.com/category/ag-news/feed"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
connection = [[NSURLConnection alloc]initWithRequest:req delegate:self startImmediately:YES];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
[self fetchEntries];
}
return self;
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
[loadingIndicator stopAnimating];
UIImage *background = [UIImage imageNamed:#"sunset"];
UIImage *effectImage = [background applyDarkEffect];
UIImageView *blurredBackground = [[UIImageView alloc]init];
blurredBackground.image = effectImage;
self.tableView.backgroundView = blurredBackground;
// Create the parser object with the data received from the web service
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:xmlData];
// Give it a delegate
[parser setDelegate:self];
//Tell it to start parsing - the document will be parsed and the delegate of NSXMLParser will get all of its delegate messages sent to it before this line finishes execution - it is blocking
[parser parse];
// Get rid of the XML data as we no longer need it
xmlData = nil;
NSMutableArray *actionAlerts = [NSMutableArray array];
for (RSSItem *object in channel.items)
{
if (object.isActionAlert)
{
[actionAlerts addObject:object];
}
}
for (RSSItem *object in actionAlerts)
{
[channel.items removeObject:object];
}
// Reload the table
[[self tableView]reloadData];
NSLog(#"%#\n %#\n %#\n", channel, [channel title], [channel infoString]);
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
// Release the connection object, we're done with it
connection = nil;
// Release the xmlData object, we're done with it
xmlData = nil;
[loadingIndicator stopAnimating];
// Grab the description of the error object passed to us
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#", [error localizedDescription]];
// Create and show an alert view with this error displayed
// UIAlertView *av = [[UIAlertView alloc]initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// [av show];
[TSMessage showNotificationWithTitle:#"Network Error" subtitle:errorString type:TSMessageNotificationTypeError];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
[[webViewController webView]loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"about:blank"]]];
[self.navigationController pushViewController:webViewController animated:YES];
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
NSURL *url = [NSURL URLWithString:[entry link]];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[[webViewController webView]loadRequest:req];
webViewController.hackyURL = url;
}
else
{
[[webViewController webView]loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"about:blank"]]];
NSMutableArray *details = [self.splitViewController.viewControllers mutableCopy];
UINavigationController *detailNav = [[UINavigationController alloc]initWithRootViewController:webViewController];
[details replaceObjectAtIndex:1 withObject:detailNav];
KFBAppDelegate *appDelegate = (KFBAppDelegate *)[[UIApplication sharedApplication]delegate];
appDelegate.splitViewController.viewControllers = details;
appDelegate.window.rootViewController = self.splitViewController;
appDelegate.splitViewController.delegate = webViewController;
[appDelegate.splitViewController viewWillAppear:YES];
// Grab the selected item
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView]loadRequest:req];
webViewController.hackyURL = url;
// Set the title of the web view controller's navigation item
[[webViewController navigationItem]setTitle:[entry title]];
}
}
#end
Use this method to reload your table data -
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
[[self tableView]reloadData];
}
This method is called when parsing of your xml document is finished. You are reloading table when data is not properly set in array, so it is showing you empty table.
EDIT -
Call connection method properly on view Initialization.
fetchEntries needs to be called in viewDidLoad.