Hi everyone, I'm new to iPhone development so want to ask, what is the best way to keep global variables and constants which can be accessed by many classes?
Shall I keep them in app delegate or there is a better way which I don't know?
Thanks
Hi everyone, I'm new to iPhone development so want to ask, what is the best way to keep global variables and constants which can be accessed by many classes?
Shall I keep them in app delegate or there is a better way which I don't know?
Thanks
Keeping them in the app delegate is one solution, though it's not particularly elegant to shove everything into a class whose purpose is really to respond to events related to the application.
For constants, you can simply create header files and use #define
or const
, then include the header files wherever you need the constants.
For global variables, you can create a singleton class with static
variables. There are a lot of macros out there that can synthesize singletons for classes. Here's an example from the Google Toolbox for Mac:
//
// GTMObjectSingleton.h
// Macro to implement methods for a singleton
//
// Copyright 2005-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#define _GTMDevAssert(condition, ...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
file:[NSString stringWithUTF8String:__FILE__] \
lineNumber:__LINE__ \
description:__VA_ARGS__]; \
} \
} while(0)
/// This macro implements the various methods needed to make a safe singleton.
//
/// This Singleton pattern was taken from:
/// http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_10.html
///
/// Sample usage:
///
/// GTMOBJECT_SINGLETON_BOILERPLATE(SomeUsefulManager, sharedSomeUsefulManager)
/// (with no trailing semicolon)
///
#define GTMOBJECT_SINGLETON_BOILERPLATE(_object_name_, _shared_obj_name_) \
static _object_name_ *z##_shared_obj_name_ = nil; \
+ (_object_name_ *)_shared_obj_name_ { \
@synchronized(self) { \
if (z##_shared_obj_name_ == nil) { \
/* Note that 'self' may not be the same as _object_name_ */ \
/* first assignment done in allocWithZone but we must reassign in case init fails */ \
z##_shared_obj_name_ = [[self alloc] init]; \
_GTMDevAssert((z##_shared_obj_name_ != nil), @"didn't catch singleton allocation"); \
} \
} \
return z##_shared_obj_name_; \
} \
+ (id)allocWithZone:(NSZone *)zone { \
@synchronized(self) { \
if (z##_shared_obj_name_ == nil) { \
z##_shared_obj_name_ = [super allocWithZone:zone]; \
return z##_shared_obj_name_; \
} \
} \
\
/* We can't return the shared instance, because it's been init'd */ \
_GTMDevAssert(NO, @"use the singleton API, not alloc+init"); \
return nil; \
} \
- (id)retain { \
return self; \
} \
- (NSUInteger)retainCount { \
return NSUIntegerMax; \
} \
- (void)release { \
} \
- (id)autorelease { \
return self; \
} \
- (id)copyWithZone:(NSZone *)zone { \
return self; \
}
In case you like variety, here's another one, this one from CocoaWithLove -- he's talking about why global vars should scare you here; probably a good read.
//
// SynthesizeSingleton.h
// CocoaWithLove
//
// Created by Matt Gallagher on 20/10/08.
// Copyright 2008 Matt Gallagher. All rights reserved.
//
// Permission is given to use this source code file, free of charge, in any
// project, commercial or otherwise, entirely at your risk, with the condition
// that any redistribution (in part or whole) of source code must retain
// this copyright and permission notice. Attribution in compiled projects is
// appreciated but not required.
//
#define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \
\
static classname *shared##classname = nil; \
\
+ (classname *)shared##classname \
{ \
@synchronized(self) \
{ \
if (shared##classname == nil) \
{ \
shared##classname = [[self alloc] init]; \
} \
} \
\
return shared##classname; \
} \
\
+ (id)allocWithZone:(NSZone *)zone \
{ \
@synchronized(self) \
{ \
if (shared##classname == nil) \
{ \
shared##classname = [super allocWithZone:zone]; \
return shared##classname; \
} \
} \
\
return nil; \
} \
\
- (id)copyWithZone:(NSZone *)zone \
{ \
return self; \
} \
\
- (id)retain \
{ \
return self; \
} \
\
- (NSUInteger)retainCount \
{ \
return NSUIntegerMax; \
} \
\
- (void)release \
{ \
} \
\
- (id)autorelease \
{ \
return self; \
}
Usually I make a header file Resources.h and keep all my definition there. Using static variable is also a good idea.