I've got a singleton class named MyManager which holds multiple of properties. One of these properties is a custom class I've made that inherits from NSObject and also holds multiple properties.
One of my ViewControllers changes one of the properties in the MyManager class but for some reason, it also changes a property (with the same name), but inside the custom object.
To explain:
MyManager:
Custom object
objectThatGetsSet (inside custom object)
objectThatGetsSet
Once I set the objectThatGetsSet in MyManager, it also get's set inside the custom object. Why is this and how can I avoid it?
Here's the MyManager header file:
#import <Foundation/Foundation.h>
#import "myClass.h"
#interface MyManager : NSObject
#property (nonatomic, strong) NSDate *objectThatGetsSet;
#property (nonatmoc, strong) myClass *customObject;
+(id)sharedManager;
#end
And here's the implementation file:
#import "MyManager.h"
#implementation MyManager
#synthesize objectThatGetsSet, customObject;
#pragma mark Singleton Methods;
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
-(id)init {
if (self == [super init]) {
}
return self;
}
#end
Here's the custom class header file:
#import <Foundation/Foundation.h>
#interface myClass : NSObject
#property (nonatomic, strong) myClass objectThatGetsSet;
#end
And the implementation file:
#import "WorkLocationModel.h"
#implementation WorkLocationModel
-(id)init {
// Init self
self = [super init];
if (self)
{
// Setup
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.objectThatGetsSet forKey:#"objectThatGetsSet"];
}
-(instancetype)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self)
self.objectThatGetsSet = [coder decodeObjectForKey:#"objectThatGetsSet"];
return self;
}
#end
Please help me with this, thanks a lot!
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 have four classes MainVC, ParentClient and ChildClient1, ChildClient2(which are subclasses of ParentClient). ParentClient has a delegate to MainVC such that in MainVC
- (void)viewDidLoad
{
[super viewDidLoad];
[ParentClient instance].mainViewDelegate = self;
}
And then the ParentClient looks like this
#interface BaseClient : NSObject
#property (assign) id<MainVCInteraction> mainViewDelegate;
+(instancetype) instance;
#end
Now I want to access mainViewDelegate from ChildClient1, ChildClient2 and it returns me nil while [ParentClient instance].mainViewDelegate returns the correct value
Here is what I did I removed the BaseClient Class so that ChildClient1, ChildClient2 were no longer subclasses of BaseClient. I defined a objective-c protocol file MainVCInteaction.h and made Client1, Client2 look like this:
#import "MainVCInteraction.h"
#interface ChildClient1 : NSObject
#property (assign) id<MainVCInteraction> mainViewDelegate;
+(instancetype) instance;
#end
#import "MainVCInteraction.h"
#interface ChildClient2 : NSObject
#property (assign) id<MainVCInteraction> mainViewDelegate;
+(instancetype) instance;
#end
And then MainVC implements this protocol, I assigned the delegate like this
- (void)viewDidLoad
{
[super viewDidLoad];
[ChildClient1 instance].mainViewDelegate = self;
[ChildClient2 instance].mainViewDelegate = self;
}
So I was having issues where I had circular dependencies and so I am trying to implement forward declaration. I have three classes (logger, api, helpers), all of which are singleton objects. I have one controller class (globalclass), that has properties linking to the three classes.
Here is my code:
includes.h:
#import "globalclass.h"
#import "logger.h"
#import "api.h"
#import "helpers.h"
globalclass.h:
#class logger
#class api
#class helpers
#interface globalclass : NSObject
+ (id) sharedGlobal;
- (id) init;
...
#property (nonatomic, strong) logger *log;
#property (nonatomic, strong) api *remote;
#property (nonatmoic, strong) helpers *utils;
...
logger/api/helpers.h templates:
#class globalclass
#interface logger : NSObject
+ (id) sharedLogger;
- (id) init;
...
#property (nonatomic, strong) globalclass *gc;
...
globalclass.m:
#import "includes.h"
#implementation globalclass
/*
* Singleton Class
*/
+ (id) sharedGlobal
{
static globalclass *sharedGlobalClass = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedGlobalClass = [[self alloc] init];
});
return sharedGlobalClass;
}
/*
* Init
*/
- (id) init
{
self = [super init];
if (!self) return nil;
// Logging
self.logger = [logger sharedLogger];
...
return self;
}
logger/api/helpers.m template:
#import "includes.h"
#implementation logger
/*
* Singleton Class
*/
+ (id) sharedLogger
{
static logger *sharedLog = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedLog = [[self alloc] init];
});
return sharedLog;
}
/*
* Init
*/
- (id) init
{
self = [super init];
if (!self) return nil;
// Global Class
self.gc = [GlobalClass sharedGlobal];
...
return self;
}
Then, in my AppDelegate, I have a property to the global class and am doing this:
self.gc = [GlobalClass sharedGlobal];
However, it seems that everytime I boot up my app, it stalls and is automatically terminated because it takes too long to boot up.
Am I thinking about forward globals incorrectly?
The app builds fine.
Any help would be appreciated.
Thanks.
You have a deadlock, because the dispatch_once block in sharedGlobal is (via the global class init) invoking sharedLogger, which itself is invoking sharedGlobal (via the logger class init).
Since everything is singletons, there are a few approaches you could take to avoid this issue. Here are two:
A. Replace any self.log usages in the global class with [logger sharedLogger], and replace any self.gc usages in the logger class with [globalclass sharedGlobal]. You can get rid of these properties entirely. dispatch_once is very fast after the first invocation, so performance is not a reason to store reference to singletons as properties (though you could conceivably have other reasons)
B. Keep the log and gc properties, but make them readonly properties with custom getters:
#property (nonatomic, readonly) globalclass *gc;
// implementation:
- (globalclass *)gc
{
return [globalclass sharedGlobal];
}
#property (nonatomic, readonly) logger *log;
// implementation:
- (logger *)log
{
return [logger sharedLogger];
}
Personally I would choose A.
Both of these alternatives eliminate any references to the singleton accessors from the init methods, which gets rid of the deadlock.
I have a protocol in one class:
#protocol DataStorageManager
- (void) saveFile;
#end
#interface DataManager : NSObject
{
id <DataStorageManager> delegate;
}
#property (nonatomic, assign) id<DataStorageManager> delegate;
//methods
#end
and its implementation:
#implementation DataManager
#synthesize delegate;
#end
and I have another class which is the adapter between the first and the third one:
#import "DataManager.h"
#import "DataPlistManager.h"
#interface DataAdapter : NSObject <DataStorageManager>
#property (nonatomic,strong) DataPlistManager *plistManager;
- (void) saveFile;
#end
and its implementation
#import "DataAdapter.h"
#implementation DataAdapter
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
return self;
}
- (void) saveFile
{
[self.plistManager savePlist];
}
#end
So when I in first method try to call my delegate method like this
[delegate saveFile];
Nothing happened. I don't understand what's wrong with the realization - it's a simple adapter pattern realization. So I need to use the delegate which will call the methods from the third class. Any help?
You are not setting the delegate property. You need to do this,
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
self.plistManager.delegate = self;
return self;
}
Also, in DataManager class remove the ivar declaration, just declaring property is sufficient, the ivar gets automatically created. Call the delegate method as below,
if([self.delegate respondsToSelector:#selector(saveFile)] {
[self.delegate saveFile];
}
Hope that helps!
In your case you forget to set your protocol delegate and also need to call protocol method
by self.delegate....
I just Give Basic Idea for how to Create Protocol
Also Read This Question
#DetailViewController.h
#import <UIKit/UIKit.h>
#protocol MasterDelegate <NSObject>
-(void) getButtonTitile:(NSString *)btnTitle;
#end
#interface DetailViewController : MasterViewController
#property (nonatomic, assign) id<MasterDelegate> customDelegate;
#DetailViewController.m
if([self.customDelegate respondsToSelector:#selector(getButtonTitile:)])
{
[self.customDelegate getButtonTitile:button.currentTitle];
}
#MasterViewController.m
create obj of DetailViewController
DetailViewController *obj = [[DetailViewController alloc] init];
obj.customDelegate = self;
[self.navigationController pushViewController:reportTypeVC animated:YES];
and add delegate method in MasterViewController.m for get button title.
#pragma mark -
#pragma mark - Custom Delegate Method
-(void) getButtonTitile:(NSString *)btnTitle;
{
NSLog(#"%#", btnTitle);
}
I want to override an NSString property declared in a superclass. When I try to do it using the default ivar, which uses the the same name as the property but with an underscore, it's not recognised as a variable name. It looks something like this...
The interface of the superclass(I don't implement the getter or setter in this class):
//Animal.h
#interface Animal : NSObject
#property (strong, nonatomic) NSString *species;
#end
The implementation in the subclass:
//Human.m
#implementation
- (NSString *)species
{
//This is what I want to work but it doesn't and I don't know why
if(!_species) _species = #"Homo sapiens";
return _species;
}
#end
Only the superclass has access to the ivar _species. Your subclass should look like this:
- (NSString *)species {
NSString *value = [super species];
if (!value) {
self.species = #"Homo sapiens";
}
return [super species];
}
That sets the value to a default if it isn't currently set at all. Another option would be:
- (NSString *)species {
NSString *result = [super species];
if (!result) {
result = #"Home sapiens";
}
return result;
}
This doesn't update the value if there is no value. It simply returns a default as needed.
to access the superclass variables, they must be marked as #protected, access to such variables will be only inside the class and its heirs
#interface ObjectA : NSObject
{
#protected NSObject *_myProperty;
}
#property (nonatomic, strong, readonly) NSObject *myProperty;
#end
#interface ObjectB : ObjectA
#end
#implementation ObjectA
#synthesize myProperty = _myProperty;
#end
#implementation ObjectB
- (id)init
{
self = [super init];
if (self){
_myProperty = [NSObject new];
}
return self;
}
#end