how to declare a global variable in Objective-C? - objective-c

// MyClass.h
#interface MyClass : NSObject
{
NSDictionary *dictobj;
}
#end
//MyClass.m
#implementation MyClass
-(void)applicationDiDFinishlaunching:(UIApplication *)application
{
}
-(void)methodA
{
// Here i need to add objects into the dictionary
}
-(void)methodB
{
//here i need to retrive the key and objects of Dictionary into array
}
My question is since both methodA and methodB are using the NSDictionary object [i.e dictobj] In which method should i write this code:
dictobj = [[NSDictionary alloc]init];
I can't do it twice in both methods, hence how to do it golbally?

First of all, if you need to modify contents of the dictionary, it should be mutable:
#interface MyClass : NSObject
{
NSMutableDictionary *dictobj;
}
#end
You typically create instance variables like dictobj in the designated initializer like this:
- (id) init
{
[super init];
dictobj = [[NSMutableDictionary alloc] init];
return self;
}
and free the memory in -dealloc:
- (void) dealloc
{
[dictobj release];
[super dealloc];
}
You can access your instance variables anywhere in your instance implementation (as opposed to class methods):
-(void) methodA
{
// don't declare dictobj here, otherwise it will shadow your ivar
[dictobj setObject: #"Some value" forKey: #"Some key"];
}
-(void) methodB
{
// this will print "Some value" to the console if methodA has been performed
NSLog(#"%#", [dictobj objectForKey: #"Some key"]);
}

-----AClass.h-----
extern int myInt; // Anybody who imports AClass.h can access myInt.
#interface AClass.h : SomeSuperClass
{
// ...
}
// ...
#end
-----end AClass.h-----
-----AClass.h-----
int myInt;
#implementation AClass.h
//...
#end
-----end AClass.h-----

Related

NSCoding with a singleton subclass

I have a number of derived classes whose common base-class conforms to NSCoding. I want to be able to easily encode an NSArray holding instances of the various deriving classes.
#interface Base : NSObject <NSCoding>
#end
#interface DerivedSingleton : Base
+(instancetype) sharedInstance;
#end
#interface DerivedNonSingleton : Base
#end
The deriving singleton should have only one instance in the running system. It doesn't actually have any state to encode in the coder. It's instance is created with the +(void) initialize class method.
DerivedSingleton *sharedInstance;
#implementation DerivedSingleton
+(void) initialize
{
sharedInstance = [DerivedSingleton new];
}
+(instancetype) sharedInstance
{
return sharedInstance;
}
#end
So, if I now make an array holding instances of the classes, and encode it:
NSArray *const array = #[
[DerivedSingleton sharedInstance],
[DerivedNonSingleton new],
[DerivedNonSingleton new]];
NSData *const arrayData = [NSKeyedArchiver archivedDataWithRootObject: array];
When I later decode it, I require references to the shared singleton to decode as references to the shared singleton…
NSArray *const decodedArray = [NSKeyedUnarchiver unarchiveObjectWithData: arrayData];
[decodedArray objectAtIndex: 0] == [DerivedSingleton sharedInstance];
I note that the NSCoding protocol wants me to implement initWithCoder: for the singleton, but during decode, I want this class to provide the shared instance, not a newly alloced object.
Something like this should work
- (instancetype)initWithCoder:(NSCoder *)decoder
{
self = [super init];
return [self.class shared];
}
I would do something similar with the singleton:
.h
#import <Foundation/Foundation.h>
#pragma mark - Interface
#interface SerializableSingleton : NSObject <NSCoding>
#pragma mark - Class methods
#pragma mark - Shared instance
+ (instancetype)sharedInstance;
#end
.m
#import "SerializableSingleton.h"
#pragma mark - Reference
static id _serializableSingletonSharedInstance = nil;
#pragma mark - Implementation
#implementation SerializableSingleton
#pragma mark - Class methods
#pragma mark - Shared instance
+ (instancetype)sharedInstance {
#synchronized([self class]) {
if (_serializableSingletonSharedInstance == nil) {
_serializableSingletonSharedInstance = [[[self class] alloc] init];
}
}
return _serializableSingletonSharedInstance;
}
#pragma mark - Instance methods
#pragma mark - <NSCoding>
- (id)initWithCoder:(NSCoder *)aDecoder {
#synchronized([self class]) {
if (_serializableSingletonSharedInstance == nil) {
if (self = [super init]) {
// decode the desired data...
}
_serializableSingletonSharedInstance = self;
}
}
return _serializableSingletonSharedInstance;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
// encode the desired data
}
#end

