xcode fails to recognise #property but it is correct - ios

Xcode failing to recognize #property in detail controller.
.m file of ViewController2:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *selectedIndexPath = [[self.collectionView indexPathsForSelectedItems] objectAtIndex:0];
// load the image.
NSString *imageNameToLoad = [NSString stringWithFormat:#"%d", selectedIndexPath.row];
NSString *pathToImage = [[NSBundle mainBundle] pathForResource:imageNameToLoad ofType:#"JPG"];
UIImage *image2 = [[UIImage alloc] initWithContentsOfFile:pathToImage];
Detail_ViewController_Biffy *detailViewController = [segue destinationViewController];
Detail_ViewController_Biffy.**image = image;** <--- fails [property 'image'not found on object of type 'detail_ViewController_Biffy'
}
}
.h file of detail_view
#import "ViewController.h"
#interface ViewController_Biffy : ViewController
#property (strong, nonatomic) IBOutlet UIImageView *image;
#end
Tried to change the import ViewController.h to ViewController_Biffy.h but causes more errors.
If you need further info, let me know.

You are trying to get a property from a class rather than the instance. Try
Detail_ViewController_Biffy *detailViewController = [segue destinationViewController];
detailViewController.image = image
Also the type you have says detail_ViewController2 which is not anywhere in your code

First: image is a property not a class method so you would need to access it:
detailViewController.image =
Secondly image in your prepareForSegue:sender: does not exist. I am guessing you are trying to set your property to image2 which you create a couple lines up. In that case the failing line of code would look like:
detailViewController.image = image2;
All properties are accessed through instances of classes. Although you may not know it, you are already creating a detailViewController instance on your line:
Detail_ViewController_Biffy *detailViewController = [segue destinationViewController];

Related

prepareForSegue EXC_BAD_ACCESS at indexPath.row

I am trying to pass a data through a segue under prepareForSegue function but i keep getting exc_bad_access.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
//NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:0];
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"itemListSegue"])
{
itemList *vc = [segue destinationViewController];
vc.inv = [inv_list objectAtIndex:indexPath.row];
vc.title = vc.inv;
}
}
bellow is the error i got
EDIT:
inv_list is declared as followed:
#interface downloadInv (){
NSMutableArray *inv_list;
}
and in viewDidLoad:
inv_list = [[NSMutableArray alloc] init];
Content:
vc.inv is a particular element in inv_list that I want to pass to the destination view controller when a table is selected.
it was declared as followed:
#interface itemList : UITableViewController
#property(nonatomic, strong) NSString *inv;
#end
Anyone know how to fix this?
Thanks in advance.
Because in_list is not declared as a strong property, it is probably being released.
Try declaring it like this:
#property (strong, nonatomic) NSMutableArray * inv_list;
Could you please check your segue identifier, If that's not given, may cause the exception
otherwise if it's made as strong property like:
#property(nonatomic,strong) NSString *inv_list;
It may solve the problem.

Displaying an URL from a different view controller in a UIWebView

