Why am I getting unsafe retained? - objective-c

I've just starting out with obj-c and I created 2 files, a .h and a .m file. The .h file is..
#import <Foundation/Foundation.h>
#interface CardUnit : NSObject
{
#private
NSString *_name;
NSString *_gold;
}
#property (nonatomic, assign) NSString *name;
#property (nonatomic, assign) NSString *gold;
#end
and the .m file is
#import "CardUnit.h"
#implementation CardUnit
#synthesize gold = _gold;
#synthesize name = _name;
#end
But it's giving me 2 errors on the #synthesize lines, which are...
"Existing ivar "_gold" for property gold with assign attribute must be __unsafe retained" and the same for name.

From the error i see you are using ARC, Automatic Reference Counting .
Basically you can get rid of all the #synthesize statements and even the private declarations of the ivar's name and gold is not necessary.
All you need is the CardUnit.h to be like this :
#interface CardUnit : NSObject
#property (assign) NSString *name;
#property (assign) NSString *gold;
#end
The Xcode compiler will take care of the rest.
See also this reply on SO

Related

property not found on object of type error but property is there

So I'm trying to access the property isPortClosed(BOOL) in SerialPortController and its giving me an error, I'm kinda new to objective-c. I feel like this should work as I've got a reference to the class with *port. Here is a link to the project.
Error messages: ~/GroundStation/GroundStation/ViewController.m:16:22: Property 'isPortClosed' not found on object of type 'SerialPortController *'
#import <Cocoa/Cocoa.h>
#import "SceneView.h"
#import "SerialPortController.h"
#interface ViewController : NSViewController
#property (strong) IBOutlet SerialPortController *port;
#property (weak) IBOutlet SceneView *accelSceneView;
#end
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
while(!self.port.isPortClosed) {
}
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
#end
SerialPortController.h class
#import <Foundation/Foundation.h>
#import <ORSSerial/ORSSerial.h>
#interface SerialPortController : NSObject <ORSSerialPortDelegate>
#property (nonatomic, strong) ORSSerialPort *serial;
#property (nonatomic, strong) ORSSerialPortManager *serialPortManager;
#property (nonatomic) NSInteger xAngle;
#property (nonatomic) NSInteger yAngle;
#property (nonatomic) NSInteger zAngle;
#property (nonatomic) NSString *stringBuffer;
#property (nonatomic) BOOL isPortClosed;
#end
From the downloaded project I see that you have two SerialPortController class definitions (one at the root directory, and one in /GroundStation/), and the latter doesn't have any public properties. You should have only one SerialPortController class definition linked in your project (the one with the public properties).

'expected a type' errors in Obj-C using Parse

I'm declaring three related classes for my program and getting numerous 'Expected a type' and 'Unknown type name' errors. Having looked at similar problems on StackOverflow, I thought that perhaps I was having an issue with circular dependencies, but I can't seem to resolve the errors by using #class forward declarations. What do I need to do to get this project to build?
BQUser.h
#import <Parse/Parse.h>
#import "BQQuestion.h"
#import "BQAnswer.h"
#interface BQUser : PFUser<PFSubclassing>
#property (retain) NSString *userDescription;
#property (retain) PFFile *userImage;
- (BQQuestion *) addNewQuestion:(NSString *) question; //expected a type
- (BQAnswer *) addNewAnswer:(NSString *) answer toQuestion:(BQQuestion *) question; //expected a type
- (void) likeAnswer: (BQAnswer *) answer; //expected a type
#end
BQQuestion.h
#import <Parse/Parse.h>
#import "BQUser.h"
#interface BQQuestion : PFObject<PFSubclassing>
#property (retain) BQUser *user; //unknown type name 'BQUser'; did you mean 'PFUser'?
#property (retain) NSString *questionText;
#property (retain) NSArray *answers;
#property int answerCount;
+ (NSString *)parseClassName;
#end
BQAnswer.h
#import <Parse/Parse.h>
#import "BQUser.h"
#import "BQQuestion.h"
#interface BQAnswer : PFObject<PFSubclassing>
#property (retain) BQUser *user; //unknown type 'BQUser'; did you mean 'PFUser'?
#property (retain) BQQuestion *question; //unknown type name 'BQQuestion'
#property (retain) NSString *answerText;
#property int votes;
+ (NSString *)parseClassName;
#end

Setting variables in a different class in Cocoa

