Declare public static variable in objective c [duplicate] - ios

This question already has answers here:
Objective-C: how to declare a static member that is visible to subclasses?
(3 answers)
Closed 8 years ago.
I want a static varibale in .h of a class and want it to be inherited to its child class.
#interface :UIViewController
static bool isSearchWindowOpen ; //something like this.
#end
If i write like :
static bool isSearchWindowOpen ;
#interface :UIViewController
#end
it works fine but cannot be inherited by child classes.
pls suggest.

This sounds a bit like you are confusing this with some other programming language, like C++. In Objective-C, just like C, a static variable is a variable with file scope. If you declare a static variable in a header file, then any source file including that header file has its own copy of the static variable.
You'd probably want a class method
+ (BOOL)isSearchWindowOpen
with implementation
static BOOL sSearchWindowOpen;
+ (void)setSearchWindowOpen:(BOOL)open { sSearchWindowOpen = open; }
+ (BOOL)isSearchWindowOpen { return sSearchWindowOpen; }
Probably even better to write code that checks whether the search window is open, instead of relying on a static variable that you have to track correctly all the time.

The variable as declared has nothing to do with the class. It’s a global static in the “C sense”: only code in the same file can access it. (See Wikipedia for details.) You can write class accessors:
static BOOL foo;
+ (void) setFoo: (BOOL) newFoo
{
foo = newFoo;
}
That way the class descendants can access the variable, too. But it’s not a good idea anyway. What problem are you trying to solve?

Related

Declaring private variables in header file vs declaring variables in class extension

What's the difference between declaring a #private ivar in the header file and declaring the same ivar in the class extension without #private? As far as I understand it's the same thing.
Also, can you declare a private property in the header?
The concept is to declare in the header file only those things (methods, properties, etc) which are public. Declare all private items in the implementation file's class extension.
This provides the class users only information that is available for their use and hides all else. It also make it easier for a user of the class quickly see the functionality available to him. Writing code is all about readability and understandability to the developer.
This way a developer is free to change anything that is not exposed in the header files without making any externally visible changes.
In recent versions of Objective this is finally fully releasable via class extensions.
What's the difference between declaring a #private ivar in the header file and declaring the same ivar in the class extension without #private?
There are a few differences. In short, variables declared in the header file are visible to subclasses and class categories. Variables declared in the implementation are not.
1) Instance variables declared in a class's main #interface block are available to external class categories or extensions, even if those variables are declared #private. E.g.:
// YourClass.h
#interface YourClass : NSObject {
#private
int _yourPrivateIVar;
}
#end
// MyExtension.m
#implementation YourClass(MyExtension)
- (void)reset { _yourPrivateIVar = 0; } // This is allowed.
#end
Instance variables declared in the implementation are not available to external class categories.
2) A base class and its subclass cannot both declare the same ivar in their #interface, even if both ivars are #private. E.g., this is not allowed:
#interface Base : NSObject
{
#private
int _foo;
}
#end
#interface Subclass : Base
{
#private
int _foo; // Error: Duplicate member _foo
}
#end
If both ivars are declared in a class extension or implementation block then not only does it compile but it works as expected: both classes have their own separate _foo ivars that do not conflict with one another. On other words, both variables are truly private and separate:
#implementation Base {
int _foo;
}
#end
#implementation Subclass {
int _foo;
}
- (void)reset { _foo = 123; } // Does not affect base class's _foo
#end
Note: If the base class and subclass declare a "private" property or method with the same name it will compile without warning or error, but it will fail spectacularly at runtime as both classes unknowingly interfere with each other's private data.

Using a static variable to reference instances of a class in Objective C?