RecipesTableViewController.m
#import "RecipesTableViewController.h"
#import "RecipeTableViewCell.h"
#import "IngredientsViewController.h"
#import "Recipe.h"
#import "RecipeDetailViewController.h"
#interface RecipesTableViewController () {
NSMutableArray *recipesArray;
}
#end
#implementation RecipesTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
//api from recipepuppy
NSString *recipeUrlString = [NSString stringWithFormat:#"http://www.recipepuppy.com/api/?i=%#",self.searchRecipe];
//adding percentage on the textfield when the user is searching
NSString *formattedString = [recipeUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//download data
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString: formattedString]];
//put data into a dictionary
NSDictionary *recipeDictinary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
//then put the dictionary into an array
recipesArray = [[NSMutableArray alloc]init];
for (NSDictionary *recipeDict in [recipeDictinary objectForKey:#"results"]) {
Recipe *recipe = [[Recipe alloc]initWithTitle:[recipeDict objectForKey:#"title"] andRecipeIngredients:[recipeDict objectForKey:#"ingredients"] andImageURL:[NSURL URLWithString:[recipeDict objectForKey:#"thumbnail"]] andRecipeWebUrl:[recipeDict objectForKey:#"href"]];
[recipesArray addObject:recipe];
NSLog(#"%#", recipeDict);
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [recipesArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RecipeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"recipeCell" forIndexPath:indexPath];
[cell drawTheCell:[recipesArray objectAtIndex:indexPath.row]];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"recipeDetail"]) {
//NSIndexPath *indexPath =[self.tableView indexPathForSelectedRow];
RecipeDetailViewController *recipeDetail = segue.destinationViewController;
recipeDetail.title = #"Recipe";
}
}
#end
Short Story:
I’m making a recipe by ingredient for my class.
I have a UITableViewControllre parsing content from an api and and I have the objects of the api in an array. In that array I have “results” and in those results I have urls, title, ingredients, and image of recipe. I want to send the url to a WebView into another view controller but I just can’t. Whenever I select the recipe the app crashes to view the webview. I been stuck on this for threes days and I’m so frustrated and I know the problem is my linking to the webview because the array prints the url but is not displayed on the webview.
this is my table view controller where my api is and the prepare for segue to the view controller where the webview is at.
RecipeTableViewCell.m
#import <UIKit/UIKit.h>
#import "Recipe.h"
#interface RecipeTableViewCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UILabel *recipeUrl;
#property (strong, nonatomic) IBOutlet UILabel *recipeTitle;
#property (strong, nonatomic) IBOutlet UILabel *recipeIngredients;
#property (strong, nonatomic) IBOutlet UIImageView *recipeImage;
-(void)drawTheCell:(Recipe *)recipeObject;
#end
RecipeTableViewCell.m
-(void)drawTheCell:(Recipe *)recipeObject {
self.recipeTitle.text = recipeObject.title;
self.recipeIngredients.text = recipeObject.ingredients;
self.recipeUrl.text = recipeObject.recipeWebUrl;
NSData *imageData = [NSData dataWithContentsOfURL:recipeObject.imageURL];
self.recipeImage.image = [UIImage imageWithData:imageData];
#import "RecipeDetailViewController.h"
#import "RecipeTableViewCell.h"
#interface RecipeDetailViewController ()
#property (strong, nonatomic) IBOutlet UIWebView *recipeWebView;
#end
RecipeDetailViewController.m
#implementation RecipeDetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
Recipe *recipe = [[Recipe alloc] init];
NSURL *url = [NSURL URLWithString: recipe.recipeWebUrl];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.recipeWebView loadRequest:request];
}
RecipeDetailViewController.h
#import <UIKit/UIKit.h>
#interface RecipeDetailViewController : UIViewController
#property (nonatomic, strong ) NSString *recipeWebUrlString;
this is my cell and in here the title, ingredients, and image is displayed and it works fine.
Skyler's answer's heading in the right direction, but it's missing a few critical pieces...
Yes, you need to pass the web url string in prepareForSegue: like he's suggesting, i.e.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"recipeDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeTableViewCell *cell = (RecipeTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];
RecipeDetailViewController *recipeDetail = segue.destinationViewController;
recipeDetail.title = #"Recipe";
recipeDetail.recipeWebUrlString = cell.recipeUrl.text;
}
}
but the problem is that you're not using that recipeWebUrlString to perform your url request.
Instead, you're creating an empty Recipe object in your .m and thus using an empty url to perform the web request, i.e.
Recipe *recipe = [[Recipe alloc] init];
NSURL *url = [NSURL URLWithString: recipe.recipeWebUrl];
Instead replace those two lines (^) with the following:
NSURL *url = [NSURL URLWithString:self.recipeWebUrlString];
in order to use the url you just passed in from the RecipesTableViewController.
There is a long winded answer here but I will try to keep it short and hopefully it makes sense.
First I don't see where you are calling performSegueWithIdentifier: which means you are likely doing a segue from clicking the cell directly to the next view via storyboard. This is great for a simple button press but not ideal for selecting a cell that you need to send information from. I would recommend calling the segue in didSelectRowAtIndexPath:. The segue on the storyboard should go directly from one view controller to another and not directly from a table cell. Don't forget to set the identifier again.
Something like this to call the segue in code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"recipeDetail" sender:nil]; //you could also pass the cell with if you want
}
Second in your prepare for segue you are not setting the URL you want and just setting the title of the next view controller. Looks like you were close to what you wanted because I can see you were already looking at the index path but commented it out. You should grab the cell there and set the url to the recipeDetail. You could also pass the cell via sender.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"recipeDetail"])
{
NSIndexPath *indexPath =[self.tableView indexPathForSelectedRow];
RecipeTableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
RecipeDetailViewController *recipeDetail = segue.destinationViewController;
recipeDetail.title = #"Recipe";
recipeDetail.recipeWebUrlString = cell. recipeUrl.text;
}
}
Third thing if all else fails start putting NSLogs everywhere. You can log the URL in the view did load in the next view and see that it isn't getting set. The next thing you should have been looking at where you are setting it, which appears to be no where as far as I can see =)
Also with all of that being said I would not relay on the text on the cell but instead grab the recipe from your array and pass that in the segue.
I hope that helps or at least gets you pointed in the right direction.

