I have a table view controller that a user can select from and it passes a dictionary to a UITabBarController.
How do I get the different views to access the same data stored in the UITabController?
In my UITabBarController
#interface MasterTabController : UITabBarController
#property (nonatomic,strong) NSMutableDictionary * detailDictionary;
#end
Is it common practice to keep passing the same data dictionary around? I want to be able to manipulate the data so I can later post it online.
Should I create a singleton? Can I call just the detailDictionary from bView?
It sounds like you want to want to have three different table views, in there different tabs, and set the delegates to their views, and the data source to a custom class in your model.
You can create singleton class like this
+ (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]) {
someProperty = [[NSString alloc] initWithString:#"Default Property Value"];
}
return self;
}
For reference http://www.galloway.me.uk/tutorials/singleton-classes/
A very common, generic question but it seems that everybody has it's own opinion about accessing variables that belong in another class. What I want is to use boolean variable in class2 to perform a statement. Example of what I want is:
Class1.h
#Interface Class1{
bool boolean;
}
#Property (nonatomic, retain) bool boolean;
Class1.m
#synthesize boolean;
Class2.m
if(class1.boolean == YES){
Do Something
}
The if statement is class2 doesn't seem to work, as I tried to print the boolean value in class2 and all it returns is false. I want to get the current value of class1 boolean variable and use it in class 2 without initialising it.
Looking at your question, it seems you want to create an instance of 'Class1' in another class, get the properties value to be presented there.
In that case, whenever you instantiate 'Class1', it comes with the initial values. That means the values will be 'null' for sure. If you want to get the changed value, you need to create 'Class1' as Singleton class, where, this class will be instantiated once in the whole application. Means change the value of 'boolean1' in any class, and get the same value in another, whenever or wherever you want.
But again, it totally depends on how you want to use the whole thing.
Singleton example:
// Class1.h
#interface Class1 : NSObject
/**
* A boolean property
*/
#property (nonatomic, strong) BOOL *boolean;
// Class1.m
#implementation Class1
// This is actual initialisation of the class instance.
+ (Class1 *)sharedInstance {
static Class1 *sharedInstance = nil; //static property, so that it can hold the changed value
// Check if the class instance is nil.
if (!sharedInstance) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// If nil, create the instance, using dispatch_once, so that this instance never be created again. So, if needed, app will use the existing instance.
sharedInstance = [[super allocWithZone:NULL] init];
// custom initialisation if needed
});
}
return sharedInstance;
}
// So that, if somebody uses alloc and init, a new instance not created always.
// Rather use existing instance
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedInstance];
}
// So that, if somebody uses alloc and init, a new instance not created always.
// Rather use existing instance
- (id)copyWithZone:(NSZone *)zone {
return self;
}
#end
Now updating and using the value.
//Class2.m
#import "Class1.h"
Class1 *myinstance = [[Class1 alloc] init];
myinstance.boolean = YES;
Getting the value on another class
//Class3.m
#import "Class1.h"
Class1 *myinstance = [[Class1 alloc] init];
if(myinstance.boolean == YES){
Do Something
}
I know there are several threads on this, but none answer my questions.
I've implemented my singleton class like this (being aware of the controversy about singletons):
+ (MyClass*) sharedInstance {
static MyClass *_sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[MyClass alloc] init];
});
return _sharedInstance;
}
- (instancetype)init{
self = [super init];
if (self) {
//setup code
}
return self;
}
I tried instantiating a different object and compared it to the one returned by sharedInstance with '==' and they were indeed different.
Questions:
Shouldn't creating more than one object of the singleton class be impossible? Isn't that the point? Singleton implementation in Java prevents it.
And if so, how? Should I make a setup method and call it instead of having the init implemented and doing it?
Is this correct implementation?
Your observation is correct, many of the "singleton" patterns you see in Objective-C are not singletons at all but rather a "shared instance" model where other instances can be created.
In the old MRC days Apple used to have sample code showing how to implement a true singleton.
The code you have is the recommended pattern for ARC and thread-safe singletons, you just need to place it in the init method:
- (instancetype) init
{
static MyClass *initedObject;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
initedObject = [super init];
});
return initedObject;
}
This code will ensure that there is only ever one instance of MyClass regardless of how many [MyClass new] or [[MyClass alloc] init] calls are made.
That is all you need to do, but you can go further. First if you wish to have a class method to return the singleton it is simply:
+ (instancetype) singletonInstance
{
return [self new];
}
This method ends up calling init which returns the singleton, creating it if needed.
If MyClass implements NSCopying then you also need to implement copyWithZone: - which is the method which copy calls. As you've a singleton this is really simple:
- (instancetype) copyWithZone:(NSZone *)zone
{
return self;
}
Finally in Objective-C the operations of allocating a new object instance and initialising it are distinct. The above scheme ensures only one instance of MyClass is initialised and used, however for every call to new or alloc another instance is allocated and then promptly discarded by init and cleaned up by ARC. This is somewhat wasteful!
This is easily addressed by implementing allocWithZone: (like copy above this is the method alloc actually ends up calling) following the same pattern as for init:
+ (instancetype) allocWithZone:(NSZone *)zone
{
static MyClass *allocatedObject;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
allocatedObject = [super allocWithZone:zone];
});
return allocatedObject;
}
The first time an instance is created then allocWithZone: will allocate it and then init will initialise it, all subsequent calls will return the already existing object. No discarded unneeded allocations.
That's it, a true singleton, and no harder than the faux-singletons that are so common.
HTH
You can't make the init method private, like you would do in Java with the constructor. So nothing stops you from calling [[MyClass alloc] init] which indeed creates a different object. As long as you don't do that, but stick to the sharedInstance method, your implementation is fine.
What you could do: have the init method raise an exception (e.g. with [self doesNotRecognizeSelector:#_cmd]) and perform the initialization in a different method (e.g. privateInit) which is not exposed in the header file.
With objective-c, you can prevent your singleton class to create more than one object. You can prevent alloc and init call with your singleton class.
#import <Foundation/Foundation.h>
#interface SingletonClass : NSObject
+ (id) sharedInstance;
- (void) someMethodCall;
- (instancetype) init __attribute__((unavailable("Use +[SingletonClass sharedInstance] instead")));
+ (instancetype) new __attribute__ ((unavailable("Use +[SingletonClass sharedInstance] instead")));
#end
#import "SingletonClass.h"
#implementation SingletonClass
+ (id) sharedInstance{
static SingletonClass * sharedObject = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedObject = [[self alloc] initPrivate];
});
return sharedObject;
}
- (instancetype)init {
#throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:#"You can't override the init call in class %#", NSStringFromClass([self class])] userInfo:nil];
}
- (instancetype)initPrivate {
if (self = [super init]) {
}
return self;
}
- (void) someMethodCall{
NSLog(#"Method Call");
}
#end
1# If you will try to call init or new methods on SingletonClass, then these methods would not be available to call.
2# If you comment out mentioned below methods in header file and try to call the init on SingletonClass method then app will be crashed with reason "You can't override the init call in class SingletonClass".
- (instancetype) init __attribute__((unavailable("Use +[SingletonClass sharedInstance] instead")));
+ (instancetype) new __attribute__ ((unavailable("Use +[SingletonClass sharedInstance] instead")));
Just use this code to create single object to Singleton Pattern and prevent alloc init call for singleton pattern from other classes. I had tested this code with xCode 7.0+ and its working fine.
To prevent creating multiple objects of single class, you need to do following things. you just fine to created singleton object. but while calling init, copy, mutable copy, you need to handle such way.
- (instancetype)init{
if (!_sharedInstance) {
_sharedInstance = [MyClass sharedInstance];
}
return _sharedInstance;
}
- (id)copy{
if (!_sharedInstance) {
_sharedInstance = [MyClass sharedInstance];
}
return _sharedInstance;
}
the same things for mutable copy as well. so this implementation make sure that once one instance is available throughout..
May this help you.
#VeryPoliteNerd just mark the init and new methods as unavailable on the .h:
- (instancetype)init __attribute__((unavailable("Use +[MyClass sharedInstance] instead")));
+ (instancetype)new __attribute__((unavailable("Use +[MyClass sharedInstance] instead")));
This will cause the compiler to complain if a caller tries to manually instantiate this objects
This works for me:
static AudioRecordingGraph * __strong sharedInstance;
+(instancetype)sharedInstance {
#synchronized(self) {
if(!sharedInstance) {
sharedInstance = [AudioRecordingGraph new];
}
return sharedInstance;
}
}
I wanted to add observation for a modern implementation of Objective-C singletons for optimal Swift interoperability. But let me start with the code. Let’s assume for a second that the class was to manage a series of requests, so I might call it a RequestManager:
// RequestManager.h
NS_ASSUME_NONNULL_BEGIN
#interface RequestManager : NSObject
#property (nonatomic, strong, readonly, class) RequestManager *sharedManager;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)copy NS_UNAVAILABLE;
- (instancetype)mutableCopy NS_UNAVAILABLE;
- (void)someMethod;
#end
NS_ASSUME_NONNULL_END
And
// RequestManager.m
#implementation RequestManager
+ (instancetype)sharedManager {
static RequestManager *_sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
//setup code
}
return self;
}
- (void)someMethod { ... }
#end
Note:
Note, I made the singleton a class property rather than a class method.
From the Objective-C side, it is a distinction without difference, but from Swift, you can do things like MyClass.shared without the noise of the (). This is the pattern that Apple has adopted with all of their singletons.
One might give the singleton a more meaningful name. For example, if the class was a RequestManager, the singleton might be called sharedManager rather than sharedInstance.
If you do this, Swift will automatically detect the salient portion of the instance name and will expose it to Swift as shared, not sharedInstance or whatever.
If you really want to use the name sharedInstance in your Objective-C code, then will just need to supply an explicit NS_SWIFT_NAME of shared to adopt the nice, concise, and consistent singleton naming practice in Swift:
#property (nonatomic, strong, readonly, class) RequestManager *sharedInstance NS_SWIFT_NAME(shared);
Note the use of NS_UNAVAILABLE. This prevents callers from accidentally instantiating their own copies. E.g. from Objective-C:
Or from Swift:
Probably needless to say, I’ve audited this for nullability, namely using the NS_ASSUME_NONNULL_BEGIN/END to make the default non-null. Or, obviously, you could just mark the singleton property as nonnull.
Calling alloc / init to get a second instance of a Singleton class is considered a blatant programming error. To avoid this kind of programming error, you don't write complicated code to prevent it, you do code reviews and tell off everyone trying to do it, as you would with any programming error.
This works for me :
static DataModel *singleInstance;
+ (DataModel*)getInstance{
if (singleInstance == nil) {
singleInstance = [[super alloc] init];
}
return singleInstance;
}
You can call it with
_model = [DataModel getInstance];
I'm trying to build MVC Application with Objective-C, I'm trying to allocate and init my model once in my superclass witch is UIViewController, my idea is to do it once in superclass and to have access from every subclass of my superclass.
superclass.h
#property (nonatomic, strong) Lecturer *lecturer;
superclass.m
- (void) viewDidLoad {
[super viewDidLoad];
}
#pragma mark - GET
- (Lecturer *)lecturer {
if (!_lecturer) {
_lecturer = [Lecturer alloc]init];
}
return _lecturer;
}
My idea is to call self.lecturer from all subclasses and set/get the lecturer class property's but every time when i call self.lecturer its creating a new instance, i know i can use SINGLETONE but is there any way i can do it differently without singletone design pattern?
Thanks for attention.
How about using static variable?
- (Lecturer *)lecturer {
static dispatch_once_t onceToken;
static Lecturer *o;
dispatch_once(&onceToken, ^{
o = [[Lecturer alloc] init];
});
return o;
}
In addition dispatch_once helps to do it thread-safely.
How to access instance variable which is defined in class viewController.
ViewController.h
#interface ViewController : UIViewController
{
Class1* class1;
}
ViewController.m
#implementation ViewController
class1 = [[Class1 alloc]init];
#end
Class1.h
#interface Class1 : NSObject
{
NSMutableArray* variablesArray;
}
#property NSMutableArray* variablesArray;
Class1.m
#implementation Class1
#synthesize variablesArray;
#end
Now I would like to access to instance "class1" variable "variablesArray" from Class2.m. I want to add and get objects from MutableArray "variablesArray". Is it possible?
Yes it is Possible.
Make object of other class and access the variable.
In claas2 import Class1 (#import "Class1")
Class1 *objClass1= [[Class1 alloc] init];
now access like
[objClass1.variableArray addObject:#"object"];
[objClass1.variableArray objectAtIndex:0];
If you want to access same instance of array make a Singleton Class
by adding this class method in your class
+ (Class1 *)sharedInstance
{
static Class1 *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken,
^{
shared = [[self alloc] init];
});
return shared;
}
and access in Class2 like
[[Class1 sharedInstance] variableAray];
Hey you can access variable in another class by Simple making property of the variable like this
#property(nonatomic, strong) NSString *str;
I gave an Answer close to this please check this link
You can access the public property of a class instance by simple using the dot-operator. Notice that there are several ways to encapsulate an instance variable by setting property attributes like (readwrite, readonly).
Class1 aClass = [[Class1 alloc] init];
aClass.varibalesArray addObject:#[ #"someObject" ];
Make sure you initialize the NSMutableArray correctly in the init method of Class1
- (id)init
{
self = [super init];
if (self) {
_variablesArray = [NSMutableArray array];
}
return self;
}