Improper placement of images on scrolling the tableview objective c - ios

hello guys i am downloading images for each product from my server and set it up inside a custom cell of my UITableView and caching them on disk after scrolling down the UITableView images are miss placed what i mean the new cells takes the old values of the previous cells after searching of this topic i found different solution either to use prepareForReuse or checking on the cell if its nil or not both of them does not fit my case.
CODE:
MyCustomCell.h
#import <UIKit/UIKit.h>
#import "mirsaProduct.h"
#import "SVProgressHUD.h"
#import "AFNetworking.h"
#import "UIWebView+AFNetworking.h"
#import "SDWebImageCompat.h"
#import "SDWebImageDownloaderOperation.h"
#import "SDWebImageDownloader.h"
#import "SDImageCache.h"
#import "SDWebImageDownloaderOperation.h"
#import "SDWebImageManager.h"
#import "SDWebImageDecoder.h"
#import "SDWebImagePrefetcher.h"
#interface mirsaProductTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *mirsaProductTitle;
#property (weak, nonatomic) IBOutlet UITextView *mirsaProductDescription;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *mirsaProductActivityIndicatorView;
#property (weak, nonatomic) IBOutlet UIImageView *mirsaProductLogoImageView;
#end
**MyCustomCell.m**
#import "mirsaProductTableViewCell.h"
#implementation mirsaProductTableViewCell
#synthesize mirsaProductTitle = _mirsaProductTitle;
#synthesize mirsaProductDescription = _mirsaProductDescription;
#synthesize mirsaProductLogoImageView = _mirsaProductLogoImageView;
#synthesize mirsaProductActivityIndicatorView = _mirsaProductActivityIndicatorView;
-(void)prepareForReuse
{
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
myTableViewController.h
#import <UIKit/UIKit.h>
#import "mirsaCategories.h"
#import "sharedManagers.h"
#import "mirsaProductTableViewCell.h"
#import "constant.h"
#import "SVProgressHUD.h"
#import "AFNetworking.h"
#import "UIWebView+AFNetworking.h"
#import "SDWebImageCompat.h"
#import "SDWebImageDownloaderOperation.h"
#import "SDWebImageDownloader.h"
#import "SDImageCache.h"
#import "SDWebImageDownloaderOperation.h"
#import "SDWebImageManager.h"
#import "SDWebImageDecoder.h"
#import "SDWebImagePrefetcher.h"
#import "mirsaProduct.h"
#import "mirsaDetailedProductViewController.h"
#import "mirsaProductDetailsTableViewController.h"
#interface mirsaProductsTableViewController : UITableViewController
#property (nonatomic,strong) mirsaCategories *currentCategory;
#property (nonatomic,strong) NSMutableArray *listOfProducts;
#property (nonatomic,strong) mirsaProduct *currentProduct;
#end
myTableViewController.m
due to not make the question too long i just import the cellOfRowAtIndexPath and the relevant method to it.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"mirsaProductCell";
mirsaProductTableViewCell *cell = (mirsaProductTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[mirsaProductTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] ;
cell.mirsaProductLogoImageView.layer.cornerRadius = 50.0f;
cell.mirsaProductLogoImageView.layer.borderWidth = 1.5f;
cell.mirsaProductLogoImageView.clipsToBounds = YES;
cell.mirsaProductLogoImageView.layer.borderColor = [UIColor colorWithRed:redRedColor green:redGreenColor blue:redBlueColor alpha:ALFA].CGColor;
mirsaProduct *currentProduct = [self.listOfProducts objectAtIndex:indexPath.row];
cell.mirsaProductTitle.text = [NSString stringWithFormat:#"Product Code:%#",currentProduct.mirsaProductCode];
cell.mirsaProductDescription.text = [NSString stringWithFormat:#"Description: %#",currentProduct.mirsaProductDescription];
[self downloadProductLogoImageView:cell :indexPath.row];
for (int i = 0; i < currentProduct.mirsaProductUrlImage.count; i++) {
[self downloadImageWithCached:currentProduct.mirsaProductUrlImage[i] :cell :indexPath.row :(NSInteger)i];
}
}
else
{
cell.mirsaProductLogoImageView.layer.cornerRadius = 50.0f;
cell.mirsaProductLogoImageView.layer.borderWidth = 1.5f;
cell.mirsaProductLogoImageView.clipsToBounds = YES;
cell.mirsaProductLogoImageView.layer.borderColor = [UIColor colorWithRed:redRedColor green:redGreenColor blue:redBlueColor alpha:ALFA].CGColor;
mirsaProduct *currentProduct = [self.listOfProducts objectAtIndex:indexPath.row];
cell.mirsaProductTitle.text = [NSString stringWithFormat:#"Product Code:%#",currentProduct.mirsaProductCode];
cell.mirsaProductDescription.text = [NSString stringWithFormat:#"Description: %#",currentProduct.mirsaProductDescription];
[self downloadProductLogoImageView:cell :indexPath.row];
for (int i = 0; i < currentProduct.mirsaProductUrlImage.count; i++) {
[self downloadImageWithCached:currentProduct.mirsaProductUrlImage[i] :cell :indexPath.row :(NSInteger)i];
}
}
return cell;
}
-(void)downloadProductLogoImageView:(mirsaProductTableViewCell *)cell :(NSInteger )index;
{
#autoreleasepool {
[cell.mirsaProductActivityIndicatorView startAnimating];
mirsaProduct *currentProduct = [self.listOfProducts objectAtIndex:index];
NSString *cachedKey = currentProduct.mirsaProductImage;
SDImageCache *imageCache = [[SDImageCache alloc] initWithNamespace:#"productLogoImageView"];
[imageCache queryDiskCacheForKey:cachedKey done:^(UIImage *image, SDImageCacheType cacheType)
{
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
[cell.mirsaProductActivityIndicatorView stopAnimating];
cell.mirsaProductLogoImageView.image = image;
});
}else{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:currentProduct.mirsaProductImage];
[[SDWebImageDownloader sharedDownloader]downloadImageWithURL:url options:SDWebImageDownloaderLowPriority progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
if (finished && image){
dispatch_async(dispatch_get_main_queue(), ^{
[imageCache setMaxCacheAge:60*60*24];
[imageCache storeImage:image
recalculateFromImage:NO
imageData:data
forKey:currentProduct.mirsaProductImage
toDisk:YES];
});
[cell.mirsaProductActivityIndicatorView stopAnimating];
cell.mirsaProductLogoImageView.image = image;
}
}];
});
}
}];
}
}
some links that i found on stack overflow Tableview images chaging when scrolling using custom tableview, Incorrect cell data display when scrolling UITableView

