I have a problem accessing a object in my array. I store "Place" objects in my NSMutableArray. I want to access this array for my TableView. I get the "No known instance method for selector" error in line one. See lines below.
cell.imageView = [[self.currentPlaces objectAtIndex:indexPath.row]picture];
cell.subtitleLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]description];
cell.objectNameLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]name];
This is my Place object:
#interface Place : NSObject{
CLLocation *objectLocation;
UIImageView *picture;
NSString *name;
NSString *description;
}
The access of the properties "description" and "name" is no problem. I just dont know why this error occurs.
Thx. Dominik
I had the same problem; what worked for me was passing the UIImage instead of the UIImageView. So your code should look like this:
#interface Place : NSObject{
CLLocation *objectLocation;
UIImage *picture;
NSString *name;
NSString *description;
}
and this
cell.imageView.image = [[self.currentPlaces objectAtIndex:indexPath.row]picture];
cell.subtitleLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]description];
cell.objectNameLB.text = [[self.currentPlaces objectAtIndex:indexPath.row]name];
If that doesn't work I'll post some more code for you to look at.
You haven't actually declared any methods. What you have declared are instance variables. You should probably be using #propertys instead.
#interface Place : NSObject
#property (nonatomic, retain) CLLocation *objectLocation;
#property (nonatomic, retain) UIImageView *picture;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy, getter=objectDescription) NSString *description;
#end
This will actually create the methods that you want. Note that I changed the method for the description property to read -objectDescription. This is because NSObject already declares the -description method and you shouldn't be overriding it with an unrelated property.
If you're on recent Clang, then this is all you need, and instance variables will get synthesized automatically (using an underbar prefix, e.g. _picture). If you're on an older version (e.g. if this causes errors), you need to add #synthesize lines, as in
#implementation Place
#synthesize objectLocation=_objectLocation;
#synthesize picture=_picture;
#synthesize name=_name;
#synthesize description=_description;
#end
Related
I am trying to get image in return from the instance method, i am declaring the method in following way, but giving error. I am using NSObject class.
-(UIImage *)getAdImg;
This is giving error that "Expected a type". What does it mean. I normal view controller it is working fine, but in NSObject class it is giving this error. Please guide for the above.
Thanks in advance.
This is my .h file
#import <Foundation/Foundation.h>
#import "JSON.h"
#interface adClass : NSObject
{
NSString *mStrPid;
NSString *mStrAppUrl;
}
#property (nonatomic, strong) NSString *mStrPid;
#property (nonatomic, strong) NSString *mStrAppUrl;
#property (nonatomic, strong) NSMutableArray *mArrAdsDesc;
#property (nonatomic, strong) NSMutableArray *mArrDeviceType;
#property (nonatomic, strong) NSString *mDevice;
#property (nonatomic, strong) NSString *mImgStr;
-(void)iphoneDevice;
-(UIImage *)getAdImg; //(error line)
#end
You have to #import <UIKit/UIKit.h> (where UIImage is declared)
Use this code
-(UIImage *)getAdImg
{
UIImage *image=[[UIImage alloc]init];
image.images=/**An Array of images**/
return ima;
}
Hope it helps!!!
I'm working on a project for iOS5 using ARC and storyboard.
I have a mapview with annotations with a disclosure button going to my DetailView (which is a TableViewController) but when it's supposed to be loaded, I get the following error:
2012-07-18 14:09:43.328 Zone-It-new[1966:707] Loadded the view for MapViewController
2012-07-18 14:11:40.467 Zone-It-new[1966:707] -[UILabel copyWithZone:]: unrecognized selector sent to instance 0x138470
2012-07-18 14:11:40.470 Zone-It-new[1966:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILabel copyWithZone:]: unrecognized selector sent to instance 0x138470'
*** First throw call stack:
(0x3748488f 0x35189259 0x37487a9b 0x37486915 0x373e1650 0x311997ef 0x31195059 0x31194711 0x3119466b 0x311945e7 0x31284f63 0x311979bb 0x311973ad 0x31191b8b 0x311917d5 0x9386d 0x3120a93d 0x31284627 0x37cf5933 0x37458a33 0x37458699 0x3745726f 0x373da4a5 0x373da36d 0x33b99439 0x31186cd5 0x924b3 0x92458)
terminate called throwing an exception(lldb)
This is my detailviewcontroller.h:
#import <UIKit/UIKit.h>
#import "Event.h"
#interface DetailViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>{
IBOutlet UILabel *title;
IBOutlet UILabel *description;
IBOutlet UILabel *zone;
IBOutlet UILabel *gemeente;
IBOutlet UILabel *plaats;
IBOutlet UILabel *deelnemers;
IBOutlet UILabel *start;
IBOutlet UILabel *einde;
IBOutlet UILabel *id_nr;
}
#property (nonatomic) Event *event;
#property (nonatomic) IBOutlet UILabel *title, *zone, *description, *gemeente, *deelnemers, *start, *einde, *plaats, *id_nr;
#end
part of the DetailViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[[self navigationController] setNavigationBarHidden:NO animated:YES];
/*title.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;*/
[title lineBreakMode];
[title setText:[event title]];
[title sizeToFit];
gemeente.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
[title lineBreakMode];
[gemeente setText:[event gemeente]];
}
And this is where the view gets created in via the ListView:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"detail"];
SingletonManager *sharedManager = [SingletonManager sharedManager];
[detail setEvent:[sharedManager.eventsManager objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:detail animated:YES];
}
Event.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface Event : NSObject <MKAnnotation>
// required property from mkanotation
#property (nonatomic) CLLocationCoordinate2D coordinate;
// Optional
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *description;
#property (nonatomic, copy) NSString *zone;
#property (nonatomic, assign) NSString *gemeente;
#property (nonatomic, copy) NSString *straat;
#property (nonatomic, assign) int deelnemers;
#property (nonatomic, copy) NSDate *start;
#property (nonatomic, copy) NSDate *einde;
#property (nonatomic, copy) NSString *plaats;
#property (nonatomic, readonly) int id_nr;
#property (nonatomic, assign) int huisnummer;
#end
----- Some more debugging information -------
While using the exception breakpoints it stopped here:
[self.navigationController pushViewController:detail animated:YES];
console:
2012-07-18 15:53:46.691 Zone-It-new[179:707] Loadded the view for MapViewController
2012-07-18 15:54:01.940 Zone-It-new[179:707] -[UILabel copyWithZone:]: unrecognized selector sent to instance 0x170bb0
(lldb)
It appears that somewhere in your code you're trying to copy a UILabel. UIView subclasses don't adhere to the NSCopying protocol, so trying to copy any UIView will result in an exception (unless it's a subclass that does implements the protocol). I'd search through your code base to check where the copy is occurring. If you can't find any place that explicitly copies the UILabel, check collection classes. Some collections classes will copy values in (NSDictionary does this with keys, so if you're trying to use a UILabel as a key for a NSDictionary, you'll get the error). Also check your properties. What you show in your displayed code is fine, but if you specify a copy in a protocol for a UILabel, that'll also give the error.
You should also try standard debugging techniques like setting a breakpoint for all exceptions. (go to the breakpoints nav pane, at the bottom click the plus sign). This should help you find the problem by breaking on your offending line of code. Just be aware that if the copying is occurring in Apple's code (like setting a NSDictionary key) the breakpoint might not break on your code.
Update
Given your new code, I would suggest trying the following:
Try to find any place in your code where "anything" is copied. Obviously your not explicitly copying UILabel but maybe you're accidentally copying it by passing the wrong argument somewhere. For example: Remove all copy keywords from your Event properties and test it again. You probably don't need to specify copy for NSString anyway, but what we're doing here is making sure you're not accidentally setting a UILabel to one of those properties. If the code doesn't break, you didn't fix it but now you know what the problem is (trying to assign a UILabel to the wrong property).
Start commenting out various blocks of code, one at a time, to find the problem. For example, comment out your entire viewDidLoad method and test your code. If it works, you know the problem is in there. So uncomment part of the method and test again. Keep repeating until you've narrowed down the problem. If it still breaks with viewDidLoad, uncomment that and try a different block of code. In essence, you're playing detective to try to find the offending line of code.
The fix for this is to rename the title property in the UIViewController. This is due to the fact that UIViewController already defines an NSString * property with a name of title.
This can often mean you're trying to assign an object to a method that can't handle it, rather than a property of that object. For example, trying to set a UILabel to an object rather than a string property on that object.
My guess is it's this line: [gemeente setText:[event gemeente]];
There could also be an issue here:
#property (nonatomic) Event *event;
You haven't set Event *event as an instance variable but are referencing it as one. Try self.event for accessing event as you have it above.
I'm having a problem with NSString. I feel like it's a pretty simple thing to figure out but I've been staring at it for a while and just can't seem to get anywhere :/ Your help is highly appreciated!
I defined a class called Painting.
Here is Painting.h:
#interface Painting : NSObject {
NSString *artist;
UIImage *image;
}
#property (nonatomic, copy) NSString *artist;
#property (nonatomic, copy) UIImage *image;
#end
Here is Painting.m:
#implementation Painting
#synthesize artist, image;
#end
In a .h file for a view controller, I create a "painting":
Painting *monet;
#property (nonatomic, retain) Painting *monet;
Now, in it's .m file, I'm trying to do a very very simple print and it won't work. I get (null) instead of "Monet".
monet.artist = #"Monet";
NSString *bob3 = monet.artist;
NSLog(#"Real artist: %#", bob3);
However, this does work (gives me "Monet" instead of (null)):
NSString *bob3 = #"Monet";
NSLog(#"Real artist: %#", bob3);
What am I missing??
You probably need before:
monet.artist = #"Monet";
this:
monet = [[Painting alloc] init];
I am getting NSCFString Errors passing the results of a text string converted into an array to a method that expects strings.
I have a feeling that the problem is that there is something wrong with the array conversion but i am not clever enough to work this out !!!
here's the .h file
#interface RootViewController : UIViewController <ZXingDelegate> {
IBOutlet UITextView *resultsView;
NSString *resultsToDisplay;
IBOutlet UITextField *ItemNo;
NSString *ItemNoToDisplay;
IBOutlet UITextField *VariantCode;
NSString *VariantCodeToDisplay;
IBOutlet UITextField *Description;
NSString *DescriptionToDisplay;
IBOutlet UITextField *Qty;
NSString *QtyToDisplay;
}
#property (nonatomic, retain) IBOutlet UITextView *resultsView;
#property (nonatomic, copy) NSString *resultsToDisplay;
#property (nonatomic, retain) IBOutlet UITextField *ItemNo;
#property (nonatomic,copy) NSString *ItemNoToDisplay;
#property (nonatomic, retain) IBOutlet UITextField *VariantCode;
#property (nonatomic,copy) NSString *VariantCodeToDisplay;
#property (nonatomic, retain) IBOutlet UITextField *Description;
#property (nonatomic,copy) NSString *DescriptionToDisplay;
#property (nonatomic, retain) IBOutlet UITextField *Qty;
#property (nonatomic,copy) NSString *QtyToDisplay;
in the .m file i am doing this, the code is based on the Zxing Barcode scanning scan test application.
The barcode i am scanning has a string separated by ;
- (void)zxingController:(ZXingWidgetController*)controller didScanResult:(NSString *)result {
self.resultsToDisplay = result;
if (self.isViewLoaded)
{
//This is where the result comes back from the scanner.
//Need to use this to add items to a basket etc
//This is where we can create a new basket screen...
//NSString *myString = #"This is a test";
NSArray *myArray = [result componentsSeparatedByString:#";"];
ItemNoToDisplay = [myArray objectAtIndex:0];
[ItemNo setText:ItemNoToDisplay];
[ItemNo setNeedsDisplay];
VariantCodeToDisplay = [myArray objectAtIndex:1];
[VariantCode setText:VariantCodeToDisplay];
[VariantCode setNeedsDisplay];
DescriptionToDisplay = [myArray objectAtIndex:2];
[Description setText:DescriptionToDisplay];
[Description setNeedsDisplay];
[resultsView setText:resultsToDisplay];
[resultsView setNeedsDisplay];
}
[self dismissModalViewControllerAnimated:NO];
}
I then have a button on the screen that the user uses to pass the data to a simple method.
-(int)AddItemToBasket:(NSString *)ItemNo:(int)QtyToAdd:(NSString *)ItemDescription:(double)SalesPrice:(NSString *)DisplayPrice;
the app runs, the user scans the code, the window gets filled in correctly, there are some fields to hold the split data.
when the use presses the button to call the method.
if i use what i expect to work
Utility *sharedUtility = [Utility sharedUtility];
[sharedUtility AddItemToBasket:(ItemNoToDisplay):(1):(DescriptionToDisplay):(0):(#"1")];
but this does
Utility *sharedUtility = [Utility sharedUtility];
[sharedUtility AddItemToBasket:(ItemNoToDisplay):(1):(Description.text):(0):(#"1")];
The first call always errors with bad access or not a NSCFstring type error.
It seems that the LAST part of the array has some funny char in it that the textfield handles, but the code does not. Some sort of termination issue.
I have worked around it by using the variable from the text box, but am confused as to why i can pass directly the value in the textfield i am passing to the text box ?
Help / Confused..
You are directly assigning to your string ivars instead of going through the synthesized accessors (e.g. should be self.DescriptionToDisplay = ....
This means you are assigning an autoreleased object to the ivar, which may not be around by the time you call your AddItemToBasket method.
As an aside, it is conventional to begin method names and ivar names with lower case letters, and also to name arguments in your methods, that AddItemToBasket method is very difficult to read.
In answer to your comments, it may sometimes work if the area of memory has not been re-allocated since the autorelease. But you definitely need to use the accessors, particularly the setter - this will copy and increase the retain count for you. You could directly use the ivar for the getter in this situation.
You go through all the effort of defining properties but then never use them. This means that you're not retaining the values, and the OS is deallocating them before you actually use them.
So here:
DescriptionToDisplay = [myArray objectAtIndex:2];
You need:
self.DescriptionToDisplay = [myArray objectAtIndex:2];
We declare properties using the #property keyword and synthesize it in the implementation file. My question is,
What if I declare a property using the #property keyword and also declare a variable in the interface block with the same name? For example, consider the following code,
Interface:
#interface myClass : NSObject {
NSString *myClass_name; // LINE 1
}
#property(nonatomic, retain) NSString *myClass_name; // LINE 2
#end
Implementation:
#implementation myClass
#synthesize myClass_name // LINE 3
#end
Declaring myClass_name in LINE 1 will make any problem? Like any reference problem or any unnecessary memory consumption problem?
No, in fact, declaring properties like that expects it. You could replace your declaration to:
#interface MyClass : NSObject {
NSString *ivar;
}
#property (nonatomic, retain) NSString *myClass_name;
#end
And then change your implementation to
#implementation MyClass
#synthesize myClass_name = ivar;
#end
(If you don't specify the = some_ivar, it will assume the ivar has the same name as the property.)
You always need to have the following lines:
Declaration of the property (Line 2)
Synthesization of the property (Line 3)
When you synthesize the property, if you do not specify which ivar to use (by using =ivar at the end), it will assume that there is an ivar with the same name as the property.
Declaring properties and synthesizing it will not create any reference problem in your case.
Doing this will create accessor and setter methods for your instance variable in your class.
If the variable names in the property and the one declared in the class, then the xcode will refer both as a single variable.
Line 3 and Line 4 are must. Line 1 is optiona
I got the following content from Apple's doc for Declared Properties. I am posting it here, so that it may be helpful for someone in future.
Runtime Difference
In general the behavior of properties is identical on all runtimes (see Runtime Versions and Platforms in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.
For #synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the #synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you. For example, given the following class declaration and implementation:
#interface MyClass : NSObject {
float sameName;
float otherName;
}
#property float sameName;
#property float differentName;
#property float noDeclaredIvar;
#end
#implementation MyClass
#synthesize sameName;
#synthesize differentName=otherName;
#synthesize noDeclaredIvar;
#end
the compiler for the legacy runtime would generate an error at #synthesize noDeclaredIvar; whereas the compiler for the modern runtime would add an instance variable to represent noDeclaredIvar.
The following is the Object-oriented way:
DeclaringProperties.h
#interface DeclaringProperties : NSObject
// ivars and {} can be omitted
#property (nonatomic, readwrite, retain) NSString *normal;
#property (nonatomic, readwrite, retain) NSString *alias;
#property (nonatomic, readonly, retain) NSString *readonly;
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias;
#end
DeclaringProperties.m
#import "DeclaringProperties.h"
// private interface
#interface DeclaringProperties ()
#property (nonatomic, readwrite, retain) NSString *readonly; // readwrite for self
#property (nonatomic, readwrite, retain) NSString *private;
#property (nonatomic, readwrite, retain) NSString *retain;
#end
#pragma mark -
#implementation DeclaringProperties
#synthesize normal, alias = _alias, readonly, private, retain;
// You can not use "normal" here;
// But you can still use "alias", and it is highlighted in XCode!
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias {
self = [super init];
if (self) {
self.normal = aNormal;
self.alias = alias;
self.readonly = #"readonly";
self.private = #"private";
// allocated(copied) variable for retained(copied) property should be released or autoreleased
NSString *alloc = [[NSString alloc] init];
self.retain = alloc;
[alloc release];
// or
self.retain = [[NSString alloc] init];
[self.retain release];
// or
self.retain = [[[NSString alloc] init] autorelease];
// I don't like ;)
retain = [[NSString alloc] init];
}
return self;
}
- (void) dealloc {
self.normal = nil;
self.alias = nil;
self.readonly = nil;
self.private = nil;
self.retain = nil;
[super dealloc];
}
#end