Lazy loading Objective-C class with int properties - objective-c

I use the following as a getter for a property in one of my classes:
- (NSString *)version
{
if (_version == nil) {
_version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
}
return _version;
}
This works well. However, when I try the same for an int property I obviously get an error since int are never nil. What is the best way around this?
- (int)numberOfDays
{
if (_numberOfDays == nil) {
// relatively memory intense calculation that works out numberOfDays:
_numberOfDays = X;
}
return _numberOfDays;
}

Firstly, using int is not recommended Objective-C if possible. If you need to use a primitive integer type, you should use NSInteger. The size of NSInteger is determined at compile time based on the architecture(s) being built for. int is a static size that will not widen for different architectures. It's OK to use it, just be aware.
Using NSInteger, you still face the same problem, it can't be nil. You should therefore make your property an NSNumber which you can init with the result of your computation with [NSNumber numberWithInteger:anInteger];. That way, you can keep you nil check on your property and only do the computation once to create your NSNumber.

Add another boolean instance variable _numberOfDaysCalculated.
A thread-safe version would be
- (int)numberOfDays
{
#synchronized(self) {
if (!_numberOfDaysCalculated) {
// relatively memory intense calculation that works out numberOfDays:
_numberOfDays = X;
_numberOfDaysCalculated = YES;
}
}
return _numberOfDays;
}
Alternatively, if there is some "invalid" value of the property, you can use that
as a "not yet computed" marker. For example, if the computed value of numberOfDays has to be non-negative, you could initialize _numberOfDays = -1 in the init method,
and then test for if (_numberOfDays == -1) in the lazy getter method.

Use GCD.
static dispatch_once_t tok;
dispatch_once(&tok, ^{ memory_intensive_computation(); });
No, don't use GCD, I missed the point. In an instance method, you want to tie information to each instance, so using a static dispatch token is not appropriate. Maybe you should just stick with the "boolean flag as instance variable" approach.
Alternatively, you can initialize the int to a value which is known to be out of its valid range (for example, I suppose that numberOfDays can never be negative) and use that as a condition for performing the calculation.

Use a NSNumber to store the int value.
- (int)numberOfDays
{
if (_numberOfDays == nil) {
// relatively memory intense calculation that works out numberOfDays:
_numberOfDays = #(X);
}
return [_numberOfDays intValue];
}

I would initialize the _numberOfDays in the -init with NSNotFound and test for that in the getter.

Related

Is it okay to return a subclass from a class constructor that uses instancetype?

I have a class method in a category to construct a Cocoa collection in some way that the built-in initializers don't allow. Due to the limited initializer functionality, I have to use the mutable version of the collection to actually build it. Here's an example for NS{Mutable}IndexSet:
#implementation NSIndexSet (WSSNonContiguous)
+ (instancetype)WSSIndexSetFromMask:(NSUInteger)mask
{
NSMutableIndexSet * set = [NSMutableIndexSet indexSet];
for( NSUInteger i = 0; i < (sizeof(NSUInteger) * 8); i++ ){
if( mask & (1l << i) ){
[set addIndex:i];
}
}
return set;
}
My return type is sometimes a lie here -- there's always a mutable collection being returned, whether the user is requesting an immutable version or not.
Is it still appropriate to use instancetype in cases like this, or should I go with id? If I do use instancetype, should I also be explicitly re-creating the collection:
// Ick?
return [[self alloc] initWithIndexSet:set];
to make sure an immutable copy is returned when the call is +[NSIndexSet WSSIndexSetFromMask:]?
Everything is okay:
NSIndexSet *set = [[NSIndexSet WSSIndexSetFromMask:0] addIndex:0];
No visible #interface for 'NSIndexSet' declares the selector 'addIndex:'
instancetype says to the sender, that you return a instance of the receivers type even it is a subtype. For the sender it is a NSIndexSet, because it is send to the class object of NSIndexSet.
An introspection that way, that someone looks to the return type and sees a subclass and takes any advantage out of this information, is malformed. The contract is build with the return type and this is in this case NSIndexSet.

How to pass ivar into a function and set it without losing the reference to the original object

