How to convert this to ARC - objective-c

I'm converting some older Obj-C code to ARC. I have this method:
+ (NSString **)sortKeys
{
return sortKeys;
}
And the complaint I get from the automatic conversion is:
Cannot initialize return object of type 'NSString *__autoreleasing *' with an lvalue of type 'NSString *__strong [14]
The sortKeys are declared as:
static NSString *sortKeys[] = {
NAME_KEY,
CATNUM_KEY,
CATNUM_NAME_KEY,
MAG_KEY,
DISTANCE_KEY,
CONST_KEY,
RISE_KEY,
TRANSIT_KEY,
SET_KEY,
RA_KEY,
DEC_KEY,
AZM_KEY,
ALT_KEY,
DATE_KEY
};
There is also a complaint when called:
NSString **sortKeys = [ListMgr sortKeys];
I don't want to transfer any ownership of the string, I just want the caller to be able to iterate through them.
How do I declare the method when using ARC?

This is not compatible with ARC. It can't safely memory-manage this. You're relying on behaviors that aren't promised (so this has always been unsafe). sortKeys is not retaining NAME_KEY, so there is no promise that NAME_KEY will be valid. You may happen to have special knowledge that it will be (because NAME_KEY is a static string for instance), but this is an implementation detail, not a language promise. ARC is about guarantees, not "we happen to get away with it."
The correct tool for this is an NSArray:
#interface MyClass : NSObject
+ (NSArray<NSString *>*)sortKeys;
#end
#implementation MyClass
static NSArray<NSString *>* sortKeys;
+ (void)initialize {
if (self == [MyClass class] ) {
sortKeys = #[ ... ];
}
}
+ (NSArray<NSString *>*)sortKeys
{
return sortKeys;
}
#end
If you can't change the interface, then you'll have to keep this definition in an non-ARC file.
I kept your caching here, but if you don't call +sortKeys very often, I'd get rid of the static and just construct a new array each time. It's quite cheap, especially in this case:
#interface MyClass : NSObject
+ (NSArray<NSString *>*)sortKeys;
#end
#implementation MyClass
+ (NSArray<NSString *>*)sortKeys
{
return #[...]; // Just put your value here; then it's simple
}
#end

You can use NSArray's initWithObjects:count: initializer to convert from the C array into a Foundation one, and create an ARC, memory-safe array:
+ (NSArray<NSString *> *)sortKeys
{
static NSArray<NSString *> *convertedKeys;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
convertedKeys = [[NSArray alloc] initWithObjects:sortKeys count:sizeof(sortKeys)];
});
return convertedKeys;
}
You'd get ARC-compatible code, and also you can access NSArray's helpers methods - like count, fast enumeration, etc.

Related

How to allocate memory for an array in class in objective-C?