How to implement initWith method passing custom object as an argument?

For instance I have following class:
#interface PrivateInfo: NSObject
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi;
#end
#implementation PrivateInfo
{
#private
NSString *name;
NSString *creditCardID;
}
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi
{
// how to init current object with passed pi ?
}
- (PrivateInfo *)copy
{
// how to create a copy of current object?
}
#end
Assuming ARC:
.h:
#interface PrivateInfo: NSObject <NSCopying>
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi;
#end
.m:
#implementation PrivateInfo {
NSString *name;
NSString *creditCardID;
}
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi
{
self = [super init];
if (self) {
name = pi->name;
creditCardID = pi->creditCardID;
}
return self;
}
- (PrivateInfo *)copyWithZone:(NSZone *)zone {
PrivateInfo *res = [[PrivateInfo alloc] initWithPrivateInfoObject:self];
return res;
}
#end
You don't need #private in the #implementation block for declaring ivars. And use the NSCopying protocol is you want to copy objects.

Objective C methods [make release] issue [duplicate]

This question already has answers here:
Under automatic reference counting, why are retain, release, and dealloc not allowed?
(4 answers)
Closed 9 years ago.
I'm using the latest xcode.
implementation file:
SimpleCar.m:
#import "SimpleCar.h"
#implementation SimpleCar
// set methods
- (void) setVin: (NSNumber*)newVin {
[vin release];
vin = [[NSNumber alloc] init];
vin = newVin;
}
- (void) setMake: (NSString*)newMake {
[make release];
make = [[NSString alloc] initWithString:newMake];
}
- (void) setModel: (NSString*)newModel {
[model release];
model = [[NSString alloc] initWithString:newModel];
}
// convenience method
- (void) setMake: (NSString*)newMake
andModel: (NSString*)newModel {
// Reuse our methods from earlier
[self setMake:newMake];
[self setModel:newModel];
}
//get methods
- (NSString*) make; {
return make;
}
- (NSString*) model;{
return model;
}
- (NSNumber*) vin;{
return vin;
}
-(void) dealloc
{
[vin release];
[make release];
[model release];
[super dealloc];
}
#end
interface file:
SimpleCar.h:
#import <Foundation/Foundation.h>
#interface SimpleCar : NSObject {
NSString* make;
NSString* model;
NSNumber* vin;
}
// set methods
- (void) setVin: (NSNumber*)newVin;
- (void) setMake: (NSString*)newMake;
- (void) setModel: (NSString*)newModel;
// convenience method
- (void) setMake: (NSString*)newMake
andModel: (NSString*)newModel;
// get methods
- (NSString*) make;
- (NSString*) model;
- (NSNumber*) vin;
#end
I get an error in the implementation file when I type "[vin release], [model release], [make release]" and I cannot run the program.
ARC is turned on, therefore memory management is automatic.
A modern definition of that class would be declared as:
#interface SimpleCar : NSObject
#property(copy) NSString *make;
#property(copy) NSString *model;
#property(copy) NSNumber *vin;
- initWithMake:(NSString*)make model:(NSString*)model vin:(NSNumber*)vin;
#end
And would be implemented as:
#implementation SimpleCar
- initWithMake:(NSString*)make model:(NSString*)model vin:(NSNumber*)vin
{
if (self = [super init]) {
_make = [make copy];
_model = [model copy];
_vin = [vin copy];
}
return self;
}
#end
You wouldn't typically implement a convenience method like setMake:andModel:. It just adds API footprint without really buying much in the way of convenience. It also raises questions like "What happens when I observe either make or model?".

