Providing each subclass with its own copy of the class variable

I have the following class in my iOS application (this looks like an abstract class from the Java world).

@implementation WSObject static NSDictionary* _dictionary = nil; +(NSDictionary*) dictionary { if (_dictionary == nil) { _dictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]]; } return _dictionary; } ... @end 

Then I have several classes that implement this above WSObject using the dictionary class method. The problem is that each of these classes must have its own _dictionary , but they all use the same object from the superclass. I could, of course, copy to all subclasses, but that would violate reuse. Besides this getter, there are other class methods in WSObject that mutate the dictionary. Because of this, there would be several class methods that should be in each subclass.

How can I solve this in a reasonable way? Please tell me if my description is not enough.

+4
source share
3 answers

To give each subclass its own dictionary, save the second dictionary in the main dictionary, using the class name as the key. For instance:

 static NSMutableDictionary *_dictionary = nil; + (NSDictionary*)dictionary { if (_dictionary == nil) _dictionary = [[NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]] mutableCopy]; NSString *key = NSStringFromClass( [self class] ); if ( [_dictionary objectForKey:key] == nil ) [_dictionary setObject:[NSMutableDictionary dictionary] forKey:key]; return [_dictionary objectForKey:key]; } 
+7
source

Associative links seem to do the trick. You can essentially bind some storage to the class object itself. (I use NSString here, instead of the dictionaries you want to use, just for demonstration.)

superclass:

 #import <Foundation/Foundation.h> #import <objc/runtime.h> @interface Stuper : NSObject // Accessor method for the "class variable" + (NSString *) str; // Analog to your +localStorePath + (NSString *) quote; @end 

 #import "Stuper.h" // The doc suggests simply using the address of a static variable as the key. // This works fine, even though every class is (as in your problem) using // the same key, because we are associating to a different class each time. static char key; @implementation Stuper + (NSString *) str { NSString * s = objc_getAssociatedObject(self, &key); if( !s ){ s = [self quote]; // You'll probably want to use OBJC_ASSOCIATION_RETAIN for your dictionary. // self inside a class method is the class object; use that as // the associator. The string is now tied to the associator, ie, // has the same lifetime. objc_setAssociatedObject(self, &key, s, OBJC_ASSOCIATION_COPY); } return s; } + (NSString *) quote { return @"It was the best of times, it was the worst of times."; } @end 

<h / "> <h /">

Subclass:

 #import "Stuper.h" @interface Stub : Stuper @end 

 #import "Stub.h" @implementation Stub + (NSString *) quote { return @"Call me Ishmael."; } @end 

<h / "> <h /">

Attempt:

 #import <Foundation/Foundation.h> #import "Stuper.h" #import "Stub.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; NSLog(@"%@", [Stuper str]); NSLog(@"%@", [Stub str]); [pool drain]; return 0; } 

Each class object now has its own string associated with it.

2011-12-05 23: 11: 09.031 SubClassVariables [36254: 903] It was the best time, it was the worst time.
2011-12-05 23: 11: 09.034 SubClassVariables [36254: 903] Call me Ishmael.

The only drawback here is that you will need to call the access method every time you want this object; you do not have a pointer that you can use directly. You can call objc_getAssociatedObject in the superclass as an accessory, of course, since it has access to key .

+8
source

Perhaps you can return a copy of the dictionary

 @implementation WSObject static NSDictionary* _dictionary = nil; +(NSDictionary*) dictionary { if (_dictionary == nil) { _dictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]]; } return [_dictionary copy]; } ... @end 

Keep in mind that if you change _dictionary , you will get a copy of this modified dictionary, which may differ from what is on disk.

How often is it called? Is it really necessary to cache the contents of the file in this static _dictionary object?

Why not just extract it each time to a form disk, assuming it's not too often that performance is being questioned.

 @implementation WSObject +(NSDictionary*) dictionary { return [NSKeyedUnarchiver unarchiveObjectWithFile:[self localStorePath]]; } ... @end 
+2
source

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


All Articles