I have a little problem with a global variable. This is the class.h:
#import <Foundation/Foundation.h>
#interface GlobalVariables : NSObject{
NSMutableArray *categories;
}
#property (nonatomic, retain) NSMutableArray *categories;
+ (GlobalVariables *)sharedInstance;
#end
And this is the class.m file:
#import "GlobalVariables.h"
#implementation GlobalVariables
#synthesize categories;
+ (GlobalVariables *)sharedInstance
{
// the instance of this class is stored here
static GlobalVariables *myInstance = nil;
// check to see if an instance already exists
if (nil == myInstance) {
myInstance = [[[self class] alloc] init];
// initialize variables here
}
// return the instance of this class
return myInstance;
}
#end
So I now have 4 tabs with UITableViewController and each Tab needs data from the category array above.
The problem is, in the first tab an update algorithm is running to update this array but however this update is only available in tab 2 if I restart the app.
What can I do to immediately see these changes in all other tabs?
Related
I have a class (singleton class) that has three global static variables. Each of these static variables has the same type (another class that has a custom init method).
When I want to initialize the static variables, one of them has the value "nil" even if the custom init method returns a valid instance.
Please consider the above code.
//The header file of the singleton class
#import "B.h"
static B *firstVariable;
static B *secondVariable;
static B *thirdVariable;
#interface A : NSObject
//some properties and methods declarations here
#end
//The implementation file of the singleton class
#import "A.h"
#implementation A
static A *sharedInstance = nil;
+ (A *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[A alloc] init];
}
return sharedInstance;
}
...
#end
//The header file for the other class
#interface B : NSObject
#property(nonatomic, strong, readonly) NSString *path;
- (instancetype)initWithPath:(NSString *)path;
#end
//The implementation of this class
#import "B.h"
#implementation B
- (instancetype)initWithPath:(NSString *)path {
self = [super init];
if (self) {
_path = path;
}
return self;
}
#end
This is how I try to initialize those static variables
firstVariable = [[B alloc] initWithPath:#"firstPath"];
secondVariable = [[B alloc] initWithPath:#"secondPath"];
thirdVariable = [[B alloc] initWithPath:#"thirdPath"];
As I previously mentioned, even if there is a valid instance inside of the "initWithPath" method before returning, the "secondVariable" has the "nil" value.
Can anyone help me out with this?
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
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.
I am working on a project that contains a Singleton instance of a class called Survey. Within that singleton instance is a property called "itemArray," which is an NSMutableArray that contains any number of instances of an Item class.
My Items class contains several NSInteger properties, but for the purposes of the application, I need to initialize all NSIntegers with a value of -1 instead of the default 0.
Now, for my Survey class (the one with the Singleton instance), I use the following method in the implementation to change the default value of a property:
-(id)init {
if (self = [super init]) {
_thingy = -1;
}
return self;
}
This works, but for some reason, the same exact syntax (with different properties) doesn't work for instances of my Item instances. For what it's worth, the following codeblock is the creation of 2 instances of Item, and their insertion into itemArray. I also tried the Item *item1 = [[Item alloc]init; method to no avail.
Item *item1;
[[[Survey sharedInstance]itemArray]insertObject:item1 atIndex:0];
Item *item2;
[[[Survey sharedInstance]itemArray]insertObject:item2 atIndex:1];
}
I would appreciate any assistance.
!!!!!UPDATE!!!!!
I entered the following conditional:
if (![[Survey sharedInstance]itemArray]){
NSLog(#"Test");
}
And the "test" logged onto the console, so it looks like the itemArray isn't being initialized. I'm not sure how to actually initialize it, though. When I try the following:
[[Survey sharedInstance]addressArray] = [[NSMutableArray alloc]init];
I'm getting an error saying "Expression is not assignable."
Survey.h:
#import <Foundation/Foundation.h>
#interface Survey : NSObject
+(instancetype)sharedInstance;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *emailAddress;
#property (nonatomic, assign) NSInteger trigger1;
#property (nonatomic, assign) NSInteger trigger2;
#property (nonatomic, assign) NSInteger trigger3;
#property (nonatomic, assign) NSInteger activeItem;
#property (nonatomic, strong) NSMutableArray *itemArray;
#end
Survey.m
#import "Survey.h"
#implementation Survey
+ (instancetype)sharedInstance {
static Survey *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[Survey alloc] init];
});
return _instance;
}
-(id)init {
if (self = [super init]) {
_storage = -1;
}
return self;
}
#end
Instead of
[[Survey sharedInstance]addressArray] = [[NSMutableArray alloc]init];
you need to use
[Survey sharedInstance].addressArray = [[NSMutableArray alloc]init];
or
[[Survey sharedInstance] setAddressArray:[[NSMutableArray alloc]init]];
You were trying to assign a value to the return value of a getter method, which is not possible, so the compiler was saying "Expression not assignable." You need to use the setter method or dot notation instead.
Very basic question here...
I have 2 classes and I want to keep an NSArray in one class and access it in different class.
Questions.h
#import <Foundation/Foundation.h>
#interface Questions : NSObject
#property NSMutableArray *questions;
-(void) questionMethod;
#end
Questions.m
#import "Questions.h"
#implementation Questions
-(void) questionMethod {
NSArray *questionBank = [4,5,6];
}
#end
ViewController.m
#import "Questions.h"
-(void)generateRandomQuestionOrder {
Questions *questions = [[Questions alloc] init];
}
How do I count the values of questionBank array in generateRandomQuestionOrder method?
Not the best naming convention but take a look at the following example. You declare a public property in the Questions object and access it from the controller after you initialised a new object there. You may consider declaring it readonly and set it to readwrite in the private interface extension.
Questions.h
#import <Foundation/Foundation.h>
#interface Questions : NSObject
#property NSMutableArray *questions;
#end
Questions.m
#import "Questions.h"
#implementation Questions
-(id) init {
if (self = [super init]) {
_questions = #[4,5,6];
}
return self;
}
#end
ViewController.m
#import "Questions.h"
-(void)generateRandomQuestionOrder {
Questions *theQuestions = [[Questions alloc] init];
NSLog(#"%#", [theQuestions.questions description]);
}