If I have a class/object like this
#import <Foundation/Foundation.h>
#interface anObject : NSObject {
NSString *aProp;
}
#property NSString aProp;
#end
and in the cellForRowAtIndexPath method i want to assign one of the string values from its properties to a uilabel of a tableviewcell, how do i do it?
I've tried this but it doesn't work
[[cell topLabel] setText:(NSString *)anObject.aProp];
Putting a breakpoint on the above line and inspecting it, the debugger says "variable is not a CFString
Casting the property to a CFString doesnt work
Modifying the class and declaring the property as a CFStringRef doesnt work either
cell.textLabel.text = #"Foo";
This is the proper way to declare the property:
#property (nonatomic, copy) NSString * aProp;
note: the issue was with your "NSString aProp" not being a pointer.
and, yes, as frog suggested, copy is more appropriate.
Related
I apologise if this is a bad question as I'm new to iOS development. So here is my problem: I declared a class variable NSString, the string is assigned a string value from a textView but when i try to access the string from other method, the app crashes. Here's the code:
Interface: (ClassName.h)
#interface ClassName: UIViewController <UITextViewDelegate>{}
#property (nonatomic, assign)NSString *strSomeText;
#end
Implementation: (ClassName.m)
#implementation
#synthesize strSomeText;
- (void)textViewDidChange:(UITextView *)textView{
strSomeText = textView.text;
NSLog(#"%#", strSomeText); //This line works just fine
}
- (void)textViewDidEndEditing:(UITextView *)textView{
NSLog(#"%#", strSomeText); //this line causes the app to crash
}
#end
Thanks for the help!
Loc.
Your problem is likely due to the fact that you're using assign for your property. This will mean that the string can be deallocated while you still have a reference to it. Try using copy instead:
#property (nonatomic, copy) NSString *strSomeText;
Then you should use your property accessor in your textViewDidChange: method:
self.strSomeText = textView.text;
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
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];
Hi i will try to explain my problem: i'm working with webservices and i need to give variable or label.text to webservice request wich is in another class... I tried in lots ways, but i can't find solution. I know it must be very easy, but i'm new in objective-c so i have problem in primitive situation. Thanks for everyone who will help me :)
Use an instance variable and a property. See here.
In .h:
#interface YourClass : Superclass {
NSString *text;
}
#property (nonatomic, retain) NSString *text;
in .m you have to synthesize it:
#implementation YourClass
#synthesize text;
now you can set this variable like so:
[instanceOfYourClass setText:someText];
get it like so:
someString = [instanceOfYourClass text];
and use it like so (in your implementation):
someString = [self text];
This makes no sense to me. Maybe someone here can explain why this happens.
I've got an NSMutableString that I alloc at the top of my iPhone app, then append to later in the process. It results in a SIGABRT, which doesn't add up to me. Here's the code:
Header File (simplified):
#interface MyAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
NSMutableString *locationErrorMessage;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, copy) NSMutableString *locationErrorMessage;
#end
And the relevant parts of the Main:
#implementation MyAppDelegate
#synthesize window;
#synthesize locationErrorMessage;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
self.locationErrorMessage = [[NSMutableString alloc] init];
}
- (void)anotherFunction {
[self.locationErrorMessage appendString: #"Blah Blah Blah"];
}
This all seems simple enough. What am I missing?
I would call this a bug in how property setters are generated, but the answer is pretty simple:
You declared the property as (nonatomic, copy). This means that whenever the locationErrorMessage property is set, it's going to invoke copy on the new value and use that copy as the property value.
Unfortunately, invoking copy on an NSMutableString does not result in an NSMutableString, it results in an NSString (which cannot be mutated using something like appendString:).
So the simple fix would be to change the property declaration from copy to retain.
(I would say that the bug would be: If you declare a property for a mutable object as copy, then the copy setter should actually use mutableCopy and not copy) => rdar://8416047
Your property is copying the passed in string. A copy always is immutable, so you’re trying to send appendString: to an immutable NSString. Declare your property as retain and it will work or write a custom setter that copies the string using mutableCopy.
You also have a memory leak, you should use [NSMutableString string] instead of the alloc-init sequence.
Btw, you have a leak there,
self.locationErrorMessage = [[NSMutableString alloc] init];
you're copying the value, but you never release the actual first allocated NSMutableString.