Passing String through Segue

I'm trying to pass a NSMutableString through a segue.
The mutableString is a title from an MKPolygon.
I've done the mutableString like this: self.titleString = [[NSMutableString alloc] initWithString:polygon.title];
I'm not sure how to segue the String:
I've got this now:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"PickerViewController"])
{
NSLog(#"delegated");
//Get the new view controller using [segue destinationViewController].
PickerViewController *vc =[segue destinationViewController];
vc.titleString = titleString;
}
}
I get an error with vc.titleString = titleString;. Not sure how to set the String in the PickerViewController segue.
Error: Property 'titleString' not found on object of type 'PickerViewController *'
The PerformSegueWithIdentifier is this Method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
//this would be the yes button or cancel
if (buttonIndex == 0 ){
NSLog(#"ButtonIndex Okay");
}
if (buttonIndex == 1) {
[self performSegueWithIdentifier:#"PickerViewController" sender:self];
}
}
I do know how to segue an object, but with Strings I don't get my mind to it.
Help would be really appreciated!
Update 1:
I've imported the PickerViewController.h in the ViewController.h file.
I've changed the vc.titleString = titleString; with vc.titleString = self.titleString;
I've added a #property (strong,nonatomic) NSMutableString *titleString; to the PickerViewController.h
No luck.
Update 2:
Tried an other way to segue the String: [(PickerViewController *)[segue destinationViewController] setTitleString:self.titleString];
Got the error: No visible #interface for 'PickerViewController' declares the selector 'setTitleString:'
ViewController.h file:
#property (strong, nonatomic) NSMutableString *titleString;
ViewController.m file:
#synthesize titleString;
self.titleString = [[NSMutableString alloc]init];
PickerViewController.h file:
#property (strong, nonatomic) NSMutableString *titleString;
PickerViewController.m file:
#synthesize titleString;
self.titleString = [[NSMutableString alloc]init];
Still seems like it doesn't recognises the titleString.
Update 3:
Still no luck with segueing the string.
Maybe it has something to with this:
The NSMutableString is being used in a loop. The loop checks if there is an GPS, annotation or a touch is inside a MKPolygon. Each polygon has it's own color, which is named in the polygon.title: See code below*. So the String saves the 'selected' polygon title. See the loop below:
One of the Polygons:
CLLocationCoordinate2D roodPoly[2];
roodPoly[0] = CLLocationCoordinate2DMake(52.372445351278294, 4.876454472541809);
roodPoly[1] = CLLocationCoordinate2DMake(52.37288748990477, 4.878369569778442);
MKPolygon *roodpoly = [MKPolygon polygonWithCoordinates:roodPoly count:2];
roodpoly.title = #"red";
[myMapView addOverlay:roodpoly];
A little bit of the loop:
if(CGPathContainsPoint(mpr , NULL, mapPointAsCGP, FALSE)){
NSLog(#"Coordinate %f,%f is in polygon %#", tapCoord.latitude, tapCoord.longitude, polygon.title);
self.titleString = [[NSMutableString alloc] initWithString:polygon.title];
self.subtitleString = [[NSMutableString alloc] initWithString:polygon.subtitle];
alertView = [[UIAlertView alloc]initWithTitle:#"Found it" message:subtitleString delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Stel notificatie in", nil];
[alertView show];
NSLog(#"The color of the Polygram is: %#", titleString);
}
CGPathRelease(mpr);
}
}
}
I thought this could cause the problem for not finding the String :(
On your "PickerViewController.h" should look like:
#import <UIKit/UIKit.h>
#interface PickerViewController : UIViewController
#property (strong,nonatomic) NSMutableString * titleString;
#end
And on your "ViewController.m" file:
#import "ViewController.h"
#import "PickerViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[(PickerViewController *) [segue destinationViewController] setTitleString:self.titleString];
}
#end
It is Working fine here..
Hope it helps :)