I am passing an ivar (NSMutableArray) into some method. I was expecting that if I modify the object inside the function, it would be reflected outside the function, but in this case I need to set the object; something like the following:
- (void) someMethod:(SMResponseObject *)response onData:(NSMutableArray *)imAnIvar {
imAnIvar = [response objects];
//Some other stuff
}
But I noticed that the memory reference of imAnIvar inside the function changes when I set it, and given that, the actual ivar doesn't change. I understand that the problem is that I'm changing the reference of the object inside the method, so it stops pointing to the ivar and then it points to some other random memory direction.
I thought about one solution to this problem, and it can be to ensure that the ivar is not nil before calling the function and do something like this:
- (void) someMethod:(SMResponseObject *)response onData:(NSMutableArray *)imAnIvar {
NSMutableArray *data = [response objects];
[arrayForTableView removeAllObjects];
for(id element in data){
[imAnIvar addObject:element];
}
//Some other stuff
}
So I use the original object instead of setting it directly. The problem is that in order for this to work I need to ensure that the ivar is not nil, which I think is not clean, because I'll need to do something like this on every call to the method:
if(!_ivar){
//alloc it
}
So my question is: Is there a way to force the local scope variable to point to the original variable even if I'm setting it? if not, is there any cleaner way to make this work?
Do you mean this?
- (void)setFoo:(SomeClass **)objPtr
{
*objPtr = someOtherObject;
}
// call it as:
SomeClass *foo = someObject;
NSLog(#"Before: %#", foo);
[self setFoo:&foo];
NSLog(#"After: %#", foo);
Why not use a getter for the array so that you need not check for the array being nil while using it?
-(NSMutableArray *)iAmAnIvar {
if(_iAmAnIvar == nil) {
_iAmAnIvar = [NSMutableArray array];
}
return _iAmAnIvar;
}
And when you have to set a value to the array, as you mentioned in your question, you could use
[self.iAmAnIvar removeAllObjects];
[self.iAmAnIvar addObject:someObj];
I believe you can use the - (id)copy; function of NSObject
so your code might look like this:
- (void)someFunction:(NSString *)someArg
{
NSString *str = [someArg copy];
}

Obj-C: using mutable and returning non mutable classes in methods

In objective-C I find myself creating alot of Mutable objects and then returning them as non mutable objects. Is the way I am doing it here, simply returning the NSMutableSet as an NSSet a good practice? I was thinking maybe I should specify that i make a copy of it.
/** Returns all the names of the variables used in a given
* program. If non are used it returns nil */
+ (NSSet *)variablesUsedInProgram:(id)program
{
NSMutableSet* variablesUsed = [[NSMutableSet alloc]init];
if ([program isKindOfClass:[NSArray class]]) {
for (NSString *str in program)
{
if ([str isEqual:#"x"] || [str isEqual:#"y"] || [str isEqual:#"a"] || [str isEqual:#"b"])
[variablesUsed addObject:str];
}
}
if ([variablesUsed count] > 0) {
return variablesUsed;
} else {
return nil;
}
}
If I were you, I would do it this way.
+ (NSSet *)variablesUsedInProgram:(id)program
{
NSSet *variablesUsed;
if ([program isKindOfClass:[NSArray class]]) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF = 'x' or SELF = 'y' or SELF = 'z'"];
variablesUsed = [NSSet setWithArray:[program filteredArrayUsingPredicate:predicate]];
}
int count;
return (count = [variablesUsed count]) > 0 ? variablesUsed : nil;
}
I find using predicate to filter array quite comprehensive and easy. Rather than dealing with creating a new mutable type and then testing certain condition, adding until the loop; in this scenario, it seems to be easier to use predicate. Hope this helps you.
It depends how much safety you require. If you return the object as an NSSet it will still be an NSMutableSet, so it could easily be cast back to one and modified.
Certainly, if you're creating a public API, I'd recommend returning a copy. For in internal project, perhaps the method signature already makes the intention clear enough.
Its, worth noting that, generally the performance impact of returning a copy is negligible - copying an immutable instance is effectively free whereas each copy sent to a mutable-passing-as-immutable will create another copy. So I would say its good practice to default to.
No. This is an absolutely correct OOP approach (it takes advantage of polymorphism). Every NSMutableSet is a proper NSSet. Don't copy superfluously.
Not a full answer here, consider NSProxy's one, but I want to clarify something.
In your case you create your object from scratch, and you don't set any ivar to point to that object. In my opinion in a good percentage of cases you don't need to make a copy of the mutable object returned. But if there is a good reason to deny the class client from mutating the class, then you should copy the variable.
Consider a property like this:
#property (nonatomic,assign) NSSet* set;
The class client could do this:
NSMutableSet* set= ... ; // inizialized to some value
classInstance.set= set;
// Mutate the set
Once mutated the set it could make the class be in an inconsistent state.
That's why when I have a property with the type of a class that has also a mutable version, I always put copy instead of assign in the property.

Implementing NSFastEnumerator: EXC_BAD_ACCESS when iterating with for…in

I have a data structure that I wanted to enumerate. I tried to implement my object's NSFastEnumerator as follows:
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
objects:(__unsafe_unretained id [])buffer
count:(NSUInteger)len {
NSUInteger c = 0;
while (c < len) {
id obj = [self objectAtIndex:state->state];
if (obj == nil) break;
buffer[c] = obj;
c++;
state->state++;
}
state->itemsPtr = buffer;
state->mutationsPtr = nil;
return c;
}
If I use objectAtIndex directly, my object works properly. I get a nil when the index doesn't exist. But when I then use the for loop:
for (Pin *pin in coll) { ... }
the code runs through the above function fine and fills in state with what appears to be valid values and returns the number of objects, then I get an EXC_BAD_ACCESS failure at the for statement itself.
What am I doing wrong in this implementation?
I just had a similar issues, and after looking more closely into Apple's FastEnumerationSample, this part (that I had overlooked) jumped at me:
// We are not tracking mutations, so we'll set state->mutationsPtr to point into one of our extra values,
// since these values are not otherwise used by the protocol.
// If your class was mutable, you may choose to use an internal variable that is updated when the class is mutated.
// state->mutationsPtr MUST NOT be NULL.
state->mutationsPtr = &state->extra[0];
The important part being: state->mutationsPtr MUST NOT be NULL. I just used the example line provided and it worked like a charm!
I'm assuming you're using ARC. The problem may be that the buffer is an array of __unsafe_unretained objects, so ARC might be over-releasing them. But what does your objectAtIndex: method look like? This shouldn't be a problem if you are returning objects that are guaranteed to be alive at least as long as your object itself.
Instead of:
id obj = [self objectAtIndex:state->state];
use
__unsafe_unretained id = [self objectAtIndex:state->state];

How to check object is kind of block or not

How can we identify any particular object is kind of block or not?
for example,
NSSet *set =[NSSet setWithObjects:
#"name1",
#"name2",
[^{ /* ..... some code */ } copy],
nil];
How can we find out which object from set is kind of block?
There is a safer way to determine if something is a block without actually using private api or constructing a class using the private string name:
- (BOOL)isBlock:(id)item {
id block = ^{};
Class blockClass = [block class];
while ([blockClass superclass] != [NSObject class]) {
blockClass = [blockClass superclass];
}
return [item isKindOfClass:blockClass];
}
Wrap your block in a class of your own:
BlockWrapper *blockWrapper = [BlockWrapper wrapperWithBlock:^{ … }];
Check for the type and extract the actual block:
if ([obj isKindOfClass:[BlockWrapper class]]) {
codeBlock = [(BlockWrapper*)obj block];
}
There is no supported way to do this. You must keep track of what objects are blocks, and what their type signatures are.
Do you have a practical use case for a set of mixed strings and blocks?
It's possible, but I wouldn't recommend doing this, because NSBlock is not a public class and its name might change in the future:
if ([obj isKindOfClass:NSClassFromString(#"NSBlock")]) {
NSLog(#"It's a block!");
}
If you only have strings and blocks, just check ![thing isKindOfClass:[NSString class]]. i.e. invert your test.
Likewise, if you have strings, numbers and blocks, check that thing is not a string or a number, and in that case it must (by deduction) be a block. Either that, or your program is incorrect and will crash.
I suppose that ![thing isKindOfClass:[NSObject class]], while not technically correct (you don't have to subclass NSObject), will probably get you want you want.