Global variables for class methods

Background

In Cocoa, Apple often uses the following paradigm:

[NSApplication sharedApplication] [NSNotificationCenter defaultNotificationCenter] [NSGraphicsContext currentContext] [NSCalendar currentCalendar] 

etc.

They will also sometimes use the paradigm, which, in my opinion, is far more understandable when working with a huge amount of code.

 NSApp //which maps to [NSApplication sharedApplication] 

goal

I would like to use this global variable both in my own classes and in extensions for other classes.

 MYClassInstance NSDefaultNotificationCenter NSCal /* or */ NSCurrentCalendar 

etc.

The duh approach

#define It's just #define NSCal [NSCalendar currentCalendar] , but as we all know, macros are evil (or, as they say), and it just doesn't seem to be the right Cocoa way to do this.

Apple approach

The only source I could find regarding NSApp was APPKIT_EXTERN id NSApp; , which is not a completely repeated code. If I'm not mistaken, all this code defines NSApp as the id world around. Unfortunately, it is useless.

Close but not completely

In my searches, I managed to find a few guides regarding the "global constants", however such things:

 extern NSString * const StringConstant; 

unfortunately, they are limited by compile-time constants and cannot be matched to the required class.

Bottom line

I would like to collapse my own NSApp global variables that map to class methods such as [NSNotificationCenter defaultNotificationCenter] . Is it possible? If so, how do I do this?

Further attempts

I am trying to implement specific structure singlets as follows:

MySingletons.h

 //... extern id NSNotifCenter; //... 

MySingletons.m

 //... +(void)initialize { NSNotifCenter = [NSNotificationCenter defaultCenter]; } //... 

MyAppDelegate.m

 //... #import "MySingletons.h" //... //in applicationDidFinishLaunching: [MySingletons initialize]; NSLog(@"%@", NSNotifCenter); //... 

However, this leads to a compile-time error when the _NSNotifCenter character cannot be found.

Goal!

I'm currently working on an Objective-C class to encapsulate some of the single-mode frameworks that I talked about in this question. I will add GitHub information here when I pick it up.

+6
source share
2 answers

This is ridiculous, I just made this proposal on another matter.

You simply expose the variable that contains the singleton instance as the most global. NSApp does not actually display a sharedApplication call. This is a regular old pointer; it was configured during the application launch process to point to the same instance that you would receive from this call.

Like NSApp , you declare a variable for any file that imports the header:

 extern MySingleton * MySingletonInstance; 

in the header (you can use APPKIT_EXTERN if you want: the docs indicate that it just solves extern in ObjC anyway).

In the implementation file, you define a variable. Typically, a variable containing a shared instance is declared static to limit its association with this file. If you remove static , the statement defines the repository that is β€œupdated” in the header.

Then use it as before. The only caveat is that you still have to call the oneton [MySingleton sharedInstance] installation method before using the WAN for the first time to make sure it is initialized. -applicationDidFinishLaunching: may be a good candidate for a place to do this.

Regarding creating pointers to frame singlets, you can simply write the result of [CocoaSingleton sharedInstance] in any variable you like: ivar in the class that wants to use it, a local variable or in a global variable that you initialize very early in your program with using the function you are writing.

The fact is that this is not guaranteed so as not to cause problems. Except in the case of NSApp (or if it is not documented NSApp ), there really is no guarantee that the object that you return from any given sharedInstance call will remain alive, valid, or useful after the call stack ends,

It may just be paranoia, but I would advise against it if you cannot find a guarantee somewhere that the alleged singletones that interest you always return the same instance. Otherwise, you may suddenly encounter a dangling global pointer.

Turning to your code, the header declaration does not create a variable. You still need a definition:

 // MySingletons.h // Dear compiler, There exists a variable, NSNotifCenter, whose // storage is elsewhere. I want to use that variable in this file. extern id NSNotifCenter; 

 // MySingletons.m // Dear compiler, please create this variable, reserving memory // as necessary. id NSNotifCenter; @implementation MySingletons // Now use the variable. // etc. 

If you are creating a singleton, you can take a look at the Apple singleton documentation .

+8
source

The existing discussion here was so intriguing that I did a little research and discovered something that I did not know before: I can #import header file from my own project to the .pch project (precompiled header), This header file automatically becomes visible to everyone other class files in my project without any effort on my part.

So, here is an example of what I'm doing right now. In the .pch file, under the existing code:

 #import "MyIncludes.h" 

There are two types of things in MyIncludes.h, categories and external (the latter as suggested by Josh):

 extern NSString* EnglishHiddenKey; extern NSString* IndexOfCurrentTermKey; @interface UIColor (mycats) + (UIColor*) myGolden; + (UIColor*) myPaler; @end 

At MyIncludes.m, we provide definitions to satisfy all ads from the header file. External elements should not be defined from any class:

 #import "MyIncludes.h" NSString* EnglishHiddenKey = @"englishHidden"; NSString* IndexOfCurrentTermKey = @"indexOfCurrentTerm"; @implementation UIColor (mycats) + (UIColor*) myGolden { return [self colorWithRed:1.000 green:0.894 blue:0.541 alpha:.900]; } + (UIColor*) myPaler { return [self colorWithRed:1.000 green:0.996 blue:0.901 alpha:1.000]; } @end 

Except for the part about using the pch file to get magical global visibility, this is actually no different from Josh's suggestion. I am posting it as a separate answer (and not just a comment), because it is long and requires formatting, and explicit code can help someone.

(Please note that there is no memory management because I use ARC. Of course, externs are leaking, but they must flow: they need to live until the application starts.)

+2
source

Source: https://habr.com/ru/post/903727/


All Articles