Hi as far i go through your code there two major changes that need to be done to solve your problem
if (cell == nil) {
cell = [[mirsaProductTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] ;
cell.mirsaProductLogoImageView.layer.cornerRadius = 50.0f;
in this lines of code don't use nil instead of use cell Identifier
to download image you don't need to write that much of code just write
[imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.example.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];

A third party library like SDWebImage is a reasonable idea, though a simple home-rolled version is not too tough to create. Instead of a regular image view in the cell, use your own subclass, something like this:
// .h
#import <UIKit/UIKit.h>
#interface AsynchImageView : UIImageView
- (void)setImageFromUrl:(NSString *)url placeholder:(UIImage *)placeholder;
#end
// .m
#import "AsynchImageView.h"
#implementation AsynchImageView
- (void)setImageFromUrl:(NSString *)url placeholder:(UIImage *)placeholder {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLCache *cache = [NSURLCache sharedURLCache];
NSCachedURLResponse *cachedResponse = [cache cachedResponseForRequest:request];
if (cachedResponse) {
[self setImageFromData:cachedResponse.data];
} else {
self.image = placeholder;
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
[cache storeCachedResponse:[[NSCachedURLResponse alloc] initWithResponse:response data:data] forRequest:request];
[self setImageFromData:data];
}
}] resume];
}
}
- (void)setImageFromData:(NSData *)data {
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
self.image = image;
});
}
#end
This checks to see if the image has been downloaded already, if it hasn't it sets a placeholder image and starts a download. Upon completion, it sets the image to the downloaded one and caches it.
Remove all of the other image code when configuring the cell, and do this:
NSString *url = currentProduct.mirsaProductImage;
[cell.mirsaProductLogoImageView setImageFromUrl: placeholder:];

Related

Passing data using calloutAccessoryControlTapped Xcode

