Set property of NSObject - ios

Somehow i can not change the properties of my custom object anymore.
I used Xcode 6 to create my project and moved to XCode 7 now. It told me to "update to recommended settings" and i did it.
Object.h
#interface Object : NSObject <NSCoding>
#property (nonatomic, copy) NSString *ID;
ViewController.m
#import "Object.h"
#interface ViewController ()
#end
Object *myObject;
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
myObject = [[Object alloc] init];
}
- (IBAction)editProperty:(id)sender {
myObject.ID = _textfield.text;
NSLog(#"ID : %#",myObject.ID);
}
This all worked perfectly fine, but now myObject.ID is always (null).....
When i write this code:
myObject.ID = _textfield.text;
NSLog(#"ID : %#",myObject.ID);
inside viewDidLoad it works...

One major issue is this line:
Object *myObject;
What is myObject? It is just floating free. It is not a property. It is not an instance variable. So what is it? That line is legal but it makes little sense.

Related

Property Inheritance in Objective C

I want to inherit my base class properties and methods which will be used by my several derived classes. I want these properties and methods to be exactly protected so that they will only be visible in derived class and not to any external class. But it always gives me some errors.
#interface BasePerson : NSObject
#end
#interface BasePerson ()
#property (nonatomic, strong) NSMutableArray<Person*>* savedPersons;
#property (nonatomic) BOOL shouldSavePerson;
#end
#interface DerivedPerson1 : BasePerson
#end
#implementation DerivedPerson1
- (instancetype)init
{
if (self = [super init]) {
self.savedPersons = [NSMutableArray array];
self.shouldSavePerson = NO;
}
return self;
}
It always gives me an error that
Property 'savedPersons' not found on object of type 'DerivedPerson1 *'
Property 'shouldSavePerson' not found on object of type 'DerivedPerson1 *'
How i can make use of inheritance in Objective C, I don't want savedPersons and shouldSavePerson properties to be visible to external classes. I only want them to visible in my base class and all the derived classes.
Any help will be great. Thanks
This is not something that the objectiveC really support. There are some ways though. So lets see.
If you put a property in the source file class extension then it is not exposed and you can not access it in the subclass either.
One way is to put all of the subclasses into the same source file as the base class. This is not a good solution at all as you do want to have separate files for separate classes.
It seems logical to import the BaseClass.m in the SubClass source file but that will produce a linker error saying that you have duplicate symbols.
And the solution:
Separate the extension into a separate header. So you have a MyClass
Header:
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
#end
Source:
#import "MyClass.h"
#import "MyClassProtected.h"
#implementation MyClass
- (void)foo {
self.someProperty = #"Some text from base class";
}
#end
Then you create another header file (only the header) MyClassProtected.h which has the following:
#import "MyClass.h"
#interface MyClass ()
#property (nonatomic, strong) NSString *someProperty;
#end
And the subclass MyClassSubclass
Header:
#import "MyClass.h"
#interface MyClassSubclass : MyClass
#end
And the source:
#import "MyClassSubclass.h"
#import "MyClassProtected.h"
#implementation MyClassSubclass
- (void)foo {
self.someProperty = #"We can set it here as well";
}
#end
So now if the user MyClassSubclass he will not have the access to the protected property which is essentially what you want. But the downside is the user may still import MyClassProtected.h after which he will have the access to the property.
Objective-C doesn't have member access control for methods, but you can emulate it using header files.
BasePerson.h
#interface BasePerson : NSObject
#property (strong,nonatomic) SomeClass *somePublicProperty;
-(void) somePublicMethod;
#end
BasePerson-Private.h
#import "BasePerson.h"
#interface BasePerson ()
#property (nonatomic, strong) NSMutableArray<Person*>* savedPersons;
#property (nonatomic) BOOL shouldSavePerson;
#end
BasePerson.m
#import "BasePerson-Private.h"
...
DerivedPerson1.h
#import "BasePerson-Private.h"
#inteface DerivedPerson1 : BasePerson
...
#end
Now any class that #imports BasePerson.h will only see the public methods. As I said though, this is only emulating access control since if a class #imports *BasePerson-Private.h" they will see the private members; this is just how C/Objective-C is.
We can achieve using #protected access specifier
#interface BasePerson : NSObject {
#protected NSMutableArray *savedPersons;
#protected BOOL shouldSavePerson;
}
DerivedPerson1.m
#implementation DerivedPerson1
- (instancetype)init
{
if (self = [super init]) {
self->savedPersons = [NSMutableArray array];
self->shouldSavePerson = NO;
}
return self;
}
#end
OtherClass.m
#import "OtherClass.h"
#import "BasePerson.h"
#implementation OtherClass
- (void)awakeFromNib {
BasePerson *base = [[BasePerson alloc]init];
base->savedPersons = #[];//Getting Error. Because it is not a subclass.
}
#end

CoreData property cannot be found in forward class object [duplicate]

I'm adapting This tutorial to my app, and I've got it boiled down to one last error, which is stopping me in my tracks. The program is unable to find a property in another file, but that property is clearly defined. Here is the code in question:
The actual error line:
for (DTContact *dtc in _dtContact.contact) {
the .h for the file, and items in question:
#import <UIKit/UIKit.h>
#class XMLTestViewController;
#class DTCXMLResponse;
#interface XMLTestController : UIViewController{
UIWindow *window;
XMLTestViewController *viewController;
DTCXMLResponse *_dtContact;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet XMLTestViewController *viewController;
#property (nonatomic, retain) DTCXMLResponse *dtContact;
#property (nonatomic, retain) IBOutlet UIButton *mybutton;
-(IBAction)buttonClicked;
#end
It's having issues with the _dtContact.contact. It can't find the contact in the file DTCXMLResponse. Here is the .h file and the section of the .m:
.h
#import <Foundation/Foundation.h>
#interface DTContactXMLResponse : NSObject {
NSMutableArray *_contact;
}
#property (nonatomic, retain) NSMutableArray *contact;
#end
.m
#import "DTCXMLResponse.h"
#implementation DTContactXMLResponse
#synthesize contact = _contact;
- (id)init {
if ((self = [super init])) {
self.contact = [[NSMutableArray alloc] init];
}
return self;
}
#end
So theres that. As you can see, I have 'contact' propertied in the DTCXMLResponse.h, and linked in the .m.
This error usually points out that Xcode can not recognize your symbol.
I can assume this is DTContact.
Try to insert this in your .h file:
#import DTContact.h
Its not relevant to ur case but I was getting the same error. I googled for a solution but the problem was in my code. I was using different class object as I was copy pasting similar snippet of code in my project. So here is the problem that I had for the same error :
For my classA , I had some code snippet like :
ManagedObjectOfClassA * managedObjectOfClassA = [NSEntityDescription insertNewObjectForEntityForName:#"ManagedObjectOfClassA" inManagedObjectContext:managedObjectContext];
managedObjectOfClassA.somePropertyA = sameValue; //somePropertyA is an attribute of ManagedObjectOfClassA
And similar code for class B :
ManagedObjectOfClassA *managedObjectOfClassB = [NSEntityDescription insertNewObjectForEntityForName:#"ManagedObjectOfClassB" inManagedObjectContext:managedObjectContext];
managedObjectOfClassB.somePropertyB = someValue;////somePropertyB is an attribute of ManagedObjectOfClassB
If u look closely, the mistake was in assigning the right entities to the corresponding objects in class B.
So the problem is in code of class B. And the correct code would be :
ManagedObjectOfClassB *managedObjectOfClassB = [NSEntityDescription insertNewObjectForEntityForName:#"ManagedObjectOfClassB" inManagedObjectContext:managedObjectContext];
managedObjectOfClassB.somePropertyB.someValue;
I hope that helps someone.

How to save UITextField Text to NSString?

In my main view controller, I have a UITextField, and I am trying to save the text input into it to a NSString in my Homework model(class).
Homework.h
#import <Foundation/Foundation.h>
#interface Homework : NSObject
#property (nonatomic, strong) NSString *className;
#property (nonatomic, strong) NSString *assignmentTitle;
#end
Homework.m
#import "Homework.h"
#implementation Homework
#synthesize className = _className;
#synthesize assignmentTitle = _assignmentTitle;
#end
In my assignmentViewController, I create an object of type Homework and try to set it equal to whatever is entered into the the UITextField when the Save Button is pressed.
Assignment View Controller
#import <UIKit/UIKit.h>
#import "Homework.h"
#interface Assignment : UIViewController {
}
#property(nonatomic) IBOutlet UITextField *ClassNameField;
#property(nonatomic) IBOutlet UILabel *ClassNameLabel;
#property (weak, nonatomic) IBOutlet UIButton *SaveButton;
#property (nonatomic, strong) Homework *homeworkAssignment;
- (IBAction)Save:(UIButton *)sender;
#end
AssignmentViewController.m
- (IBAction)Save:(UIButton *)sender {
self.homeworkAssignment.className = self.ClassNameField.text;
NSLog(#"SaveButtonPressed %#", self.homeworkAssignment.className);
}
The NSLog prints out that className is (null). Can anyone help me figure out what I am doing wrong? This is my first ever iOS app (besides Hello World).
Edit: This is using ARC
Edit: I tried changing
self.homeworkAssignment.className = self.ClassNameField.text; to
self.homeworkAssignment.className = #"TEST";
and the log still shows (Null).
Double check you properly linked ClassNameField outlet and that you're initializing homeworkAssignment. Something like.-
self.homeworkAssignment = [[Homework alloc] init];
By the way, you should consider using camelCase notation for your variable names :)
Well to be honest the first steps are always hard but you should learn it the right way, héhé
First of all synthesize this way:
#synthesize labelAssignmentTitle,labelClassName;
or
#synthesize labelAssignmentTitle;
#synthesize labelClassName;
there is no need to do the following:
#synthesize className = _className;
#synthesize assignmentTitle = _assignmentTitle;
Now if you initialize the right way from the the start you'll find it a lot easier later!
HomeWork.h
#interface HomeWork : NSObject
#property (nonatomic, strong) NSString *className;
#property (nonatomic, strong) NSString *assignmentTitle;
-(id)initWithClassName:(NSString *)newClassName andAssignmentTitle:(NSString*)newAssigmentTitle;
HomeWork.m
#implementation HomeWork
#synthesize assignmentTitle,className;
-(id)initWithClassName:(NSString *)newClassName andAssignmentTitle:(NSString*)newAssigmentTitle {
self = [super init];
if(self){
assignmentTitle = newAssigmentTitle;
className = newClass;
}
return self;
}
#end
ViewController.m
- (IBAction)saveIt:(id)sender {
HomeWork *newHomeWork = [[HomeWork alloc]initWithClassName:[labelClassName text]andAssignmentTitle:[labelAssignmentTitle text]];
}
Because of this, you directly make a newHomeWork object with the parameters given by your two UITextFields.
Now print it out in your logmessage and see what happends ;)

Issue passing object to NSMutableArray in AppDelegate

I'm having trouble making a shopping cart sort-of concept in my app. I have my AppDelegate (named ST2AppDelegate) that contains an NSMutableArray called myCart. I want RecipeViewController.m to pass an NSString object to myCart, but every time I pass it the NSString and use NSLog to reveal the contents of the array, it is always empty.
Can anyone please tell me what I am doing wrong? I have worked on this code for days, and there is a line of code in which I don't understand at all what's going on (in the RecipeViewController.m, labeled as such).
Any help would be so appreciated... I'm just a beginner. Here are the relevant classes:
ST2AppDelegate.h:
#import <UIKit/UIKit.h>
#interface ST2AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) NSMutableArray* myCart;
- (void)addToCart:(NSString*)item;
- (void)readCartContents;
#end
ST2AppDelegate.m:
#import "ST2AppDelegate.h"
#implementation ST2AppDelegate
#synthesize myCart;
// all the 'applicationDid...' methods...
- (void)addToCart:(NSString *)item
{
[self.myCart addObject:item];
}
- (void)readCartContents
{
NSLog(#"Contents of cart: ");
int count = [myCart count];
for (int i = 0; i < count; i++)
{
NSLog(#"%#", myCart[count]);
}
}
#end
RecipeDetailViewController.h:
#import <UIKit/UIKit.h>
#import "ST2AppDelegate.h"
#interface RecipeDetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel* recipeLabel;
#property (nonatomic, strong) NSString* recipeName;
#property (nonatomic, strong) IBOutlet UIButton* orderNowButton;
- (IBAction)orderNowButtonPress:(id)sender;
#end
RecipeDetailViewController.m:
#import "RecipeDetailViewController.h"
#implementation RecipeDetailViewController
#synthesize recipeName;
#synthesize orderNowButton;
// irrelevant methods...
- (IBAction)orderNowButtonPress:(id)sender
{
// alter selected state
[orderNowButton setSelected:YES];
NSString* addedToCartString = [NSString stringWithFormat:#"%# added to cart!",recipeName];
[orderNowButton setTitle:addedToCartString forState:UIControlStateSelected];
// show an alert
NSString* addedToCartAlertMessage = [NSString stringWithFormat:#"%# has been added to your cart.", recipeName];
UIAlertView* addedToCartAlert = [[UIAlertView alloc] initWithTitle:#"Cart Updated" message:addedToCartAlertMessage delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[addedToCartAlert show];
// add to cart (I don't understand this, but it works)
[((ST2AppDelegate*)[UIApplication sharedApplication].delegate) addToCart:recipeName];
// read cart contents
[((ST2AppDelegate*)[UIApplication sharedApplication].delegate) readCartContents];
}
#end
You need to initialize myCart when your application launches:
self.myCart = [[NSMutableArray alloc] init];
otherwise you are just attempting to add objects to a nil object which while it won't throw an exception because of the way objective-c handles nil objects it will not function as expected until you initialize it.
Do you ever initalize the shopping cart variable?
Try doing lazy instantiation.
-(NSMutableArray *) myCart{
if (!_myCart){
_myCart = [[NSMutableArray alloc] init];
}
return _myCart;
}
This way you will know it will always get allocated. Basically, this method makes it so that whenever someone calls your classes version of the object it checks to see if that object has been allocated and then allocates it if it has not. It's a common paradigm that you should employ with most of your objects.
This method should go in the app delegate (where the object was declared).

Property cannot be found in forward class object

I'm adapting This tutorial to my app, and I've got it boiled down to one last error, which is stopping me in my tracks. The program is unable to find a property in another file, but that property is clearly defined. Here is the code in question:
The actual error line:
for (DTContact *dtc in _dtContact.contact) {
the .h for the file, and items in question:
#import <UIKit/UIKit.h>
#class XMLTestViewController;
#class DTCXMLResponse;
#interface XMLTestController : UIViewController{
UIWindow *window;
XMLTestViewController *viewController;
DTCXMLResponse *_dtContact;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet XMLTestViewController *viewController;
#property (nonatomic, retain) DTCXMLResponse *dtContact;
#property (nonatomic, retain) IBOutlet UIButton *mybutton;
-(IBAction)buttonClicked;
#end
It's having issues with the _dtContact.contact. It can't find the contact in the file DTCXMLResponse. Here is the .h file and the section of the .m:
.h
#import <Foundation/Foundation.h>
#interface DTContactXMLResponse : NSObject {
NSMutableArray *_contact;
}
#property (nonatomic, retain) NSMutableArray *contact;
#end
.m
#import "DTCXMLResponse.h"
#implementation DTContactXMLResponse
#synthesize contact = _contact;
- (id)init {
if ((self = [super init])) {
self.contact = [[NSMutableArray alloc] init];
}
return self;
}
#end
So theres that. As you can see, I have 'contact' propertied in the DTCXMLResponse.h, and linked in the .m.
This error usually points out that Xcode can not recognize your symbol.
I can assume this is DTContact.
Try to insert this in your .h file:
#import DTContact.h
Its not relevant to ur case but I was getting the same error. I googled for a solution but the problem was in my code. I was using different class object as I was copy pasting similar snippet of code in my project. So here is the problem that I had for the same error :
For my classA , I had some code snippet like :
ManagedObjectOfClassA * managedObjectOfClassA = [NSEntityDescription insertNewObjectForEntityForName:#"ManagedObjectOfClassA" inManagedObjectContext:managedObjectContext];
managedObjectOfClassA.somePropertyA = sameValue; //somePropertyA is an attribute of ManagedObjectOfClassA
And similar code for class B :
ManagedObjectOfClassA *managedObjectOfClassB = [NSEntityDescription insertNewObjectForEntityForName:#"ManagedObjectOfClassB" inManagedObjectContext:managedObjectContext];
managedObjectOfClassB.somePropertyB = someValue;////somePropertyB is an attribute of ManagedObjectOfClassB
If u look closely, the mistake was in assigning the right entities to the corresponding objects in class B.
So the problem is in code of class B. And the correct code would be :
ManagedObjectOfClassB *managedObjectOfClassB = [NSEntityDescription insertNewObjectForEntityForName:#"ManagedObjectOfClassB" inManagedObjectContext:managedObjectContext];
managedObjectOfClassB.somePropertyB.someValue;
I hope that helps someone.

Resources