I am trying to parse a JSON image url and display it in a view. I have no trouble getting the image url and converting it to UIImage. When the user selects a row in the tableview a new view is presented and displays the image from the url. The issue is that the image is different every time the view loads. I NSLog the url and it is the same every time I select the row. I can not see where I am going wrong here.
This is the view that gets the image url and converts it to an image:
// ViewController.m
#import "ViewController.h"
#import "DetailViewController.h"
#interface ViewController ()
#end
#implementation ViewController
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
//imgURL = [imgURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *imageUrl = [NSURL URLWithString:[[_model.bars objectAtIndex:indexPath.row] objectForKey:#"image_url"]];
//NSLog(#"%#", imageUrl);
UIImage *barImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageUrl]];
NSLog(#"%#", imageUrl);
_model.barAddress = [NSString stringWithFormat: #"%# %# %#", [[_model.bars objectAtIndex:indexPath.row] objectForKey:#"address"],
[[_model.bars objectAtIndex:indexPath.row] objectForKey:#"state"],
[[_model.bars objectAtIndex:indexPath.row] objectForKey:#"zip"]];
_detailData.selectedBarName = [[_model.bars objectAtIndex:indexPath.row] objectForKey:#"name"];
_detailData.selectedBarAddress = _model.barAddress;
_detailData.selectedBarPhoneNumber = [[_model.bars objectAtIndex:indexPath.row] objectForKey:#"phone"];
_detailData.selectedBarImage = barImage;
NSLog(#"%#", _detailData.selectedBarImage);
if ([[segue identifier] isEqualToString:#"detailSeg"]) {
DetailViewController *controller = (DetailViewController *)segue.destinationViewController;
controller.barNameObject = _detailData.selectedBarName;
controller.barAddressObject = _detailData.selectedBarAddress;
controller.barPhoneNumberObject = _detailData.selectedBarPhoneNumber;
controller.barImageObject = _detailData.selectedBarImage;
NSLog(#"%#", controller.barImageObject);
}
}
#end
This is the view that displays the image.
// DetailViewController.m
#import "DetailViewController.h"
#import "DetailViewData.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
//_detailData = [[DetailViewData alloc] init];
_model = [[Model alloc] init];
// Do any additional setup after loading the view from its nib.
_barName.text = self.barNameObject;
_barAddress.text = self.barAddressObject;
_barPhone.text = self.barPhoneNumberObject;
_barPhoto.image = self.barImageObject;
}
Your code is absolutely correct.
So, I checked the web service response. If you check any of the image_URl
say http://lorempixel.com/900/500/sports/?v=-417059871 , it is loading different images all the time. I think the issue is not in your code but in the url, just paste it in your browser and refresh, each time it loads different images.
I wanted to add this as a comment but I don't have enough reputation as of now.
Related
I am making a blog reader app. Everything works fine until I try to access the detailView from a cell. I receive this error,
[UINavigationController setPFeedURL:]: unrecognised selector sent to instance 0x7f96d5802800
below code is in the PRTableViewController.m
#import "PRTableViewController.h"
#import "PRFeedPost.h"
#import "PRDetailViewController.h"
This is where the code is where the crash happens
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showDetail"]){
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
PRFeedPost *feed_Post = [self.polisenFeed objectAtIndex:indexPath.row];
[segue.destinationViewController setPFeedURL:feed_Post.url];
}
}
This is to help you understand what I am trying to setPFeedURL to. Also in PRViewTableController.m
self.polisenFeed = [NSMutableArray array];
NSArray *polisenFeedArray = [dataDictionary objectForKey:#"posts"];
for (NSDictionary *postDictionary in polisenFeedArray) {
PRFeedPost *fp = [PRFeedPost feedWithTitle:[postDictionary objectForKey:#"title"]];
fp.author = [postDictionary objectForKey:#"author"];
fp.thumbnail = [postDictionary objectForKey:#"thumbnail"];
fp.date = [postDictionary objectForKey:#"date"];
fp.url = [NSURL URLWithString:[postDictionary objectForKey:#"url" ]];
[self.polisenFeed addObject:fp];
}
Now the PRDetailViewController.h,
This is where the property is I am trying to set is,
#property (strong, nonatomic) NSURL *pFeedURL;
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UIWebView *webView;
Here is the code in PRDetailViewController.m,
- (void)viewDidLoad {
[super viewDidLoad];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:self.pFeedURL];
[self.webView loadRequest:urlRequest];
I cannot seem to figure out why this is crashing. I know it has to do with this line ,
[segue.destinationViewController setPFeedURL:feed_Post.url];
(at leaset I think it is that line. I can't figure out why I cannot set it.
Thanks for your help guys!
Change This
PRDetailViewController *objPRDetailViewController = (PRDetailViewController *)[segue.destinationViewController topViewController];
objPRDetailViewController.pFeedURL=feed_Post.url;
And Also put bellow code in viewDidAppear
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:self.pFeedURL];
[self.webView loadRequest:urlRequest];
try this
[[((id)segue.destinationViewController) topViewController] setPFeedURL:feed_Post.url];
let me know if it works
I'm new to iOS development and am currently studying from video tutorials. I came across a problem with quite a simple app I'm experimenting on.
The problem is with loading pictures to UIImage in a split view control iPad app. The app is based on the XCode master-detail application template. I created an array with NSObject variables and two properties.
#interface Burger : NSObject
#property (nonatomic) NSString *name;
#property (nonatomic) NSString *filename;
#end
- (void)viewDidLoad {
[super viewDidLoad];
photos = [[NSMutableArray alloc]init];
Burger *pic = [[Burger alloc]init];
pic.name = #"Bacon";
pic.filename = #"burger-bacon";
[photos addObject:pic];
pic = [[Burger alloc]init];
pic.name = #"Cheese";
pic.filename = #"burger-cheddar";
[photos addObject:pic];
pic = [[Burger alloc]init];
pic.name = #"Hawaii";
pic.filename = #"burger-hawaii";
[photos addObject:pic];
pic = [[Burger alloc]init];
pic.name = #"Koko z jajkiej kurzym";
pic.filename = #"burger-jajo";
[photos addObject:pic];
pic = [[Burger alloc]init];
pic.name = #"Kozi ser";
pic.filename = #"burger-kozi";
[photos addObject:pic];
pic = [[Burger alloc]init];
pic.name = #"Łosoś";
pic.filename = #"burger-losos";
[photos addObject:pic];
pic = [[Burger alloc]init];
pic.name = #"Vege (Soczewica)";
pic.filename = #"burger-soczewica";
[photos addObject:pic];
}
I want the UImageView nested in DetailView to display a picture of the object chosen in the MasterView controller. I got it to display the pictures in the MasterView table
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Burger *current = [photos objectAtIndex:indexPath.row];
UIImage *image = [UIImage imageNamed:[current filename]];
[cell.imageView setImage:image];
self.title = self.currentPhoto.name;
cell.textLabel.text = [current name];
cell.detailTextLabel.text = [current price];
return cell;
}
and it also works when I point to a specific file name:
- (void)configureView {
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem notes];
UIImage *image = [UIImage imageNamed: #"burger-bacon"];
[self.currentImage setImage:image];
self.title = self.currentPhoto.name;
}
}
but when I try to show the picture of the chosen element like this:
- (void)configureView {
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem notes];
UIImage *image = [UIImage imageNamed: self.currentPhoto.filename];
[self.currentImage setImage:image];
self.title = self.currentPhoto.name;
}
}
I get these few lines in the debug area:
2015-06-23 12:13:25.964 SlowFoodiPad[22177:744765] CUICatalog: Invalid asset name supplied: (null)
which means the segues work and the photo files seem to be fine. There seem to be a problem with pointing to the right file to display. Any ideas how to fix it?
OK, I managed to solve the problem partially. I edited prepareForSegue method of MasterViewController:
DetailViewController *controller = (DetailViewController *)[[segue destinationViewController] topViewController];
Burger *c = photos [indexPath.row];
[controller setDetailItem:c];
//this line helped
[controller setCurrentPhoto:c];
The appropriate photos now show, although the debug area keeps showing me this message:
CUICatalog: Invalid asset name supplied: (null)
two identical lines each time I tap on an element in the MasterView table.
Right now it's unclear when "-(void)configureView" is being called. My guess, based on your issue, is that it's actually called before prepareForSegue. Or at least, the very first time, it's being called before you actually have an image. You are checking for "if (self.detailItem)" but you are not checking for if (self.currentPhoto).
So probably the first time configure view is called, there is no self.currentPhoto so it can't be set. Then when the segue is actually prepared (prepareForSegue:) you set the current photo, so then when configure view is called again, it's there.
If you paste more of your view controller code that shows what triggers the segue (probably it's just the storyboard but unclear from what you have above) and when configureView, then we'd know for sure if my guess is correct.
OK, there's some progress. Now I only get two lines of this message and only at initial start of the app:
CUICatalog: Invalid asset name supplied: (null)
I commented out few lines here. Can you see anything else that is causing problems?
- (void)setDetailItem:(id)newDetailItem {
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView {
// Update the user interface for the detail item.
// if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem notes];
// UIImage *image = [UIImage imageNamed:self.currentPhoto.filename];
// [self.currentImage setImage:image];
}
//}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIImage *image = [UIImage imageNamed:self.currentPhoto.filename];
[self.currentImage setImage:image];
self.title = self.currentPhoto.name;
self.detailDescriptionLabel.text = [self.detailItem notes];
// [self configureView];
}
Here's the prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
DetailViewController *controller = (DetailViewController *)[[segue destinationViewController] topViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Burger *c = photos [indexPath.row];
[controller setDetailItem:c];
//adding this line helped
[controller setCurrentPhoto:c];
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
controller.navigationItem.leftItemsSupplementBackButton = YES;
}
}
I have 2 VC, one where the users write the data, with textfield or pickerview, and the main screen where i show the data on a tableview. The problem is that when i click on done button, it might call the delegate, but on the first vc, where is implemented, it doesnt receive any call. What should i do? I have been for 2 days trying to find the bug, and nothings happens. Thanks for any Help.
2VC.h
#protocol AddCountryDelegate <NSObject>
#required
-(void)didCreateCountry:(CountryClass*)country;
#end
#interface AddCountryViewController : UIViewController
#property (assign, nonatomic) id<AddCountryDelegate> customDelegate;
2VC.m
- (IBAction)actionDone:(id)sender {
NSString* itemName = self.itemNameTextField.text;
NSString* countryName = self.countryNameTextField.text;
NSDate *countryDate = [datePickerView date];
NSString *daysLeftString = [NSString stringWithFormat:#"%# days", self.daysLeftTextField.text];
NSInteger daysLeftInt = [daysLeftString integerValue];
NSNumber *daysLeft = [NSNumber numberWithInteger:daysLeftInt];
NSString *paymentMethod = self.paymentMethodTextField.text;
CountryClass* newCountryItem =
[[CountryClass alloc] initWithCountryName:countryName countryLogo:#"" itemName:itemName countryDate:countryDate daysLeft:daysLeft andPaymentMethod:paymentMethod];
[self.customDelegate didCreateCountry:newCountryItem];
[self dismissViewControllerAnimated:YES completion:nil];
}
And finally the implementation on the 1st VC:
-(void)didCreateCountry:(CountryClass *)country{
//Add new country-itemCountry - UPDATING OUR MODEL DATA
NSMutableArray *mutableCountries = [self.countries mutableCopy];
[mutableCountries addObject:country];
self.countries = [mutableCountries copy];
//UPDATING THE VIEW
[self.tableView reloadData];
NSLog(#"Created");
[self saveCountriesToDisc];
}
-(void)saveCountriesToDisc{
NSMutableArray* convertedCountries = [NSMutableArray array];
//Converting the model to dictionary
for(CountryClass *country in self.countries)
{
NSDictionary *convertedCountry = [shop countriesToDictionary];
[convertedCountries addObject:convertedCountry];
}
//NOW convertedShows CONTAINS ONLY STRINGS, NUMBERS,
//ARRAYS AND DICTIONARY
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths.firstObject;
NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:#"countriesListData.plist"];
//NOW TELL THE ARRAY TO SAVE
[convertedCountries writeToFile:destinationPath atomically:YES];
NSLog(#"Saved");
[self.tableView reloadData];
}
I initialize my delegate on the prepareforsegue
-(void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender
{
if ([segue.identifier isEqualToString:#"AddSegue"]) {
AddCountryViewController* addCountryVC =
segue.destinationViewController;
addCountryVC.customDelegate = self;
}
where in VC1 did you set the customDelegate to self?
also you should set your delegate to weak not assign
I have created an "events table", which features the event name, the date and location. Upon clicking each event cell, I am trying to load a specific event URL into a web view. Completely lost.
I have integrated a "prepareForSegue" in the ViewController.m, and have successfully loaded a single url into each table cell that is defined within the code, but I cannot seem to load a string of URLs from Parse.com. The rest of the event table data is loaded fine from Parse.. i'm just struggling with the URL.
Can anybody help?
This is what I have for the individual url load:
-(void)loadRequestFromString:(NSString*)urlString
{
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[self.eventWebView loadRequest:urlRequest];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = event.name;
[self loadRequestFromString:#"http://www.airleague.co.uk"];
}
- (void)viewDidUnload
{
[self setEventWebView:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
My segue is:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showEventDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
EventDetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
Event *event = [[Event alloc] init];
event.name = [object objectForKey:#"name"];
event.eventURL = [object objectForKey:#"eventURL"];
destViewController.event = event;
}
}
#end
for:
[self loadRequestFromString:NSString];
to work, the url should have #"http://" (or any protocol) in the url.
For example it must be "http://google.com" and NOT "google.com"
Does you urls in Parse.com have the protocol in the string?
First you have to retrieve your objects, which are stored as a string:
So in your viewDidLoad you perform the following query like this:
PFQuery *urlQuery = [PFQuery queryWithClassName:#"WebViewURLs"];
urlQuery.cachedPolicy = whateverPolicyYouWant;
[urlQuery selectKeys:#[#"NameOfURLColumn"]];
[urlQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.urlArray = objects;
NSLog(#"%#", self.urlArray);
//you'll notice the NSLog logs all attributes to that array, so if you want to narrow it down to a specific column you can do something like this:
self.urlArray = [objects valueForKey:#"NameOfColumn"];
}
}];
So now you have the objects in an array and you can act accordingly. Your going to have to be more specific with your set up if you want a more specific answer. I'm just guessing at this point since i'm not a mind reader...yet :)
EDIT after taking a gander from the project you sent to me via email...
A quick synopsis for other users looking for an answer similar:
Ensure your IBOutlet connections are singular and attached to their respective owners.
Additionally the OP wasn't segueing properly, they were allocating a new subclass every time the cell was selected, but wasn't passing any information to the webView View Controller.
It's also worth to point out the OP had subclassed the tableView to Parses PFQueryTableViewController
Make sure you properly call your destination view controller and pass information to a properly set property in the Detail VCs header :
if ([segue.identifier isEqualToString:#"showDetailVC"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailViewController *destViewController = segue.destinationViewController;
PFObject *object = [self.objects objectAtIndex:indexPath.row];
destViewController.eventURL = [object objectForKey:#"ingredients"];
destViewController.eventName = [object objectForKey:#"name"];
}
Detail VC Header
#property (nonatomic, strong) IBOutlet UIWebView *webView;
#property (nonatomic, strong) NSString *eventURL;
#property (nonatomic, strong) NSString *eventName;
Detail VC implementation :
//Load the webView in viewDidLoad:
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.eventURL]]];
I am having a hard time figuring out how to pass a NSString to a NSObject class.
I have a .h and .m file which is a NSObject and I need to pass a string from a UIViewController.
This is what I tried when pushing the view:
NSString *urlString = #"TextHere";
WXClient *svc = [[WXClient alloc]init];
svc.urlOne = urlString
And then, I am retrieving it this way:
#interface WXClient : NSObject {
NSString *urlOne;
}
#property (strong, nonatomic) NSString *urlOne;
and of course, then on the .m :
#synthesize urlOne;
Then to use the NSString:
NSString *urlString = [NSString stringWithFormat:urlOne];
NSURL *url = [NSURL URLWithString:urlString];
//blah blah blah blah... :D
}];
But for some reason it is returning null. I am able to use this method from viewController to viewController but to NSObject is not working :(
Any ideas?
Thanks!
Try this
WXClient *svc = [[WXClient alloc]init];
NSString *urlString = #"TextHere";
svc.urlOne = urlString;
Sorry didn't read question properly
If you are pushing/presenting view controller throug segue and you want to send some data to destination view contrller. Like you want to set some property, you need to implement this method. prepareForSegue:sender:.
In it you you can get destination viewController and set whatever property you want to.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"weatherWXID"]) {
WeatherViewController *vc = [segue destinationViewController];
NSString *urlString = #"TextHere";
WXClient *svc = [WXCLient new];
svc.urlOne = urlString
vc.wxclient = svc;
}
}