This question already has answers here:
How do I declare class-level properties in Objective-C?
(10 answers)
Closed 2 years ago.
How to setup a class property that can be accessed throughout the app and from another classes in objective C?
Note: I know that there are other answers here at SO but most of then are outdated or torn apart! The question that is marked as being duplicate was asked 11 years ago ...!
Recently I had a project where dived deeper into this topic and I like to give you some code examples that may be helpful to someone out here. This is also some kind of information storage for myself :)
Since Xcode 8 you can define a class property in the header file of YourClass, using the "class" identifier like:
#interface YourClass : NSObject
#property (class, strong, nonatomic) NSTimer *timer;
#end
To use the class property in class methods in your implementation you need to asign a static instance variable to your class property. This allows you to use this instance variable in class methods (class methods start with "+").
#implementation YourClass
static NSTimer *_timer;
You have to create getter and setter methods for the class property, as these will not be synthesized automatic.
+ (void)setTimer:(NSTimer*)newTimer{
if (_timer == nil)
_timer = newTimer;
}
+ (NSTimer*)timer{
return _timer;
}
// your other code here ...
#end
Now you can access the class property from all over the app and other methods with the following syntax - here are some examples:
NSTimeInterval seconds = YourClass.timer.fireDate.timeIntervalSinceNow;
[[YourClass timer] invalidate];
You will always send messages to the same object, no problems with multiple instances!
Please find an Xcode 11 sample project here: GitHub sample code
Related
This question already has answers here:
Where to put iVars in "modern" Objective-C?
(5 answers)
Closed 7 years ago.
Im not understanding why people use extensions to make variables private instead of just declaring them only in the implementation file ?
Take a look at this code one using extension and one using a instance variable:
//this is an extension
#interface MyClass () {
NSString *myInstanceVariable;
}
// ...
#end
or in the class implementation:
#implementation MyClass {
NSString *myInstanceVariable;
}
// ...
#end
both give me instance variables that would be private. Why would i choose a extension instead of the 2nd approach of just declaring a instance variable ?
If you are declaring variables in an #interface, it exposes details of the implementation to users of the class.
If you are declaring variables in an #implementation it keeps their existence private and is not visible to someone who only imports the h file.
Edit: For more concise answer. See here
This question already has answers here:
What is the difference between class and instance methods?
(18 answers)
Closed 9 years ago.
I have this code:
.h
#interface DetalhesPod : UIViewController {
NSString *linhaPod;
}
#property (nonatomic, strong) NSString *linhaPod;
.m
+ (NSArray *)_tracks {
NSArray *arrTexto = [self.linhaPod componentsSeparatedByString:#"#"];
}
Why I have problem with "+" in "self.linhaPod" ? If I put "-" I don't have problem:
- (NSArray *)_tracks {
}
Error message:
instance variable "linhaPod" accessed in class method...
Thanks
What you're seeing here is the difference between a class and an instance of that class. Each instance of the class has its own linhaPod instance variable — in one instance, it might point to the string #"bob" and in another it might be #"andy". The class is an entity of its own. self in a class method refers to the class itself, not to any instance. So what would it mean to access this variable from the class itself? The instance variable only exists in instances (hence why it is called an instance variable).
You can't reference a property from a static, or class method (in your case, _tracks). This is because class methods don't operate on an object, and the notion of an object property value makes no sense if you don't have an object. Class methods can only use other class methods and static variables from the same class. Check out the Wikipedia article on static methods (this concept is common to many programming languages, including Objective-C). It's a fundamental concept in programming and really worth learning about.
This question already has answers here:
Implement a pure virtual method in Objective-C
(6 answers)
Closed 9 years ago.
I was reading Creating an abstract class in Objective-C, and I wasn't terribly satisfied with the fact that the "abstractness" of the class is only enforced at runtime. I'd like to be able to show some warnings if the method is not implemented in a subclass. Ideally, this could be condensed down to one or two #defines.
Is there a clever use of __attribute((available,deprecated,etc))__ or a #warning with some careful #pragma clang diagnostic pushes that can accomplish this?
I think this is possible; I just don't know enough about Clang to figure it out.
EDIT:
There's no need to tell me I should be using protocols. I already use them for this purpose. I'm more curious to see if it can be done (to learn more about Clang) than whether it should be done.
I see this working the in a similar way to NSManagedObject requiring properties to be marked #synthesized or #dynamic. I've researched this, and I see that in NSManagedObject.h the class is marked NS_REQUIRES_PROPERTY_DEFINITIONS, which translates to __attribute__((objc_requires_property_definitions)) in NSObjCRuntime.h. Is there some creative use of these built-in #defines that could make this work?
EDIT #2:
For people saying that abstract superclasses are not the Objective-C way, I'll direct you to the documentation for UIMotionEffects:
Subclassing Notes
This class is abstract and cannot be instantiated
directly.
I prefer the NSException approach (which is a run-time, not a compile time, error).
In your superclass:
#interface NSSuperclass : NSObject
- (void)execute;
#end
#implementation NSSuperclass
- (void)execute
{
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:#"Called %# on superclass NSSuperclass, this should only be called on subclasses", NSStringFromSelector(_cmd)]
userInfo:#{#"object": self}];
}
#end
And then override this method in your subclasses.
I go for protocol
untested code, the idea is use protocol type (maybe combined with class type) instead of just class type.
#interface BaseClass : NSObject
- (void)foo;
#end
#protocol BaseClassProtocol : NSObject
#required
- (void)bar;
#end
#interface SubClass : BaseClass <BaseClassProtocol>
#end
#interface SubClass2 : BaseClass // no <BaseClassProtocol>
#end
// some code
BaseClass <BaseClassProtocol> * obj = [SubClass new]; // good
BaseClass <BaseClassProtocol> * obj = [SubClass2 new]; // warning
Edit 2: In addition to Kurt's solution, there is one more way to do it. Take a look at the end of this page, just before comments: http://www.friday.com/bbum/2009/09/11/class-extensions-explained/
Edit: It seems class methods in a class category cannot access private members such as ivars and private methods that are implemented through class extensions.
I hope this question is not asked and answered before, but I could not find one as both stackoverflow and Google search spams my browser window with kinds of questions that ask to access an ivar directly from a class method, which is clearly not my intention.
Straight to the problem, I'll provide a piece of code, which summarizes what I'm trying to accomplish:
XYZPerson.h:
#interface XYZPerson : NSObject
#property (weak, readonly) XYZPerson *spouse;
#end
XYZPersonMariage.h:
#interface XYZPerson (XYZPersonMariage)
+(BOOL)divorce:(XYZPerson *) oneOfSpouses;
#end
XYZPersonMariage.m
+(BOOL)divorce:(XYZPerson *)oneOfSpouses
{
XYZPerson *otherSpouse = [oneOfSpouses spouse];
if(otherSpouse != nil)
{
oneOfSpouses->_spouse = nil;
otherSpouse->_spouse = nil;
return true;
}
return false;
}
I first thought that maybe an ivar is not automatically synthesized for a property flagged readonly, but it is indeed synthesized.
So, what paths can I take to get the job done?
Your method +[XYZPerson divorce:] is defined in XYZPersonMarriage.m, which is a different compilation unit than XYZPerson.m where the rest of XYZPerson is implemented.
Because of this, when compiling +divorce:, the compiler doesn't know there's an implicitly synthesized _spouse variable. For all it knows, the property could be backed by a method -spouse that you implemented.
Ways to get around this:
Move the implementation of +divorce into XYZPerson.m.
Don't access ivars directly, but do the work via real methods. They don't have to be part of the usual public interface of the class; they can be exposed via a separate header file that only XYZPersonMarriage.m imports. Search for "Objective-C private method" for more discussion on the pros and cons of that pattern.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Unable to access object of other class
I've been working on a little project just to increase my comprehension of the objective-c syntaxe and functionalities but I'm stuck in my own project and can't find the answer.
First I've got two classes and in my main one I have declare a object of my other class so I can use the functions from my other class. This is how I did it (I just wrote the thing that I thought were necessary:
.h of my main class
import myOtherClass
#interface PkmViewController : UIViewController
#property Pokemon * nomDePokemon;
.m of my main class
import myOtherClass
#synthesize nomDePokemon;
int nbDef = [nomDePokemon calculerUnNombrePourLaDefense];
.h of my other class
#interface Pokemon : NSObject
#property int defencePoints;
-(int)calculerUnNombrePourLaDefense;
.m of my other class
#synthesize defencePoints;
-(int)calculerUnNombrePourLaDefense
{
int nombrerandom = arc4random() % 45;
return nombrerandom;
}
When I put a breakpoint in my main class to see what number is taken from the function, it always gives me 0. And when I put this section in my other class it works but I want to keep it in another class to improve my skills. Someone can explain me how to do it please?
It sounds like you haven't actually assigned an instance of Pokemon to your nomDePokemon variable. This means that instead of a Pokemon object, the variable contains nil, which returns nil or 0 in response to any message you send it. To solve the problem, create a Pokemon.