error on Key Value coding when using prepareForSegue

I am using the following to create a reference to a view controller in my code like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"detailSegue"]){
NSIndexPath *indexPath=[self.tableView indexPathForSelectedRow];
TRDetailViewController *vc=segue.destinationViewController;
vc.item=self.items[indexPath.row];
[vc setValue:self forKeyPath:#"delegate"];
[vc setValue:indexPath.row forKeyPath:#"itemIndex"];
}
}
and this is declared as in TRDetailViewController
#interface TRDetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *detailLabel;
#property NSString *item;
#property (nonatomic, weak)id delegate;
#property NSInteger itemIndex;
- (IBAction)deleteItem:(id)sender;
#end
but I get the following error
and I'm not sure why. I am trying to pass the location in an index of the cell selected in a UITableView. If a better way, please let me know. Why am I getting this error?
thx
setValue:forKey: is expecting an object for its value argument and you are passing it a primitive (in this case, an integer). You can work around this by amending your method to read as follows:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"detailSegue"]){
NSIndexPath *indexPath=[self.tableView indexPathForSelectedRow];
TRDetailViewController *vc=segue.destinationViewController;
vc.item=self.items[indexPath.row];
[vc setValue:self forKeyPath:#"delegate"];
[vc setValue:[NSNumber numberWithInt:indexPath.row] forKeyPath:#"itemIndex"];
}
}
And then access it like:
[[vc valueForKey:#"itemIndex"] intValue];
setValue:forKeyPath: requires an object (i.e. id) as first argument.
You are instead passing a NSInteger.
You will have to use an object type, which means to turn your itemIndex into a NSNumber.
Then you can store it using
[vc setValue:#(indexPath.row) forKeyPath:#"itemIndex"];
and retrieve it by
NSInteger myIndex = [vc valueForKey:#"itemIndex"].integerValue;

What type of properties of destination controller are accessibile from prepareSegue?

When I am trying to set a property from destination controller within prepareSegue method, it is possible for some types of properties, while some others are not. For example, let's say my destination controller contains the following properties:
#interface MapController:UIViewController
#property (weak, nonatomic) IBOutlet UIWebView *streetView;
#property (strong, nonatomic) NSString *url;
#property (nonatomic) NSString *latitude;
#property (nonatomic) NSString *longitude;
#property (nonatomic) Venue *venue;
#end
By the way, "Venue" looks like this:
#interface Venue:NSObject
#property (nonatomic) NSString *latitude;
#property (nonatomic) NSString *longitude;
#end
The following code works:
/****** CODE 1 *******/
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"MapViewSegue"]){
MapController *cvc =
(MapController *)[segue destinationViewController];
NSIndexPath *selectedIndex = self.tableView.indexPathForSelectedRow;
Venue *v = (Venue *)[self.entries objectAtIndex:[selectedIndex row]];
/****** Note the difference from CODE 2 below! ******/
cvc.latitude = v.latitude;
cvc.longitude = v.longitude;
// At this point,
// both cvc.latitude and cvc.longitude are properly set.
}
}
But this one doesn't work:
/****** CODE 2 *******/
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"MapViewSegue"]){
MapController *cvc =
(MapController *)[segue destinationViewController];
NSIndexPath *selectedIndex = self.tableView.indexPathForSelectedRow;
Venue *v = (Venue *)[self.entries objectAtIndex:[selectedIndex row]];
/****** Note the difference from CODE 1 above! ******/
cvc.venue.latitude = v.latitude;
cvc.venue.longitude = v.longitude;
// At this point,
// both cvc.venue.latitude and cvc.venue.longitude are nil
}
}
As I noted in the code, it seems that an NSString property can be set within prepareSegue, but if I try to instantiate my own object it ends up with nil. I was wondering why this is happening. Thank you in advance!
The second code doesn't work because cvc.venue doesn't point to anything -- you haven't instantiated a venue object in your MapController class. There's nothing special about your custom object, it's no different than if you had: #property (nonatomic) NSArray *array; -- array will be nil until you instantiate a new array object.

Resources