Whats the difference between "-" in - (void) and "+" in + (id) or + (scene) for Objective-c? - void

As the question stated, I was confusing what the symbol - and + mean when writing a method?
Thanks

"-" means instance method
"+" means class method
For e.g. NSNumber class defines several initializers, including:
- (id)initWithInt:(int)value;
+ (NSNumber *)numberWithInt:(int)value;
First one is instance method second one is class method.
NSNumber *magicNumber = [[NSNumber alloc] initWithInt:42];
NSNumber *magicNumber = [NSNumber numberWithInt:42];
Regarding "id"
+ (id)alloc;
This is a special keyword used in Objective-C to mean “some kind of object.” It is a pointer to an object, like (NSObject *), but is special in that it doesn’t use an asterisk.
Refer https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW7

Related

NSTreeController - Retrieving selected node

I added Book object in bookController (NSCreeController). Now i want to get stored Book object when i select the row.
- (IBAction)addClicked:(id)sender {
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
// NSTimeInterval is defined as double
NSUInteger indexArr[] = {0,0};
Book *obj = [[Book alloc] init];
NSString *dateString = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterLongStyle];
obj.title = [NSString stringWithFormat:#"New %#",dateString];
obj.filename = [NSString stringWithFormat:#"%d",arc4random()%100000];
[self.booksController insertObject:obj atArrangedObjectIndexPath:[NSIndexPath indexPathWithIndexes:indexArr length:2]];
}
I concede there perhaps could be a better solution--
I am unfamiliar with how NSTreeController works, but I looked a the class reference and noticed that it has a content property, similar to an NSArrayController (Which I am familiar with grabbing specific objects from).
I believe that if the content property is actually of type of some kind of tree data structure, my answer here probably won't work. The class reference says this about content:
The value of this property can be an array of objects, or a
single root object. The default value is nil. This property is
observable using key-value observing.
So this is what I historically have done with the expected results:
NSString *predicateString = [NSString stringWithFormat:NEVER_TRANSLATE(#"(filename == %#) AND (title == %#)"), #"FILENAME_ARGUMENT_HERE", #"TITLE_ARGUMENT_HERE"];
NSArray *matchingObjects = [[self content] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:predicateString]];
Then simply calling -objectAtIndex: will grab you your object. Note that the NSArray will be empty if the object doesn't exist, and if you have duplicate objects, there will be multiple objects in the array.
I also searched for an answer to your question, and found this SO thread:
Given model object, how to find index path in NSTreeController?
It looks pretty promising if my solution doesn't work, the author just steps through the tree and does an isEqual comparison.
If you could (if it's not too much trouble), leave a comment here to let me know what works for you, I'm actually curious :)

Content of a NSMutableDictionnary erratically returned

I am trying to add keys in a dictionnary in Objective-C. The code is as follows :
I have a class MyClass whose header file contains :
#property (nonatomic) NSMutableDictionary *dict;
This gets initialized as follows :
_dict = [[NSMutableDictionary alloc] init];
Then I try to add keys to it :
- (void) addOrModify:(myKey*) key withValue:(myValue *) value {
[self.dict setObject:value forKey:key];
NSLog(#"Adding the key %# %p with value %# %p",[key description],key,[value description],value);
NSLog(#"%#",[self.dict description]);
}
And here is what I get upon adding different key/values :
Adding the key (key1) 0x7f9dc3590070 with value (value1) 0x7f9dc358e760
{
"(key1)" = "(value1)";
}
Adding the key (key2) 0x7f9dc357adc0 with value (value2) 0x7f9dc357de20
{
"(key2)" = (null);
"(key1)" = "(value1)";
}
Adding the key (key3) 0x7fa4d2cbdbd0 with value (value3) 0x7fa4d2d53cf0
{
"(key3)" = "(value3)";
"(key2)" = "(value2)";
"(key1)" = "(value1)";
}
Now if I take a look into the actual content of the dictionary with XCode's debugger, I find that all pairs key/value are present as they should. So it seems that the description method of dict fails to print correctly the value of some keys. The same happens without using NSLog but displaying the content of the dictionary in a UITable. Also note that if I try to log the address of the value for these particular keys, it also gives me 0x0 (so my description function is not at fault).
Note that the behavior is rather chaotic, sometimes several values are set to nil, then they appear correctly after I have added a few more pairs of key/values. I really can't get my head around this problem, any help would be much appreciated.
Edit 1
The interface of my keys
#interface myKey : NSObject <NSCopying>
#property(nonatomic, copy) NSString *myKeyName;
#property(nonatomic) float myKeyFloat;
#property(nonatomic, readonly, strong) NSDate *dateCreated;
The interface of my values:
typedef NS_ENUM(NSInteger, Unities) { g, kg, };
#interface myValue : NSObject
#property(nonatomic) float myValueFloat;
#property(nonatomic) Unities myValueUnit;
Calling code
- (IBAction)addKeyValue:(id)sender {
myValue *value = [myValue randomValue];
myKey *key =[[CatalogKeys sharedCatalogKeys]
getRandomKeyFromStore]; [self.dict addOrModify:key withValue: value];
}
where randomValue just set myValueUnit to 'g' and puts a random float in myValueFloat
This is a guess:
The information supplied does not show that your type myKey implements isEqual: and hash. Keys must implement these methods to work correctly in an NSDictionary; if they are not implemented the default NSObject implementations will be used and they probably do not produce the correct results for instances of myKey.
You also indicate that using the description of your myKey instances does work, this makes sense as description returns an NSString and that type implements isEqual: and hash.
HTH

How to return a primitive property value with CALayer's "+ (id) defaultValueForKey", etc?

So.. CALayer KVC "extensions" handle all the weirdo's... such as..
+ (id) defaultValueForKey: (NSString*)key {
return [key isEqualToString:#"borderColor"]
? (id)cgPINK
: [super defaultValueForKey:key]; }
And Apple's Docs allude to how best to encode a struct, when they refer to the default value if you DON'T provide a value...
For example, if the value for key is a CGSize struct, the method returns a size struct containing (0.0,0.0) wrapped in an NSValue object.
However, I can't figure out how to provide normal, stinking, primitives, i.e. CGFloat
I've tried #VAL-type NSNumber encoding,
return ![key isEqualToString:#"lineWidth"] ?: #3;
and with no viable NSValue methods, even a desperate attempt to cast them to id
return ![key isEqualToString:#"zPosition"] ?: (id)262453;// lol
What's the deal? Is this just an "oh-well, ya can't" situation due to CALayer's odd-ball nature? An obvious solution I have embarrassingly overlooked? Or is it just a shady API - that refuses to document it's own shortcomings?
You should be able to return an NSNumber.
I haven't yet tried using Objective C literals. Skip that for now to limit the complications. Just use code like this:
return [NSNumber numberWithFloat: 3.0];
or numberWithBool, or numberWithInt, or whatever is appropriate.

analyze and memory alerts in xcode

I ran 'analyze" in xcode on a current iOS project to try to track down a freeze issue and there are a number of memory alerts that I don't understand (screenshot of one below).
What is going on there: I have a custom ObjC class extending NSObject; in the init method I alloc/init an NSMutableArray and then in a loop, populate it with NSMutableArrays. This nested array is declared as a property and released in dealloc(). It lives for the life of the app.
Am I doing this wrong? I don't understand the alert#3: # object not referenced in this execution path and has a retain count of +1.
Since my class allocs the outer array, it owns it and will clean it up. Do the inner arrays need to be released?
Thanks for any tips - still new at this.
EDIT/ADDITION
Trying to stamp out the additional memory warnings I am getting so I thought I would add to the question here in the event someone stumbles upon this w/ the same issue.
I am getting the following alert with the code below (the 2nd line "[keyArray addObject: etc"). What is going on: I have a custom class (Key - based on NSObject) that I instance and store in an array. Based on answers to my previous question, I guess my alloc increases the retain count and then when it is added to the array, the retain count isn't decremented - so the memory warning occurs.
What is the proper way to handle something like this? Use a placeholder like this:
Key * k = [[Key alloc] initKeyWithPath:path isBlackKey:NO]];
[keyArray addObject: k];
[k release];
Is that the proper way to do it? Or is there I way to write the custom class to return an autoreleased obj? (thanks and sorry to be so long winded!).
Potential leak of an object allocated on line 460
Method returns an Objective-C object with a +1 retain count (owning reference)
Object allocated on line 460 is not referenced later in this execution path and has a retain count of +1 (object leaked)
-(void) addOctaveToArraysWithTransform:(CGAffineTransform*)trans andPath: (CGMutablePathRef) path
{
path = [self createCF_keyUsingTransform: trans];
[keyArray addObject:[[Key alloc] initKeyWithPath:path isBlackKey:NO]];
}
Key.h
#import <Foundation/Foundation.h>
#import "Key.h"
#interface Key : NSObject {
#public
CGMutablePathRef keyPath;
BOOL isBlackKey;
NSValue * path;
int keyState;
BOOL needsRedraw;
}
#property (nonatomic, assign) int keyState;
#property (nonatomic, assign) BOOL needsRedraw;
#property (nonatomic) CGMutablePathRef keyPath;
-(id) initKeyWithPath:(CGMutablePathRef) aPath isBlackKey:(BOOL)flag;
-(CGMutablePathRef) getKeyPath;
#end
Key.m
#import "Key.h"
#implementation Key
#synthesize keyState, needsRedraw, keyPath;
-(id) initKeyWithPath:(CGMutablePathRef) aPath isBlackKey:(BOOL)flag
{
if ((self = [super init])){
isBlackKey = flag;
keyState = 0;
needsRedraw = NO;
keyPath = aPath;
CGPathRetain(keyPath);
}
return self;
}
-(CGMutablePathRef) getKeyPath
{
return keyPath;
}
#end
Yes, you have to release the inner arrays to balance the alloc/init. Remember the outer array will retain each inner array, and the outer array will presumably release those later. But here you are still responsible for the alloc/init you just did.
Hope that helps.
You have an allocation of an NSMutableArray on each iteration of the for-loop. Instead use: NSMutableArray array] which is a convenience method that return an autoreleased NSMUtableArray suitable for adding to fieldNotes which will retain the NSMutableArray.

NSMutableString and setting up accessor methods Objective-C 2.0

There is a copy attribute for synthesised accessor methods ex:
#property (copy) NSMutableString *string;
When assign using this setter method it seems to always call the copy method, even though I would like to create a mutable copy of what ever I assign to string, during assignment of the instance variable string.
Is this a know issue and are there any workarounds?
Thanks :-)
Don't call #synthesize string in your .m implementation file and instead write your own getter.
e.g.
- (NSMutableString *) string
{
NSMutableString * stringToReturn = [NSMutableString stringWithString: someStringObject];
}
More information about properties (and what to do when you don't do #synthesize) can be found at:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
p.s. the property name "string" may be confusing to anyone else who looks at your code down the road... I'd recommend changing that to be more program-specific

Resources