Why can't I populate my controller with items?

I'm using an ItemController to provide a list of items to use in a tableview. I can't seem to populate the controller though, and I'm not sure why.
Here's the code for the controller class:
.h
#import <Foundation/Foundation.h>
#class Item;
#interface ItemController : NSObject
#property (nonatomic, copy) NSMutableArray *items;
- (NSUInteger)countOfList;
- (Item*)objectInListAtIndex:(NSUInteger)theIndex;
- (void)addItem:(Item *)item;
#end
.m
#import "ItemController.h"
#import "Item.h"
#interface ItemController ()
#end
#implementation ItemController
- (NSUInteger)countOfList {
return [self.items count];
}
- (Item *)objectInListAtIndex:(NSUInteger)theIndex {
return [self.items objectAtIndex:theIndex];
}
- (void)addItem:(Item *)item {
[self.items addObject:item];
}
#end
Item.m
#implementation Item
-(id)initWithName:(NSString *)name{
self = [super init];
if (self) {
_name = name;
return self;
}
return nil;
}
#end
I'm using the following code to populate the list:
ItemController* controller = [[ItemController alloc] init];
for (NSString* key in raw_data) {
NSLog(key); // This outputs the keys fine
[controller addItem:[[Item alloc] initWithName:key]];
}
NSLog([NSString stringWithFormat:#"%d",[controller countOfList]]); // Always 0
You need to initialize the array in the init methond.
- (id)init {
self = [super init];
if (self) {
self.items = [[NSMutableArray alloc] init];
}
return self;
}
You need to initialize your variable items. In your init method, call self.items = [NSMutableArray new]; and also change your array property from copy to retain.
I also believe your class ItemController should be of kind UIViewController and not NSObject.
#interface ItemController : UIViewController
You don't initialise the _items instance variable anywhere, so it's always nil. The result of any integer-returning method called on nil will be 0, so you see that the count is 0.

How to release property of static class

i have a static class witch has two property,like below ...
#interface Global : NSObject
{
BarcodeScanner* scanner;
NSInteger warehouseID;
}
#property(assign) BarcodeScanner* scanner;
#property(assign) NSInteger warehouseID;
+(Global *)sharedInstance;
#end
#import "Global.h"
#implementation Global
#synthesize scanner,warehouseID;
+ (Global *)sharedInstance
{
static Global *globalInstance = nil;
if (nil == globalInstance) {
globalInstance = [[Global alloc] init];
globalInstance.scanner = [[BarcodeScanner alloc] init];
globalInstance.warehouseID = 1;
}
return globalInstance;
}
-(void) dealloc
{
[super dealloc];
}
#end
now when i analyze project in Xcode i got warning for memory leak for scanner and warehouseID properties , and when i try to release them in dealloc method like ...
[[[Global sharedInstance] scanner]release];
i got warning "incorrect decrement of the reference count of an object..."
how should i resolve this problem.
so thanks for any help.
The warning is because your code does not match the rules Analyzer uses. To avoid the warning
make the scanner property retain
change the the instantiation or BarcodeScanner to be autorelease
add a release for scanner in dealloc
Example (reformatted just to save space):
#class BarcodeScanner;
#interface Global : NSObject {
BarcodeScanner* scanner;
NSInteger warehouseID;
}
#property(retain) BarcodeScanner* scanner;
#property(assign) NSInteger warehouseID;
+(Global *)sharedInstance;
#end
#implementation Global
#synthesize scanner,warehouseID;
+ (Global *)sharedInstance {
static Global *globalInstance = nil;
if (nil == globalInstance) {
globalInstance = [[Global alloc] init];
globalInstance.scanner = [[[BarcodeScanner alloc] init] autorelease];
globalInstance.warehouseID = 1;
}
return globalInstance;
}
-(void) dealloc {
[scanner release];
[super dealloc];
}
#end
just leave it to autorelease pool
globalInstance.scanner = [[[BarcodeScanner alloc] init] autorelease];