I am developing an app in Xcode (objective-c). My app has a TableView with a list of restaurants and when you press one row, another view is opened with the restaurant information. The method I am using is that I am sending the title in the row to the new view and depending on the title I load the information of the restaurant. I want to do exactly the same using a map pin button. My problem is that I am trying to send the TitleLabel to other ViewController but this is not working and I don't know why.
This is my map pin: RestMapPin.h:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface RestMapPin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
This is my RestMappin.m:
#import "RestMapPin.h"
#implementation RestMapPin
#synthesize coordinate, title, subtitle;
#end
This is my MapViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController {
MKMapView *mapView;
}
#property (weak, nonatomic) IBOutlet UIBarButtonItem *barButton;
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
-(IBAction)setMap:(id)sender;
#end
This is my MapViewController.m:
#import "MapViewController.h"
#import "SWRevealViewController.h"
#import "RestMapPin.h"
#import "RestViewController.h"
#import "MainTableViewController.h"
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
_barButton.target = self.revealViewController;
_barButton.action = #selector(revealToggle:);
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
mapView.delegate = self;
/*Babelia*/
MKCoordinateRegion region_Babelia = { {0.0, 0.0}, {0.0, 0.0}};
region_Babelia.center.latitude = 40.4234778;
region_Babelia.center.longitude = -3.686283000000003;
region_Babelia.span.longitudeDelta = 0.1f;
region_Babelia.span.latitudeDelta = 0.1f;
[mapView setRegion:region_Babelia animated:YES];
RestMapPin *ann_Babelia = [[RestMapPin alloc] init];
ann_Babelia.title = #"Babelia";
ann_Babelia.subtitle = #"Barrio de Salamanca";
ann_Babelia.coordinate = region_Babelia.center;
[mapView addAnnotation:ann_Babelia];
/*Bacira*/
MKCoordinateRegion region_Bacira = { {0.0, 0.0}, {0.0, 0.0}};
region_Bacira.center.latitude = 40.43375390000001;
region_Bacira.center.longitude = -3.699036299999989;
region_Bacira.span.longitudeDelta = 0.1f;
region_Bacira.span.latitudeDelta = 0.1f;
[mapView setRegion:region_Bacira animated:YES];
RestMapPin *ann_Bacira = [[RestMapPin alloc] init];
ann_Bacira.title = #"Bacira";
ann_Bacira.subtitle = #"Chamberí";
ann_Bacira.coordinate = region_Bacira.center;
[mapView addAnnotation:ann_Bacira];
/*Indicador de posicion del mapa (para centrarlo)*/
MKCoordinateRegion region_posicion = { {0.0, 0.0}, {0.0, 0.0}};
region_posicion.center.latitude = 40.44934744420573;
region_posicion.center.longitude = -3.695504665374756;
region_posicion.span.longitudeDelta = 0.08f;
region_posicion.span.latitudeDelta = 0.08f;
[mapView setRegion:region_posicion animated:YES];
/*************************************************/
}
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != mapView.userLocation) {
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"pin2#2x.png"];
}
else {
//[mapView.userLocation setTitle:#"I am here"];
}
UIButton *pinButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//if ([[annotation title] isEqualToString:#"Marieta"]) {
//[pinButton addTarget:self action:#selector(annotationView:) forControlEvents:UIControlEventTouchUpInside];
//}
pinView.rightCalloutAccessoryView = pinButton;
return pinView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
RestMapPin *selectedAnnotation = view.annotation;
NSLog(#"Title of selected pin - %#", selectedAnnotation.title);
// Here you get the title of selected annotation
//RestViewController *objYourVC = [[RestViewController alloc]init];
RestViewController *objYourVC = [self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
objYourVC.TitleLabel = selectedAnnotation. title;
NSLog(#"objYourVC.TitleLabel - %#", objYourVC.TitleLabel);
//objYourVC.DetailModal.title = selectedAnnotation.title;
//NSLog(#"objYourVC.TitleLabel - %#", objYourVC.TitleLabel);
objYourVC.DescriptionLabel = selectedAnnotation. subtitle;
NSLog(#"objYourVC.DescriptionLabel - %#", objYourVC.DescriptionLabel);
[self.navigationController pushViewController:objYourVC animated:YES];
}
-(IBAction)setMap:(id)sender {
switch (((UISegmentedControl *) sender).selectedSegmentIndex) {
case 0:
mapView.mapType = MKMapTypeStandard;
break;
case 1:
mapView.mapType = MKMapTypeSatellite;
break;
case 2:
mapView.mapType = MKMapTypeHybrid;
break;
default:
break;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Then I am going to show you the view that where I want to get the data of the objYourVC.TitleLabel
This is my RestViewController.h:
#import <UIKit/UIKit.h>
#import "Restaurant.h"
#interface RestViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong, nonatomic) IBOutlet UILabel *DescriptionLabel;
#property (strong, nonatomic) IBOutlet UIImageView *ImageView;
//#property (strong, nonatomic) IBOutlet NSArray *DetailModal;
#property (weak, nonatomic) IBOutlet UITextView *phoneTextView;
#property (weak, nonatomic) IBOutlet UIButton *webButton;
#property (weak, nonatomic) IBOutlet UITextView *adressTextView;
#property (weak, nonatomic) IBOutlet UIButton *cartaButton;
#property (weak, nonatomic) IBOutlet UITextView *reviewTextView;
#property (weak, nonatomic) IBOutlet UILabel *updateLabel;
#property (nonatomic, strong) Restaurant *DetailModal;
#end
This is my RestViewController.m:
#import "RestViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface RestViewController ()
#end
#implementation RestViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString *decDate = #"11/2016";
if ([_DetailModal.title isEqualToString:#"Babelia"]) {
_TitleLabel.text = _DetailModal.title;
_DescriptionLabel.text = _DetailModal.desc;
_ImageView.image = [UIImage imageNamed:_DetailModal.image];
_phoneTextView.text = #"(+34) 918 31 71 79";
_adressTextView.text = #"\n• Callejón de Puigcerdá, 6, Madrid, España";
[_webButton setTitle:#"Web" forState:UIControlStateNormal];
[_webButton addTarget:self action:#selector(openWeb_babelia_Url) forControlEvents:UIControlEventTouchUpInside];
[_cartaButton setTitle:NSLocalizedString (#"Menu", nil) forState:UIControlStateNormal];
[_cartaButton addTarget:self action:#selector(openCarta_babelia) forControlEvents:UIControlEventTouchUpInside];
_reviewTextView.text = NSLocalizedString(#"No reviews available.", nil);
_updateLabel.text = [NSString stringWithFormat:NSLocalizedString(#"Updated: %#", nil), decDate];
}
if ([_DetailModal.title isEqualToString:#"Bacira"]) {
_TitleLabel.text = _DetailModal.title;
_DescriptionLabel.text = _DetailModal.desc;
_ImageView.image = [UIImage imageNamed:_DetailModal.image];
_phoneTextView.text = #"(+34) 91 866 40 30";
_adressTextView.text = #"\n• Calle Del Castillo, 16, Madrid, España";
[_webButton setTitle:#"Web" forState:UIControlStateNormal];
[_webButton addTarget:self action:#selector(openWeb_bacira_Url) forControlEvents:UIControlEventTouchUpInside];
[_cartaButton setTitle:NSLocalizedString (#"Menu", nil) forState:UIControlStateNormal];
[_cartaButton addTarget:self action:#selector(openCarta_bacira) forControlEvents:UIControlEventTouchUpInside];
_reviewTextView.text = NSLocalizedString(#"No reviews available.", nil);
_updateLabel.text = [NSString stringWithFormat:NSLocalizedString(#"Updated: %#", nil), decDate];
}
}
-(void)openWeb_babelia_Url{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://babeliarestaurante.com/contactar/"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
-(void)openWeb_bacira_Url{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://www.bacira.es/contacto/4585843222"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
-(void)openCarta_babelia{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://babeliarestaurante.com/nuestra-cocina/las-cartas/"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
-(void)openCarta_bacira{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://www.bacira.es/carta/4591994095"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
#end
The problem is that the method calloutAccessoryControlTapped: is not working well because the RestViewController.m is not receiving the objYourVC.TitleLabel. What can I do?
When I run the project, the objYourVC.TitleLabel is good in the MapViewController.m (#"Bacira" for example), but when the project goes to RestViewContoller.m the TitleLable is not good, it shows (#"Label").
I know I have a low level of Xcode and I need your help. I am trying to learn more every day. Can anyone help me? Thank you very much.
Edit: This is my Restaurant.h:
#import <Foundation/Foundation.h>
#interface Restaurant : NSObject
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *desc;
#property (nonatomic, copy) NSString *image;
- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image;
#end
And this is my restaurant.m:
#import "Restaurant.h"
#implementation Restaurant
- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image {
self = [super init];
if (self != nil) {
self.title = title;
self.desc = description;
self.image = image;
}
return self;
}
#end
You cannot directly deal with IBoutlet , because they have weak reference. o you need to store it an varaible and then in viewDidLoad you need to update the appropriate IBOutlets.
MapViewController.m
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
RestMapPin *selectedAnnotation = view.annotation;
NSLog(#"Title of selected pin - %#", selectedAnnotation.title);
// Here you get the title of selected annotation
//RestViewController *objYourVC = [[RestViewController alloc]init];
RestViewController *objYourVC = [self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
objYourVC.DetailModal.pagetitle= selectedAnnotation.title;
objYourVC.DetailModal.pageDescription = selectedAnnotation.desc;
[self.navigationController pushViewController:objYourVC animated:YES];
}
RestViewController.h:
#import <UIKit/UIKit.h>
#import "Restaurant.h"
#interface RestViewController : UIViewController
#property (nonatomic, strong) NSString *pageTitle;
#property (nonatomic, strong) NSString *pageDescription ;
#end
RestViewController.m:
#import "RestViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface RestViewController ()
#end
#implementation RestViewController
- (void)viewDidLoad {
[super viewDidLoad];
_TitleLabel.text = _pageTitle;
_DescriptionLabel.text = _pageDescription;
}
#end

How to retrieve data properly using realm

I had a problem to retrieve data using realm. What i wanna do is caching the data so that i can use it when user first load the app or user does not have internet connection. Below is the logic what i wanna do.
request from fb api -> fb return 10 data -> display returned data and cache returned data -> if user doesn't have internet connection display cache data or if user have internet connection fetch new data.
below is my code :
FBVideo.h
#import <Realm/Realm.h>
#interface FBVideo : RLMObject
#property (nonatomic, strong) NSString *pageBefore;
#property (nonatomic, strong) NSString *pageAfter;
#property (nonatomic, strong) NSString *thumbnailsURI;
#property (nonatomic, strong) NSString *titleDescription;
#property NSString *id;
#end
FBVideo.m
#import "FBVideo.h"
#implementation FBVideo
+ (NSString *)primaryKey {
return #"id";
}
// Specify default values for properties
+ (NSDictionary *)defaultPropertyValues {
return #{#"pageBefore":#"", #"pageAfter":#"", #"thumbnailsURI":#"", #"titleDescription":#""};
}
+ (NSArray *)ignoredProperties {
return #[];
}
#end
PageVideosCVC.h
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#import "FBVideo.h"
#interface PageVideosCVC : UICollectionViewController
#property (strong, nonatomic) NSMutableArray *videoArray;
#property (strong, nonatomic) NSString *pageID;
#property (strong, nonatomic) NSString *pageName;
#property (strong, nonatomic) MPMoviePlayerController *playerController;
#property (assign, nonatomic) CATransform3D initialTransformation;
#property (nonatomic, strong) NSMutableSet *shownIndexes;
//#property (strong, nonatomic) FBVideo *fbVideoRealm;
#end
PageVideosCVC.m
#import "PageVideosCVC.h"
#import "facebook.h"
#import "MBProgressHUD.h"
#import "Reachability.h"
#import <AFNetworking/AFNetworking.h>
#import <AVFoundation/AVFoundation.h>
#import <SDWebImage/UIImageView+WebCache.h>
#import <QuartzCore/QuartzCore.h>
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
#interface PageVideosCVC () <UICollectionViewDataSource,UICollectionViewDelegate> {
NSString *pageBefore;
NSString *pageAfter;
NSString *thumbnailsURI;
Reachability *internetReachable;
NSDictionary *videoInfoToSaveInRealm;
// RLMResults *videoResultsFrom
}
#end
#implementation PageVideosCVC
#synthesize videoArray;
static NSString * const reuseIdentifier = #"Cell";
- (void) viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
videoArray = [NSMutableArray array];
/* Make a card effect, rotate the angle of the collectionviewcell to -15
1) Start with an identity transform, which is a fancy math term for “do nothing.”
2) Call CATransform3DRotate to apply a rotation of -15 degrees (in radians), where the negative value indicates a clockwise rotation.
3) Apply the rotation around the axis 0.0, 0.0, 1.0; this represents the z-axis, where x=0, y=0, and z=1.
4) Applying just the rotation to the card isn’t enough, as this simply rotates the card about its center. To make it look like it’s tipped over on a corner, add a translation or shift where the negative values indicate a shift up and to the left.
*/
CGFloat rotationAngleDegrees = -15;
CGFloat rotationAngleRadians = rotationAngleDegrees * (M_PI/180);
CGPoint offsetPositioning = CGPointMake(-20, -20);
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, rotationAngleRadians, 0.0, 0.0, 1.0);
transform = CATransform3DTranslate(transform, offsetPositioning.x, offsetPositioning.y, 0.0);
_initialTransformation = transform;
_shownIndexes = [NSMutableSet set];
}
- (void)viewWillAppear:(BOOL)animated {
UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
navBar.barTintColor = UIColorFromRGB(0x266593);
// Altering the font style of the navigation bar title
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
shadow.shadowOffset = CGSizeMake(0, 1);
[[UINavigationBar appearance] setTranslucent:NO];
[[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:245.0/255.0 green:245.0/255.0 blue:245.0/255.0 alpha:1.0], NSForegroundColorAttributeName,
shadow, NSShadowAttributeName,
[UIFont fontWithName:#"HelveticaNeue-CondensedBlack" size:21.0], NSFontAttributeName, nil]];
[self.view addSubview: navBar];
UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"Down Arrow.png"] style:UIBarButtonItemStyleBordered target:self action:#selector(backButtonTapped:)];
// UIBarButtonItem *cancelItem = [[UIBarButtonItem alloc] initWithTitle:#"Back"
// style:UIBarButtonItemStylePlain
// target:self
// action:#selector(backButtonTapped:)];
[cancelItem setTintColor:[UIColor whiteColor]];
// 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];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[self loadVideo:#"a" pagesID:self.pageID];
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if ([pageBefore isEqual:pageBefore]) {
return videoArray.count;
}
return videoArray.count + 1;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == [videoArray count] - 1) {
NSLog(#"page after : %#", pageAfter);
[self loadVideo:pageAfter pagesID:self.pageID];
}
if (![self.shownIndexes containsObject:indexPath]) {
[self.shownIndexes addObject:indexPath];
// Transform collectionviewcell layer
UIView *card = [(UICollectionViewCell*)cell contentView];
card.layer.transform = self.initialTransformation;
card.layer.opacity = 0.5;
[UIView animateWithDuration:0.5 animations:^{
card.layer.transform = CATransform3DIdentity;
card.layer.opacity = 1;
}];
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
__weak typeof(self) weakSelf = self;
if (indexPath.row == [videoArray count]) {
NSLog(#"this is last cell, later make it UIActivityIndicatorView");
} else {
// RLMResults *objects;
//
// objects = [FBVideo allObjects];
// FBVideo *fbVideoRealm = objects[indexPath.row];
//
// UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
// NSURL *thumbnailImage = [NSURL URLWithString:fbVideoRealm.thumbnailsURI];
// [imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
//
// UILabel *titleDescription = (UILabel *)[cell viewWithTag:10];
// titleDescription.text = fbVideoRealm.titleDescription;
NSDictionary *videoData = weakSelf.videoArray[indexPath.row];
NSDictionary *videoThumbnails = [videoData valueForKey:#"thumbnails"];
NSArray *thumbnailsData = [videoThumbnails objectForKey:#"data"][0];
thumbnailsURI = [thumbnailsData valueForKey:#"uri"];
UIImageView *imgView = (UIImageView *)[cell viewWithTag:100];
NSURL *thumbnailImage = [NSURL URLWithString:thumbnailsURI];
[imgView sd_setImageWithURL:thumbnailImage placeholderImage:[UIImage imageNamed:#"placeholder.jpg"]];
UILabel *titleDescription = (UILabel *)[cell viewWithTag:10];
titleDescription.text = videoData[#"description"];
}
return cell;
}
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *videoSource = videoArray[indexPath.row];
NSURL *videoURL = [NSURL URLWithString:[videoSource valueForKey:#"source"]];
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];
}
#pragma mark - Helper Methods
- (void)loadVideo:(NSString*)currentPage pagesID:(NSString*)pagesID{
__weak typeof(self) weakSelf = self;
NSString *fbToken = [facebook currentFBAccessToken];
NSString *fbNextVideoURL = [NSString stringWithFormat:#"https://graph.facebook.com/v2.5/%#/videos?access_token=%#&pretty=0&fields=source,description,thumbnails.limit(1),length&limit=10&after=%#", pagesID, fbToken, currentPage];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:fbNextVideoURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *videoDict = [[NSDictionary alloc] initWithDictionary:responseObject];
if (responseObject != nil) {
[weakSelf.videoArray addObjectsFromArray:[videoDict valueForKeyPath:#"data"]];
pageBefore = [videoDict valueForKeyPath:#"paging.cursors.before"];
pageAfter = [videoDict valueForKeyPath:#"paging.cursors.after"];
// Caching pageBefore, pageAfter, thumbnailsURI, titleDescription data to REALM
for (videoInfoToSaveInRealm in weakSelf.videoArray) {
NSDictionary *videoThumbnails = [videoInfoToSaveInRealm valueForKey:#"thumbnails"];
NSArray *thumbnailsData = [videoThumbnails objectForKey:#"data"][0];
[[RLMRealm defaultRealm] transactionWithBlock:^{
[FBVideo createOrUpdateInDefaultRealmWithValue:#{#"id": self.pageID, #"titleDescription": videoInfoToSaveInRealm[#"description"], #"thumbnailsURI": [thumbnailsData valueForKey:#"uri"], #"pageBefore": pageBefore, #"pageAfter": pageAfter}];
}];
[self retrieveDataFromRealm];
}
//NSLog(#"first product's image: %#", (FBVideo *)[FBVideo allObjects]);
// Update UICollectionView UI
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
[self.collectionView reloadData];
});
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
- (void)retrieveDataFromRealm {
RLMResults *objects;
objects = [FBVideo allObjects];
FBVideo *fbVideoRealm = [[FBVideo alloc] init];
for (fbVideoRealm in objects) {
// NSLog(#"realm object count : %d", (int)objects.count);
NSLog(#"realm description : %#", fbVideoRealm.titleDescription);
NSLog(#"realm thumbnails URi : %#", fbVideoRealm.thumbnailsURI);
NSLog(#"realm page before : %#", fbVideoRealm.pageBefore);
NSLog(#"realm page after : %#", fbVideoRealm.pageAfter);
};
}
#end
Thank you in advance.
You should store the Facebook API response directly in Realm (don't display it right away), and then you can follow the pattern demonstrated in Realm's "TableView" example to back your UITableView with an RLMResults, and update the table when its data changes.
Since you'll always be loading data from the Realm this way, you get offline mode "for free".

Set button title programmatically

I made a button in storyboard and associated it with an IBAction in my header file. How can I set the title of this button to the variable I made displayPhone and have it call that number as well?
.h
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface IBThirdViewController : UIViewController
#property (nonatomic, strong) PFRelation *agentRelation;
#property (nonatomic, strong) NSArray *agent;
#property (weak, nonatomic) IBOutlet UILabel *agentName;
#property (strong, nonatomic) IBOutlet UILabel *agentPhone;
#property (strong, nonatomic) IBOutlet UILabel *agentEmail;
#property (strong, nonatomic) IBOutlet UIImageView *agentImage;
- (IBAction)phoneButton:(id)sender;
#end
.m
#import "IBThirdViewController.h"
#import "IBAgentsTableViewController.h"
#interface IBThirdViewController ()
#end
#implementation IBThirdViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//Find the Agent and show it
self.agentRelation = [[PFUser currentUser] objectForKey:#"agentRelation"];
PFQuery *query = [self.agentRelation query];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// success
self.agent = objects;
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"name: %#", [object objectForKey:#"name"]);
NSLog(#"email: %#", [object objectForKey:#"email"]);
NSString *displayEmail = [object objectForKey:#"email"];
NSString *displayName = [object objectForKey:#"name"];
NSString *displayPhone = [object objectForKey:#"phone"];
PFFile *thumbnail = [object objectForKey:#"profilePic"];
NSURL *imageFileURL = [[NSURL alloc] initWithString:thumbnail.url];
NSData *imageData = [NSData dataWithContentsOfURL:imageFileURL];
self.agentEmail.text = displayEmail;
self.agentName.text = displayName;
self.agentPhone.text = displayPhone;
self.agentImage.image = [UIImage imageWithData:imageData];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showEditAgent"]) {
IBAgentsTableViewController *viewController = (IBAgentsTableViewController *)segue.destinationViewController;
viewController.agents = [NSMutableArray arrayWithArray:self.agent];
}
}
- (IBAction)phoneButton:(id)sender {
}
#end
First of all you need connect button from xib with IBOutlet object:
#property (nonatomic, weak) IBOutlet UIButton *displayPhone;
Then set it's title in -(void)viewDidAppear:(BOOL)animated after loading data:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//...
// Load data here
//...
[self.displayPhone setTitle:displayPhone forState:UIControlStateNormal];
}
Finally implement IBAction method for button:
- (IBAction)phoneButton:(id)sender {
NSString *phone = [sender titleForState:UIControlStateNormal];
// Remove all chars except of digits
static NSString *const kDigitsString = #"0123456789";
phone = [[phone componentsSeparatedByCharactersInSet:[[NSCharacterSet characterSetWithCharactersInString:kDigitsString] invertedSet]] componentsJoinedByString:#""];
// Initiate call
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", phone]]];
}
It looks like you haven't connected the button to an outlet but only to an action.
First you need to connect it to an outlet (like you've done with the labels).
Then use...
[self.button setTitle:#"blah" forState:UIViewControlStateNormal];
Something like that anyway. I'm currently on my iPhone so I don't have auto complete.
If you want to change the title inside the IBAction method do:
[sender setTitle:#"My title" forState:UIControlStateNormal];
If you want to change in any other place you need a #property of uibutton, something like this
#property (strong, nonatomic) IBOutlet UIButton *phoneButtonProperty;
and connect it to your button and then
[phoneButtonProperty setTitle:#"My title" forState:UIControlStateNormal];

How to load url, what come from popoverclass? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
This is probably is pretty easy, but I'm stuck with it today.
The idea is that in my browser, I've create uiwebview and I want to implimate address bar in popover with it own class.
I can get the url from UItextfield from popover class to webview class, but when I get it uiwebview get lazy and it doesn't load it.
When I check it, debuger says that webview is null.
This is ViewController.h
#import <UIKit/UIKit.h>
#import "AdressBar.h"
#import "mypopoverController.h"
#interface ViewController : UIViewController<AddressbarDelegate>
{
UIWebView* mWebView;
mypopoverController *popoverController;
}
#property (nonatomic, retain) IBOutlet UIWebView* webPage;
#end
This is ViewController.m:
#import "mypopoverController.h"
#import "MyOwnPopover.h"
#import "ViewController.h"
#import "AdressBar.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize webPage = mWebView;
- (void)viewDidLoad
{
[super viewDidLoad];
addressBar = [[AdressBar alloc] init];
addressBar.delegate = self;
[edittext addTarget:self action:#selector(showPopoverAdressBar:forEvent:) forControlEvents:UIControlEventTouchUpInside];
NSURL *url = [NSURL URLWithString:#"http://www.google.lv"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[mWebView setScalesPageToFit:YES];
[mWebView setDelegate:self];
[mWebView loadRequest:request];
}
-(void)loadReceivedAddress:(NSURLRequest *)url{
NSLog(#"url= %#", url);//there url always is not null and mWebView should load it
if(mWebView != nil){
[mWebView loadRequest:url];
}else{
NSLog(#"mWebView is null");//...but there it say's that it's null
}}
-(void)showPopoverAdressBar:(id)sender forEvent:(UIEvent*)event
{
AdressBar *popoverControllesr = [[AdressBar alloc]init];
popoverControllesr.view.frame = CGRectMake(0,0, 600, 45);
popoverControllesr.view.backgroundColor = [UIColor whiteColor];
popoverController = [[mypopoverController alloc] initWithContentViewController:popoverControllesr];
popoverController.cornerRadius = 20;
if(_titles!=NULL){
popoverController.titleText = _titles;}else{
popoverController.titleText = #"Loading...";
}
popoverControllesr.address.text = absoluteString;
popoverController.popoverBaseColor = [UIColor orangeColor];
popoverController.popoverGradient= YES;
popoverController.arrowPosition = TSPopoverArrowPositionHorizontal;
[popoverController showPopoverWithTouch:event];
}
#end
This is AdressBar.h
#import <UIKit/UIKit.h>
#protocol AddressbarDelegate <NSObject>
#required
-(void)loadSomethingFromAddressBar:(NSURLRequest*)request;
#end
#interface AdressBar : UIViewController{
IBOutlet UIButton *cancel;
}
#property (nonatomic, retain) IBOutlet UITextField *address;
#property (nonatomic, retain) NSURLRequest *request;
#property(nonatomic, weak) id <AddressbarDelegate> delegate;
#end
This is AdressBar.m:
#import "AdressBar.h"
#import "ViewController.h"
#interface AdressBar ()
#end
#implementation AdressBar
#synthesize delegate = delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[_address setDelegate:self];
_address.clearButtonMode =
UITextFieldViewModeWhileEditing;
_address.keyboardType = UIKeyboardTypeURL;
[_address addTarget:self
action:#selector(loadAddresss)
forControlEvents:UIControlEventEditingDidEndOnExit];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)loadAddresss {
NSString* urlString = _address.text;
NSURL* url = [NSURL URLWithString:urlString];
if(!url.scheme)
{
NSString* modifiedURLString = [NSString stringWithFormat:#"http://%#", urlString];
url = [NSURL URLWithString:modifiedURLString];
}
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSLog(#"request= %#", request);
NSLog(#"text= %#", urlString);
if (request!=nil) {
if(delegate!=nil)
{NSLog(#"delegate not nil");
[delegate loadSomethingFromAddressBar:request];
}else{
NSLog(#"delegate is nil");//There delegate always is nil
}
}
}
#end
Make sure that your web view Outlet & Delegate is correctly conncted.
There no space between URL Address because I also face the same issue. Try to open that url in web-Browser.
If this is your view hierarchy
---- In ViewController
---- Showing AddressBar View in POPOver
---- Remove POPover and display ViewController's web view
I suggest create a custom delegate method in AddressBar and when you remove the popOver trigger the delegate method. Implement the delegate in your ViewContrller and call loadSomethingFromAddressBar in that implemented delegate method
Note : make sure you have connected you webpage IBOutlet to your nib file.
// In Adressbar.h
#protocol AddressbarDelegate <NSObject>
#required
-(void)loadYourWebViewNow:(NSURLRequest*)request;
#end
#interface Addressbar : UIViewController
{
}
#property(nonatomic, weak) id <AddressbarDelegate>
// In Adressbar.m
- (void)loadAddresss {
NSString* urlString = _address.text; //geting text from UItextField
NSURL* url = [NSURL URLWithString:urlString];
if(!url.scheme)
{
NSString* modifiedURLString = [NSString stringWithFormat:#"http://%#", urlString];
url = [NSURL URLWithString:modifiedURLString];
}
NSURLRequest *request = [NSURLRequest requestWithURL:url];
if (request!=nil) {
NSLog(#"request is good");
if(_delegate!=nil)
{
[_delegate loadYourWebViewNow:request];
}
}
// In your ViewController.h
#interface ViewController : UIViewController<AddressbarDelegate>
{
//AdressBar *addressBar;
}
// In your ViewController.m implement the delegate method and set the delegate
#implementation ViewController
-(void)viewDidLoad
{
Remove these two below lines on viewDidLoad
//addressBar = [[Adressbar alloc] init];
//addressbar.delegate = self;
}
-(void)loadYourWebViewNow:(NSURLRequest*)request
{
[self loadSomethingFromAddressBar:request];
}
-(void)showPopoverAdressBar:(id)sender forEvent:(UIEvent*)event
{
AdressBar *popoverControllesr = [[AdressBar alloc]init];
popoverControllesr.delegate = self; // set the delegate here to this object.
popoverControllesr.view.frame = CGRectMake(0,0, 600, 45);
popoverControllesr.view.backgroundColor = [UIColor whiteColor];
popoverController = [[mypopoverController alloc] initWithContentViewController:popoverControllesr];
popoverController.cornerRadius = 20;
if(_titles!=NULL){
popoverController.titleText = _titles;}else{
popoverController.titleText = #"Loading...";
}
popoverControllesr.address.text = absoluteString;
popoverController.popoverBaseColor = [UIColor orangeColor];
popoverController.popoverGradient= YES;
popoverController.arrowPosition = TSPopoverArrowPositionHorizontal;
[popoverController showPopoverWithTouch:event];
}

Load "Loading" image before laoding Image from server?

I am new to iOS development so please bear with me.
I am trying to create a basic photo gallery but ran into a problem.
When I started out with the project I just included all the images in my project.
Now after having a lot more images(400+) I started loading them from a server.
I made an array of images using the following line of code:
[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.testsite.com/testPic.png"]]]
Obviously making the user wait for an array of 400+ images to load from a server is unacceptable.
So my question is if I included one image in my project that said something like "Loading", how could I display that image until the actual image loaded from the server?
I'm making a basic grid-style photo gallery using a table-view and scroll-view. It loads up a few rows of small(thumbnail) images and when you click one it makes it full screen.
I'm using Xcode 4.3, ARC, and storyboards if that helps!
Sorry if this is confusing!
-Shredder2794
The simplest way of doing this is to use AFNetworking, which provides setImageWithURL:placeholderImage: in a category on UIImageView (also a method with success/failure handlers).
A method is to subclass UIImageView. When you allocate it you put a default image ( the loading one) or a UIActivityIndicator, download the image you want to display ( in a separate thread) and when the image is downloaded display it. Have a look to NSURLRequest and NSURLConnection for the image download.
* EDIT *
Here is an example of code I developed. You can use this as a start point to develop your own loading image class. This class can be improved by using NSThread for the image loading.
// ImageLoader.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
/**
* #brief Class that loads an UIImage from a server
* #author Nicolas
*/
#interface ImageLoader : UIView
{
#private
NSURLConnection *connection;
NSMutableData *data;
NSString *path;
UIActivityIndicatorView *loading;
UIImageView *imageView;
}
#property (nonatomic, retain) UIActivityIndicatorView *loading;
#property (nonatomic, retain) NSURLConnection *connection;
#property (nonatomic, retain) NSMutableData *data;
#property (nonatomic, retain) NSString *path;
#property (nonatomic, retain) UIImageView *imageView;
/**
* Load an image from a server an display it
* #param URL URL to get the image
* #param chemin path to save the image
* #author Nicolas
*/
- (void)loadImageFromUrl:(NSString *)URL forPath:(NSString *)chemin;
#end
// ImageLoader.m
#import "ImageLoader.h"
#implementation ImageLoader
#synthesize path, connection, data, loading, imageView;
- (id)init
{
self = [super init];
[self setUserInteractionEnabled:YES];
return self;
}
- (void)loadImageFromUrl:(NSString *)URL forPath:(NSString *)chemin
{
//if (connection != nil) [connection release];
//if (data != nil) [data release];
//if (path != nil) [path release];
self.path = chemin;
if ([[NSFileManager defaultManager] fileExistsAtPath:chemin])
{
if (imageView != nil)
{
[imageView removeFromSuperview];
[imageView release];
}
imageView = [[UIImageView alloc] initWithFrame:self.bounds];
imageView.image = [UIImage imageWithContentsOfFile:chemin];
[self addSubview:imageView];
}
else
{
loading = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 20.0f, 20.0f)];
loading.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
[loading setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[loading startAnimating];
[self addSubview:loading];
NSURL *myURL = [NSURL URLWithString:[URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:myURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0f];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
}
#pragma mark -
#pragma mark NSURLConnection protocol
- (void)connection:(NSURLConnection *)_connection didReceiveData:(NSData *)_data
{
if (data == nil)
{
data = [[NSMutableData alloc] initWithCapacity:2048];
}
[data appendData:_data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)_connection
{
[data writeToFile:self.path atomically:YES];
if (imageView != nil)
{
[imageView removeFromSuperview];
[imageView release];
}
imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:data]];
imageView.frame = self.bounds;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[loading stopAnimating];
[loading setHidden:YES];
[self addSubview:imageView];
}
- (void)connection:(NSURLConnection *)_connection didFailWithError:(NSError *)error
{
[loading stopAnimating];
[loading release];
}
#pragma mark - Memory management
- (void)dealloc
{
[connection cancel];
[connection release];
[imageView release];
[path release];
[data release];
[super dealloc];
}
#end

Resources