I'm trying to learn how to set variables for different classes using one main data class.
Here's a diagram of of what I would like to do and the code from my project:
ClassA
#import <Foundation/Foundation.h>
#interface ClassA : NSObject {
NSString *stringA;
NSString *stringB;
}
#property (nonatomic, copy) NSString *stringA;
#property (nonatomic, copy) NSString *stringB;
#property (weak) IBOutlet NSTextField *textA;
#property (weak) IBOutlet NSTextField *textB;
- (IBAction)displayStrings:(id)sender;
#end
#import "ClassA.h"
#implementation ClassA
#synthesize stringA, stringB, textA, textB;
- (IBAction)displayStrings:(id)sender {
[textA setStringValue:stringA];
[textB setStringValue:stringB];
}
#end
Class X
#import <Foundation/Foundation.h>
#interface ClassX : NSObject {
NSMutableString *stringX;
}
- (void)theVariables:(id)sender;
#end
#import "ClassX.h"
#import "ClassA.h"
#implementation ClassX
- (void)awakeFromNib {
[self theVariables:self];
}
- (void)theVariables:(id)sender {
stringX = [[NSMutableString alloc] init];
ClassA *clssA = [[ClassA alloc] init];
[stringX setString:#"stringX for stringA"];
[clssA setStringA:stringX];
[stringX setString:#"stringX for stringB"];
[clssA setStringB:stringX];
}
#end
No errors show up in the code, but when I run the program I am receiving an error about "Invalid parameter not satisfying: aString". It looks like the setStringValue for the IBOutlet is not working. Any suggestions?
I'm not seeing the error you mention, but as far as I can tell from your code, the main problem is this line:
ClassA *clssA = [[ClassA alloc] init];
You must have an instance of ClassA in your xib, which is connected to text fields and a button. That object in the xib is a real object, and if you just create another instance of ClassA somewhere in your code, you have an entirely different object that has no connection to the one that's in your xib.
You need to make sure of/change two things. First, there needs to be an instance of ClassX in your xib. Second, ClassX needs an outlet to a ClassA instance:
#class ClassA; // Declare ClassA so you can use it below
#interface ClassX : NSObject
#property (weak) IBOutlet ClassA * theClassAInstance;
- (void)theVariables:(id)sender;
#end
Which should then be connected in the xib file. Then, in theVariables:, you just use that outlet instead of creating a new instance of ClassA: [[self theClassAInstance] setStringA:#"stringX for stringA"];
Three points of style:
First, you should be importing Cocoa.h: #import <Cocoa/Cocoa.h> instead of Foundation.h in any class that touches the GUI (ClassA in this case). That's where stuff like NSTextField is defined. It works anyways because Cocoa.h is imported via your .pch file, but it's best to be explicit.
Second, creating a mutable string and changing its value to two different literal strings doesn't make a whole lot of sense. Just use the literals directly: [clssA setStringA:#"stringX for stringA"];
Third, You don't need to declare the instance variables separately; #synthesize creates them for you, and it is now the recommended practice to not declare them:
#interface ClassA : NSObject
#property (nonatomic, copy) NSString *stringA;
#property (nonatomic, copy) NSString *stringB;
#property (weak) IBOutlet NSTextField *textA;
#property (weak) IBOutlet NSTextField *textB;
- (IBAction)displayStrings:(id)sender;
#end
Last (four points!), you should really be accessing the values of stringA and stringB in ClassA via the property: [textA setStringValue:[self stringA]];

Is the ivar required for properties where #synthesize propertyName = _propertyName;

In the following example, is the line NSObject *_propertyName; required?
.h
#interface ClassName
{
NSObject *_propertyName;
}
#property (nonatomic, retain) NSObject *propertyName;
#end
.m
#implementation ClassName
#synthesize propertyName = _propertyName;
#end
I find that if I exclude NSObject *_propertyName; but keep #synthesize propertyName = _propertyName; everything works. Here's an example of what I'm talking about:
.h
#interface ClassName
#property (nonatomic, retain) NSObject *propertyName;
#end
.m
#implementation ClassName
#synthesize propertyName = _propertyName;
#end
I've tested and seen that the property still works. I nearly always see code that includes the line NSObject *_propertyName;. Is there something I'm missing here?
You're not missing anything. Starting with the newer runtimes (newer iOS Simulator, x86_64 and ARM) you no longer need to manually declare an ivar. Prior to that on i386 and PPC you had to manually declare your ivars.

object property in objective-c

#interface Category : NSObject
#property(nonatomic) NSInteger ID;
#property(nonatomic, retain) NSString *Name;
#property(nonatomic, retain) NSString *Description;
#end
product class
#interface Product : NSObject
#property(nonatomic) NSInteger ID;
#property(nonatomic, retain) NSString *Name;
#property(nonatomic, retain) NSString *Description;
#property(nonatomic, retain) Category *category;
#end
How do I create a property of type Category. Is it possible at all?
You do it just like you have, except you need to add a forward declaration of your Category class in Product.h (before your #interface line):
#Class Category;
And then import the header in Product.m
#import "Category.h"
1) If you class Product is defined in separate file, then:
#import "Category.h" // file, where class Category is defined
#interface Product : NSObject
#property(nonatomic) NSInteger ID;
#property(nonatomic, retain) NSString *Name;
#property(nonatomic, retain) NSString *Description;
#property(nonatomic, retain) Category *category;
#end
2) If your classes Product and Category are defined in same file then you don't need any additional import but be sure that class Categiry is defineed earlier then Product.
3) In the case when two classes have objects of type of each other then your should use #class tag:
#class Product;
#interface Category : NSObject
#property(nonatomic, retain) Product *product;
#end
#interface Product : NSObject
#property(nonatomic, retain) Category *category;
#end
Yes, it is possible, and the syntax that you have posted is correct. If you are having a problem, perhaps it may be because you need to do
#import "Category.h"
at the top of Product.h, and you will need to make sure to #synthesize category. But since you have been using other properties, I assume you knew that already.