I am very much new to objective-c and I'm struggling with this problem for a while! Here is my class prototype:
#interface YoCatchModel : NSObject
/**
Name of the Yo user. Currently this is local
*/
#property (nonatomic, strong) NSString* username;
/**
History of the messages sent with Yo
*/
#property (nonatomic, strong, readonly) NSMutableArray* historyArray;
/*
implement init method
*/
+ (instancetype) initmethod;
I should allocate memory for my history mutable array in this method which is read only.
I want to make another init method that takes a username string parameter. This new initWithUsername method should call init within its definition.
And here is implementation which I am trying to implement an init method using instancetype as the return type. But I am not really sure how to
Allocate memory for the array.
Call another init method for the user name.
#implementation YoCatchModel
+ (instancetype)initmethod {
return [[[self class] alloc] init];
}
I appreciate if anyone can give me some hint how to do this. So far I have read these pages to get to here:
http://www.techotopia.com/index.php/An_Overview_of_Objective-C_Object_Oriented_Programming#Declaring.2C_Initializing_and_Releasing_a_Class_Instance
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/DefiningClasses/DefiningClasses.html#//apple_ref/doc/uid/TP40011210-CH3-SW7
https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html#//apple_ref/doc/uid/TP40014150-CH1-SW11
The initWithUsername method becomes the designated initializer of your class and would look something like:
- (instancetype)initWithUsername:(NSString *)username
{
self = [super init];
if (self) {
_username = [username copy];
_historyArray = [NSMutableArray new];
}
return self;
}
You should make the default init method use the designated initializer:
- (instancetype)init
{
return [self initWithUsername:nil];
}
and note that this code works on the property backing instance variables, which start with _, rather than using self. (which won't work with a readonly property anyway), and this is to avoid possible KVO side-effects of the property setter methods.

Is it ok to have overriden getters of an Objective-C class be static?

I have some existing code I'm modifying from another developer. They have a static NSString declared as follows...
static NSString *myStaticString;
This string should be initialized before use. What I'm looking to do is have a property method overriden which will ensure the variable is set. Here's what my suggested layout would look like...
static NSString *myStaticString;
#interface MyClass ()
#property (readonly) NSString *myProperty;
#end
#implementation MyClass
+(NSString *)myProperty
{
if (!myStaticString)
myStaticString = [#"My string value!" retain];
return myStaticString;
}
#end
The new thing for me here is I've never declared a getter as a static method and to be honest I don't know if that is a good idea or not.
In answer to the question (and I paraphrase) "is it ok to have getters return a pointer to a static?" the answer is yes, it is.
The issue here is, though, that getters are instance methods, and you've defined a class method. So you'll end up with a confusing combination of your explicitly defined class method that happens to bear the same name of an automatically synthesized getter instance method (and, worse, that synthesized getter instance method will just be returning a pointer to some automatically synthesized ivar, which is obviously not what you intended). Bottom line, you are not overriding the getter like you obviously thought you were.
As bbum pointed out, you can easily remedy this by defining this explicitly declared method as an instance method. By doing that, you will thereby be overriding the getter, accomplishing what you probably intended.
Personally, since there's nothing here that requires an instance method, I might be inclined to just retire the property altogether and have the class method return a pointer to the string referenced by your static variable. In that case, I'd suggest one of two approaches:
If the string is truly a constant, then I might do something like:
// MyClass.h
#interface MyClass : NSObject
+ (NSString *)someString;
#end
and
// MyClass.m
#import "MyClass.h"
static NSString * const kSomeInternalConstant = #"my string";
#implementation MyClass
+ (NSString *)someString
{
return kSomeInternalConstant;
}
#end
If the string is defined at runtime, but does not change while the app is running, then I'd replace the MyClass.m with:
// MyClass.m
#import "MyClass.h"
#implementation MyClass
+ (NSString *)someString
{
static NSString *someInternalString = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
someInternalString = ... // set it to be whatever you want
});
return someInternalString;
}
#end
Clearly, replace these variable names with something more logical, but hopefully this illustrates the idea.
If you're looking for the class-level equivalent of #property, then the answer is "there's no such thing". But remember, #property is only syntactic sugar, anyway; it just creates appropriately-named object methods.
You still can use class methods that access static variables which have only a slightly different syntax.
Here's thread safe example:
// Foo.h
#interface Foo {
}
+(NSDictionary*) dictionary;
// Foo.m
+(NSDictionary*) dictionary
{
static NSDictionary* fooDict = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
// create dict
});
return fooDict;
}
You need it to be an instance method:
-(NSString *)myProperty
{
if (!myStaticString)
myStaticString = [#"My string value!" retain];
return myStaticString;
}
And, yes, that is fine.
• The retain is odd; don't need it, doesn't hurt. Best turn on ARC and be done with it.
• I'd move the static into the method or, if it never changes, just return #"My string value!" directly.
• This is not an uncommon pattern; this class may return a default, static, value and subclasses might override to return a different value, as necessary.
• When initializing a static, use dispatch_once. In this case, it doesn't matter as it is an assignment of a static constant string. But, like the retain, best to follow convention (i.e. eliminate the retain, use dispatch_once or just return the value directly).

Avoid extra static variables for associated objects keys

When using associated objects, an Objective-C runtime feature available starting from iOS 4 and OSX 10.6, it's necessary to define a key for storing and retrieving the object at runtime.
The typical usage is defining the key like follows
static char const * const ObjectTagKey = "ObjectTag";
and then use is to store the object
objc_setAssociatedObject(self, ObjectTagKey, newObjectTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
and retrieve it
objc_getAssociatedObject(self, ObjectTagKey);
(example taken by http://oleb.net/blog/2011/05/faking-ivars-in-objc-categories-with-associative-references/)
Is there a cleaner way to define the associated object key, that doesn't involve the declaration of extra variables?
According to this blog entry by Erica Sadun (whose credits go to Gwynne Raskind), there is.
objc_getAssociatedObject and objc_getAssociatedObject require a key to store the object. Such key is required to be a constant void pointer. So in the end we just need a fixed address that stays constant over time.
It turns out that the #selector implementation provides just about what we need, since it uses fixed addresses.
We can therefore just get rid of the key declaration and simply use our property's selector address.
So if you are associating at runtime a property like
#property (nonatomic, retain) id anAssociatedObject;
we can provide dynamic implementations for its getter/setter that look like
- (void)setAnAssociatedObject:(id)newAssociatedObject {
objc_setAssociatedObject(self, #selector(anAssociatedObject), newAssociatedObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (id)anAssociatedObject {
return objc_getAssociatedObject(self, #selector(anAssociatedObject));
}
Very neat and definitely cleaner than defining an extra static variable key for every associated object.
Is this safe?
Since this is implementation-dependent, a legitimate question is: will it easily break?
Quoting the blog entry
Apple would probably have to implement a completely new ABI for that to happen
If we take those words to be true, it's then reasonably safe.
If you need access to the key from outside the scope of a single method, a nice pattern for this which leads to more readable code is to create a pointer which simply points to its own address in the stack. For example:
static void const *MyAssocKey = &MyAssocKey;
If you only need access from within the scope of a single method, you can actually just use _cmd, which is guaranteed to be unique. For example:
objc_setAssociatedObject(obj, _cmd, associatedObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
A slight variation on the idea #Gabriele Petronella discussed is to associate a dictionary to every object:
//NSObject+ADDLAssociatedDictionary.h
#import <Foundation/Foundation.h>
#interface NSObject (ADDLAssociatedDictionary)
- (void)addl_setAssociatedObject:(id)object forKey:(id<NSCopying>)key;
- (id)addl_associatedObjectForKey:(id<NSCopying>)key;
#end
//NSObject+ADDLAssociatedDictionary.m
#import <objc/runtime.h>
#interface NSObject (ADDLAssociatedDictionaryInternal)
- (NSMutableDictionary *)addl_associatedDictionary;
#end
#implementation NSObject (ADDLAssociatedDictionary)
- (void)addl_setAssociatedObject:(id)object forKey:(id<NSCopying>)key
{
if (object) {
self.addl_associatedDictionary[key] = object;
} else {
[self.addl_associatedDictionary removeObjectForKey:key];
}
}
- (id)addl_associatedObjectForKey:(id<NSCopying>)key
{
return self.addl_associatedDictionary[key];
}
#end
#implementation NSObject (ADDLAssociatedDictionaryInternal)
const char addl_associatedDictionaryAssociatedObjectKey;
- (NSMutableDictionary *)addl_associatedDictionaryPrimitive
{
return objc_getAssociatedObject(self, &addl_associatedDictionaryAssociatedObjectKey);
}
- (void)addl_setAssociatedDictionaryPrimitive:(NSMutableDictionary *)associatedDictionary
{
objc_setAssociatedObject(self, &addl_associatedDictionaryAssociatedObjectKey, associatedDictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSMutableDictionary *)addl_generateAssociatedDictionary
{
NSMutableDictionary *associatedDictionary = [[NSMutableDictionary alloc] init];
[self addl_setAssociatedDictionaryPrimitive:associatedDictionary];
return associatedDictionary;
}
- (NSMutableDictionary *)addl_associatedDictionary
{
NSMutableDictionary *res = nil;
#synchronized(self) {
if (!(res = [self addl_associatedDictionaryPrimitive])) {
res = [self addl_generateAssociatedDictionary];
}
}
return res;
}
#end
Then in our category on some subclass Derived of NSObject
//Derived+Additions.h
#import "Derived.h"
#interface Derived (Additions)
#property (nonatomic) id anAssociatedObject;
#end
//Derived+Additions.m
#import "NSObject+ADDLAssociatedDictionary.h"
#implementation Derived (Additions)
- (void)setAnAssociatedObject:(id)anAssociatedObject
{
[self addl_setAssociatedObject:anAssociatedObject forKey:NSStringFromSelector(#selector(anAssociatedObject))];
}
- (id)anAssociatedObject
{
return [self addl_associatedObjectForKey:NSStringFromSelector(#selector(anAssociatedObject))];
}
#end
One benefit of the associated dictionary approach in general is the added flexibility that comes from being able to set objects for keys that are generated at runtime, not to mention the much nicer syntax.
A benefit particular to using
NSStringFromSelector(#selector(anAssociatedObject))
is that NSStringFromSelector is guaranteed to give an NSString representation of the selector which will always be an acceptable dictionary key. As a result, we don't have to worry at all (though I don't think it's a reasonable concern) about ABI changes.

Objective-C Static Class Level variables

I have a class Film, each of which stores a unique ID. In C#, Java etc I can define a static int currentID and each time i set the ID i can increase the currentID and the change occurs at the class level not object level. Can this be done in Objective-C? I've found it very hard to find an answer for this.
Issue Description:
You want your ClassA to have a ClassB class variable.
You are using Objective-C as programming language.
Objective-C does not support class variables as C++ does.
One Alternative:
Simulate a class variable behavior using Objective-C features
Declare/Define an static variable within the classA.m so it will be only accessible for the classA methods (and everything you put inside classA.m).
Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of ClassB.
You will be wondering, why should I overwrite the NSObject initialize method. Apple documentation about this method has the answer: "The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.)".
Feel free to use the static variable within any ClassA class/instance method.
Code sample:
file: classA.m
static ClassB *classVariableName = nil;
#implementation ClassA
...
+(void) initialize
{
if (! classVariableName)
classVariableName = [[ClassB alloc] init];
}
+(void) classMethodName
{
[classVariableName doSomething];
}
-(void) instanceMethodName
{
[classVariableName doSomething];
}
...
#end
References:
Class variables explained comparing Objective-C and C++ approaches
As of Xcode 8, you can define class properties in Obj-C. This has been added to interoperate with Swift's static properties.
Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: #property (class) NSString *someStringProperty;. They are never synthesized. (23891898)
Here is an example
#interface YourClass : NSObject
#property (class, nonatomic, assign) NSInteger currentId;
#end
#implementation YourClass
static NSInteger _currentId = 0;
+ (NSInteger)currentId {
return _currentId;
}
+ (void)setCurrentId:(NSInteger)newValue {
_currentId = newValue;
}
#end
Then you can access it like this:
YourClass.currentId = 1;
val = YourClass.currentId;
Here is a very interesting explanatory post I used as a reference to edit this old answer.
2011 Answer: (don't use this, it's terrible)
If you really really don't want to declare a global variable, there another option, maybe not very orthodox :-), but works... You can declare a "get&set" method like this, with an static variable inside:
+ (NSString*)testHolder:(NSString*)_test {
static NSString *test;
if(_test != nil) {
if(test != nil)
[test release];
test = [_test retain];
}
// if(test == nil)
// test = #"Initialize the var here if you need to";
return test;
}
So, if you need to get the value, just call:
NSString *testVal = [MyClass testHolder:nil]
And then, when you want to set it:
[MyClass testHolder:testVal]
In the case you want to be able to set this pseudo-static-var to nil, you can declare testHolder as this:
+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
static NSString *test;
if(shouldSet) {
if(test != nil)
[test release];
test = [_test retain];
}
return test;
}
And two handy methods:
+ (NSString*)test {
return [MyClass testHolderSet:NO newValue:nil];
}
+ (void)setTest:(NSString*)_test {
[MyClass testHolderSet:YES newValue:_test];
}
Hope it helps! Good luck.
On your .m file, you can declare a variable as static:
static ClassName *variableName = nil;
Then you can initialize it on your +(void)initialize method.
Please note that this is a plain C static variable and is not static in the sense Java or C# consider it, but will yield similar results.
In your .m file, declare a file global variable:
static int currentID = 1;
then in your init routine, refernce that:
- (id) init
{
self = [super init];
if (self != nil) {
_myID = currentID++; // not thread safe
}
return self;
}
or if it needs to change at some other time (eg in your openConnection method), then increment it there. Remember it is not thread safe as is, you'll need to do syncronization (or better yet, use an atomic add) if there may be any threading issues.
As pgb said, there are no "class variables," only "instance variables." The objective-c way of doing class variables is a static global variable inside the .m file of the class. The "static" ensures that the variable can not be used outside of that file (i.e. it can't be extern).
Here would be an option:
+(int)getId{
static int id;
//Do anything you need to update the ID here
return id;
}
Note that this method will be the only method to access id, so you will have to update it somehow in this code.
(Strictly speaking not an answer to the question, but in my experience likely to be useful when looking for class variables)
A class method can often play many of the roles a class variable would in other languages (e.g. changed configuration during tests):
#interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
#end
#implementation
+ (NSString*)theNameThing { return #"Something general"; }
- (void)doTheThing {
[SomeResource changeSomething:[self.class theNameThing]];
}
#end
#interface MySpecialCase: MyCls
#end
#implementation
+ (NSString*)theNameThing { return #"Something specific"; }
#end
Now, an object of class MyCls calls Resource:changeSomething: with the string #"Something general" upon a call to doTheThing:, but an object derived from MySpecialCase with the string #"Something specific".
u can rename the class as classA.mm and add C++ features in it.
Another possibility would be to have a little NSNumber subclass singleton.

Can I validate a #property value in Objective-C using #synthesized methods?

What it says on the tin: I'd like to use the #property/#synthesize syntax to define a property on my Objective-C 2.0 class, but I want to place restrictions on the range of values allowed in the property. For example:
#interface MyClass : NSObject {
int myValue;
}
#property (nonatomic) int myValue;
Implementation:
#implementation MyClass
#synthesize myValue(test='value >= 0');
Note that the syntax here is just an example. Is this, or something much like it possible? Alternately, what is the literal equivalent of a synthesized setter, so that I can ensure that I use the same object retention rules in my manual setters as is used in a synthesized one.
Assuming your properties are Key-Value compliant (as they would be if you are using #synthesize) you should also implement Key-Value compliant validators. Take a look at Apple's documentation on the matter: http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/Validation.html
The important thing to note is that validation does not happen automatically except when using certain kinds of binding. You either call the validator directly or by calling validateValue:forKey:error:.
You could override the produced setter to call the validator before saving it but if you are using bindings this is probably not what you want to do as the validator will possibly be called more than once for a single modification.
Also note that the validator might change the value being validated.
So lets look at your example (untested, btw. I'm not near a Mac):
#implementation MyClass
#synthesize myValue;
-(BOOL)validateMyValue:(id *)ioValue error:(NSError **)outError
{
if (*ioValue == nil) {
// trap this in setNilValueForKey
// alternative might be to create new NSNumber with value 0 here
return YES;
}
if ( [*ioValue intValue] < 0 ) {
NSString *errorString = #"myValue must be greater than zero";
NSDictionary *userInfoDict = [NSDictionary dictionaryWithObject:errorString
forKey:NSLocalizedDescriptionKey];
NSError *error = [[[NSError alloc] initWithDomain:#"MyValueError"
code:0
userInfo:userInfoDict] autorelease];
*outError = error;
return NO;
} else {
return YES;
}
}
If you wanted to override the synthesised setter and make it do the validation (still untested):
- (void)setMyValue:(int)value {
id newValue = [NSNumber numberWithInt:value];
NSError *errorInfo = nil;
if ( [self validateMyValue:&newValue error:&errorInfo] ) {
myValue = [newValue intValue];
}
}
You can see we had to wrap the integer in an NSNumber instance to do this.
When you use the #synthesize the accessor methods are generated. You can implement your own which will overwrite the generated one.
You can put your own implementation inside the accessor methods, e.g. you can add value checking before assignment and so on.
You can ommit one or the other or both, the ones that you don't implement will be generated because of #synthesize, if you use #dynamic you are specifying that you will provide accessors either at compile or run time.
Accessors will have names derived from the property name myproperty and setMyproperty. The method signatures are standard so it is easy to implement your own. The actual implementation depends on property definition (copy, retain, assign) and if it is read-only or not (read-only doesn't get set accessor). For more details see objective-c reference.
Apple reference:
#synthesize You use the #synthesize
keyword to tell the compiler that it
should synthesize the setter and/or
getter methods for the property if you
do not supply them within the
#implementation block.
#interface MyClass : NSObject
{
NSString *value;
}
#property(copy, readwrite) NSString *value;
#end
#implementation MyClass
#synthesize value;
- (NSString *)value {
return value;
}
- (void)setValue:(NSString *)newValue {
if (newValue != value) {
value = [newValue copy];
}
}
#end