I'm brand new to Objective C, and this may be somewhat of a lame question but:
I'm trying to make an iOS game, in which there is a class 'Monster' which generates a new instance of Monster every second or so, I want to be able to keep track of each Monster in order to use/manipulate it somehow.
Currently I'm trying to issue each Monster an unique ID,
e.g something like this:
//Incorrect Syntax ...
Class Monster extends CCSprite
public static global_id = 0;
public instance_id;
init() {
instance_id = global_id;
global_id ++;
}
How would I manage this in the header/implementation file for class Monster?
It seems like "static" 'doesn't exist' in Objective-C.
You'd normally work around the problem by:
sticking to the one-class-per-source-file rule;
putting a suitable global variable within that file;
marking the global variable as static, which in C terms means "not accessible from outside of this compilation unit" (and one source file is one compilation unit if you don't go out of your way with the preprocessor).
So, interface:
#interface AEMonster: CCSprite
#property (nonatomic, readonly) int instanceID;
#end
Implementation:
static int globalID = 0;
#implementation AEMonster
- (instancetype)init
{
self = [super init];
if(self)
{
_instanceID = globalID;
globalID ++;
}
return self;
}
#end
Your example didn't look like pure Objective-C. Objective-C does support static definitions. What you're describing is a classic Factory/Singleton pattern, and it would look like this:
MyClass.h:
#interface MyClass : NSObject
+ (id)getInstance;
#end
MyClass.m:
#import "MyClass.h"
+ (id) getInstance
{
static MyClass *myClass = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
myClass = [[self alloc] init];
});
return myClass;
}
This is the singleton part of the pattern, where you call MyClass *c = [MyClass getInstance]; to get a reference to the instance. Only one instance will ever exist, and this is great for things where you want something semi-global but with a better pattern (things like network services are great examples).
A Factory pattern is just a step beyond this. You build MyClass exactly the same way, but instead of a getInstance() method you would have a createMonster() method. That would take any parameters required to create the type of Monster you wanted (this pattern is especially useful when you're going to have a Monster base class and then sub-classes of specific Monster types).
That's where you would generate your unique ID. Just add another static member variable inside the factory function and you can increment it each time it's called. That's a really naive unique ID generator, though - you probably want to make sure what you do is thread-safe, too. (That's another story.)

ObjectiveC: Need suggestion for my way of having protected method? [duplicate]

This question already has answers here:
Protected methods in Objective-C
(9 answers)
Closed 9 years ago.
Simply put, I need a way to have some private methods in a class that are only exposed for its subclasses, and it is difficult (maybe impossible) to do this in Objective-C.
What I did so far:
// MyClass.h
#protocol MyClassProtectedMethodsProtocol
- (void)__protectedMethod;
#end
#interface MyClass : NSObject
- (void)publicMethod;
- (id<MyClassProtectedMethodsProtocol>)protectedInstanceForSubclass:(id)subclass;
#end
Then:
// MyClass.m
#import "MyClass.h"
#interface MyClass() <MyClassProtectedMethodsProtocol>
#end
#implementation MyClass
- (void)publicMethod
{
// something
}
- (id<MyClassProtectedMethodsProtocol>)protectedInstanceForSubclass:(id)subclass
{
if ([subclass isKindOf:MyClass.class] && ![NSStringFromClass(subclass.class) isEqualToString:NSStringFromClass(MyClass.class)])
{
// the subclass instance is a kind of MyClass
// but it has different class name, thus we know it is a subclass of MyClass
return self;
}
return nil;
}
- (void)__protectedMethod
// something protected
{
}
#end
Then the subclass of MyClass can just:
id<MyClassProtectedMethodsProtocol> protectedMethodInstance = [self protectedMethodForSubclass:self];
if (protectedMethodInstance != nil)
{
[protectedMethodInstance protectedMethod];
}
This way does not break OO (compared to calling the private method and ignoring the compiler warning, or even guessing the private method name as only .h is known), but a protocol is needed for the available protected methods and once this is exposed, in a big project that we only deliver interface and static library to client, client can actually know the private methods and try to call them regardless of warning. And the bigest problem is from outside of the subclass, user can as well call this method to get the protectedInstance. Can anyone advice?
Thanks
Check this: Protected methods in Objective-C
Simply put, there is no way to prevent a method from being called in Objective-C, since ultimately, the client can still call performSelector on any object.
A standard way to handle this scenario is to include the internal methods in a separate header, like MySuperClass_Internal.h. Use a class extension: #interface MySuperClass (Internal). Do not install MySuperClass_Internal.h at /usr/local/include or in the framework, or however you're delivering the library to your clients.

When to declare something in category .m file or in header .h file? [duplicate]

This question already has answers here:
Why is there another #interface inside the.m file? [duplicate]
(6 answers)
Closed 9 years ago.
As we know, normally we used to declare our class instance variables, properties, method declarations in class header file (.h).
But we can do the same things, in .m file, using blank category.
So my question is: what should be declared in .h file and what should be declared in .m file - and why?
Regards,
Mrunal
New Edit:
Hi all,
If you refer to newly added Apple examples over developer.apple.com - they are now declaring their IBOutlets and IBActions in .m file itself and that too with property declaration. But we can achieve the same thing by declaring those references in .h file in class private member section.
Then why are they declaring those in .m file and as properties, any idea?
-Mrunal
But we can do the same things, in .m file, using blank category.
A class continuation.
Normally, you choose to declare something in the header if it is intended to be public -- used by any client. Everything else (your internals) should typically go in the class continuation.
I favor encapsulation -- Here's my approach:
variables
Belongs in the class continuation or #implementation. Exceptions are very, very rare.
properties
Typically belongs in the class continuation in practice. If you want to give subclasses the ability to override these or to make these part of the public interface, then you could declare them in the class declaration (the header file).
method declarations
More in the class continuation than in the class declaration. Again, if it is meant to be used by any client it would belong in the class declaration. Often, you won't even need a declaration in the class continuation (or class declaration) -- the definition alone is adequate if it is private.
Basically, in the header file (.h) you declare your public API, while in the implementation file (.m) you declare your private API.
Visibility in Objective-C
You can also find the answer here
It's mostly up to you.
The .h file is like the description of your class.
It's smart to only put in the .h file what's really important to be visible from the outside of the class, especially if you're working with other developers.
It will help them to understand more easily what methods/properties/variables they can use, rather than having a whole list of things they don't.
Usually you want to use blank category in .m file for declaration of private properties.
// APXCustomButton.m file
#interface APXCustomButton ()
#property (nonatomic, strong) UIColor *stateBackgroundColor;
#end
// Use the property in implementation (the same .m file)
#implementation APXCustomButton
- (void)setStyle:(APXButtonStyle)aStyle
{
UIColor *theStyleColor = ...;
self.stateBackgroundColor = theStyleColor;
}
#end
If you try to access property declared in black category outside .m file, you will receive undeclared property compiler error:
- (void)createButton
{
APXCustomButton *theCustomButton = [[APXCustomButton alloc] init];
theCustomButton.stateBackgroundColor = [UIColor greenColor]; // undeclared property error
}
In most cases, if you want add new method/properties to an existing class without subclassing, then you want declare category in .h file and implementation of declared methods in .m file
// APXSafeArray.h file
#interface NSArray (APXSafeArray)
- (id)com_APX_objectAtIndex:(NSInteger)anIndex;
#end
// APXSafeArray.m file
#implementation NSArray
- (id)com_APX_objectAtIndex:(NSInteger)anIndex
{
id theResultObject = nil;
if ((anIndex >= 0) && (anIndex < [self count]))
{
theResultObject = [self objectAtIndex:anIndex];
}
return theResultObject;
}
#end
Now you can use "com_APX_objectAtIndex:" method wherever "APXSafeArray.h" is imported.
#import "APXSafeArray.h"
...
#property (nonatomic, strong) APXSafeArray *entities;
- (void)didRequestEntityAtIndex:(NSInteger)anIndex
{
APXEntity *theREquestedEntity = [self.entities com_APX_objectAtIndex:anIndex];
...
}

Objective C: Good way to define C array like MyStruct theArray[18][18]?

I need to use something like a C array:
MyStruct theArray[18][18];
but I cannot define it as a property:
#property (nonatomic) MyStruct theArray[18][18];
then I have to:
#implementation MyClass
{
MyStruct theArray[18][18];
}
But is this good in term of modern Objective C guideline?
Thanks
Update:
I know I can define the struct as class and use NSMutableArray to handle it, but it is more convenient to use the C array in my case, the main concern is coding guideline and memory issue, as I do not allocate or release the theArray[18][18], not sure what its life cycle is, and I'm using ARC.
Properties cannot be of array type, while public instance variables do not provide sufficient encapsulation. A more Objective C - like approach would be defining a private 2D array, and a pair of methods or a method returning a pointer to access it - something along these lines:
// For small structs you can use a pair of methods:
-(MyStruct)getElementAtIndexes:(NSUInteger)i and:(NSUInteger)j;
-(void)setElementAtIndexes:(NSUInteger)i and:(NSUInteger)j to:(MyStruct)val;
// For larger structs you should use a single method that returns a pointer
// to avoid copying too much data:
-(MyStruct*)elementAtIndexes:(NSUInteger)i and:(NSUInteger)j;
How about use pointers instead?
#property (nonatomic) MyStruct **theArray;
The answers so far are great. . . here's two more options:
1. A bit hacky
(I'm not sure if this requires Objective-C++)
You can create the array as a public property like so:
#interface MyClass
{
#public:
MyStruct theArray[18][18];
}
#end
And then access it as follows:
myClass->theArray
2. Return a Struct
While you can't return a C-style array, you can return a struct:
typedef struct
{
CGPoint textureCoordinates[kMaxHillVertices];
CGPoint borderVertices[kMaxBorderVertices];
} HillsDrawData;
#interface Hills : NSObject
{
HillsDrawData _drawData;
}
- (HillsDrawData)drawData; //This will get cleaned up when the class that owns it does.
#end

Resources