What is this syntax when I was attempting to override a getter??
I'm just messing around trying to learn more about how properties work in Objective-C. Here is my property:
#property (nonatomic, strong) UIView *myView;
When I try to override the getter I get this help:
-(void)getMyView:(<object-type> **)buffer range:(NSRange)inRange
{
}
I know I can use this:
-(UIView *)myView
{
}
But I am just curious as to what the previous method does, why it's there, etc. Thanks for any help!
It's called "Getter Indexed Accessors" as explained in the Key-Value Coding Programming Guide
From the documentation:
In order to support read-only access to an ordered to-many relationship, implement the following methods:
-countOf<Key> Required. This is the analogous to the NSArray primitive method count.
-objectIn<Key>AtIndex: or -<key>AtIndexes: One of these methods must be implemented. They correspond to the NSArray methods objectAtIndex: and objectsAtIndexes:
-get<Key>:range: Implementing this method is optional, but offers additional performance gains. This method corresponds to the NSArray method getObjects:range:.
You can implement such methods for performance reasons, as explained in the guide
If benchmarking indicates that performance improvements are required, you can also implement -get<Key>:range:. Your implementation of this accessor should return in the buffer given as the first parameter the objects that fall within the range specified by the second parameter.
As an example
- (void)getEmployees:(Employee * __unsafe_unretained *)buffer range:(NSRange)inRange {
// Return the objects in the specified range in the provided buffer.
// For example, if the employees were stored in an underlying NSArray
[self.employees getObjects:buffer range:inRange];
}
Related
We have a weird memory leak, but since the code is closed source I can't just post the code so I'll do my best to make sure the important bits are available.
Disclaimers:
I can't post the complete backtrace, but if you want to see it I'll do my best to produce an obfuscated version
I can't post complete class definitions, but I am including the parts that have been run in this scenario, obfuscated.
What I hope to learn
I want to know why this happens, not get a solution. Or perhaps when I know what happens, I'll know how to better solve it if there's a better way than making them lazy.
Problem
These default values leak
Pricing:
#objcMembers
class Pricing: Mappable {
var price: Money = Money.zero()
var vat: Percent = Percent.zero()
...
}
Some related information
These two properties leak. From what I can gather, these instances of zero are immediately lost as our ObjC interface Mappable has a category called Mappable+JSONMappings which provides a default implementation of our JSON deserialisation initialised, initWithJSON:, in Objective C for all objects that implement Mappable. This means that all you have to do is claim to implement it, and then you get this initialiser which is then called by our deserialiser, magic!
However, we get two separate leaks every time we deserialise this Pricing object. One for the Money class and its internal NSDecimalNumber and one for Percent. Fixing Money fixes NSDecimalNumber. This is consistent and they leak the exact same way when I look at the memory graph.
Mappable was originally used only by our ObjC models, as our Swift models we had up until this point were structs that implemented Codable to achieve the same result, just using JSONDecoder. This model had to be used in the legacy parts of our system and thus needed to also use Mappable, but we went with Swift in order to use Swift features not available in ObjC, such as enum Enum: String and such, which are used internally by Pricing for whatever reasons.
Money.m:
#interface Money()
#property (nonatomic, strong) NSDecimalNumber *value;
#property (nonatomic, strong) NSString *currencyCode;
#end
#implementation Money
+ (instancetype)zero {
return [Money initWithDecimal:[#(0) decimalValue]];
}
+ (instancetype)initWithDecimal:(NSDecimal)decimal {
return [[self alloc] initWithDecimal:decimal];
}
- (instancetype)initWithDecimal:(NSDecimal)value {
return [self initWithDecimal:value currency:[[CurrencySettings getInstance] getCurrency]];
}
- (instancetype)initWithDecimal:(NSDecimal)value currency:(NSString *)currencyCode {
self = [super init];
if (self) {
_currencyCode = currencyCode;
_value = [NSDecimalNumber decimalNumberWithDecimal:value];
}
return self;
}
#end
I have found a method which is called frequently in our internal JSON deserialisation implementation. It builds our data recursively using this NSObject method:
[self setValue:value forKey:key]
TL;DR;
We have an internal ObjC JSON deserialisation layer that through magic implements default methods for things implementing an interface. This calls on the following method frequently:
[self setValue:value forKey:key]
[NSObject setValue: forKey:]
According to the docs it says the following:
If key identifies a to-one relationship, relate the object specified by value to the receiver, unrelating the previously related object if there was one. Given a collection object and a key that identifies a to-many relationship, relate the objects contained in the collection to the receiver, unrelating previously related objects if there were any.
The search pattern that setValue:forKey: uses is described in Accessor Search Patterns in Key-Value Coding Programming Guide.
In a reference-counted environment, if the instance variable is accessed directly, value is retained.
Debugging and tracing
We have Automatic Reference Counting (ARC) enabled on the target and right now these are the only leaks we have currently in a pretty big project, and the usage of Money.zero() is used elsewhere very frequently as well, indicating it is not actually a problem with the Money class itself.
The memory graph for Money is not very informative and displays only this:
The graph for NSDecimalNumber shows that Money is at fault, though:
Inspecting the graph for Percent will show the same sort of relationship.
Making the properties lazy
A workaround is to make the properties lazy. It does not give us any insights as to why it happened though, so this is why I am posting here.
#objcMembers
class Pricing: Mappable {
lazy var price: Money = Money.zero()
lazy var vat: Percent = Percent.zero()
...
}
I'm trying to understand some theory part in Objective C related to KVC. Following is the example I've done.
I'm having class call Cookie and it has a property like below
#property NSString *name;
Next, I have another class call Person and it has following property
#property Cookie *cookie;
Inside Person implementation file
#import "Cookie.h"
- (id)init
{
self = [super init];
if (self) {
_cookie = [[Cookie alloc] init];
}
return self;
}
In my ViewContrtoller I can write following two options to get the same result.
Using KVC :
[me valueForKeyPath:#"cookie.name"]
Using accessor methods :
[[me cookie] name]
To write accessor method , I had to import the Cookie class but doesn't need when using KVC.
Apart from that, what are the benefit of using KVC instead or using accessor methods? Is there any performance issue or security issue or good coding practice or any other benefit?
One situation where i found KVC very handy was when i had to perform some kind of operation on a collection object such as finding the average of a particular value.Specifically I used KVC operators.
For example
[myDict valueForKey:#"gamePoints"] valueForKey:#"doubleValue"] valueForKeyPath:#"#max.self"];
This will help you find the maximum value for the property 'gamePoints' from among an array of dictionaries/ objects.
Here is an excellent article by Mattt Thompson
Hope this contributes to what you are looking for.
There's no particular benefit in this case to using KVC. In general, you should prefer to use the accessors or dot syntax (e.g. me.cookie.name) when you can.
KVC is for when the name of the property you want to access is dynamic. It's not known at compile time. It comes from data (including a NIB, in the case of bindings on OS X) or is computed.
According to the Apple Docs:
Though key-value coding is efficient, it adds a level of indirection that is slightly slower than direct method invocations. You should use key-value coding only when you can benefit from the flexibility that it provides.
But I think this is probably a little over-cautious; I doubt you need worry too much unless your app is very performance sensitive.
Beside the given answers (+1) you get the advantage of identifier completion in Xcode which reduces the probability of typos. Importing the class is a good strategy, if you use it semantically. Look at it as a "bill of things I use", which can be helpful for understanding your code.
Great place to use KVO is unit testing. When you have following class interface:
#interface ServerCommunicationManager : NSObject
{
NSMutableArray *commandQueue;
BOOL chanelFree;
}
- (void)send:(NSDictionary *)dictionary;
#end
And then send implementation:
- (void)send:(NSDictionary *)json
{
if ( YES == chanelFree ) {
// send command immediately
} else {
[commandQueue addObject:json];
}
}
If we want to test send implementation without exposing commandQueue(hence without braking encapsulation) we could get use of KVO:
-(void)testSend
{
ServerCommunicationManager* aTestObj = [ServerCommunicationManager new];
//prepare conditions
[aTestObj setValue:#NO forKey:#"channelFree"];
NSDictionary* dummyReq = #{};
[aTestObj send:dummyReq];
//check commandQueue state
XCTAssertEqualObjects(dummyReq, [[aTestObj valueForKey:#"commandQueue"] firstObject]);
XCTAssertTrue(1 == [[aTestObj valueForKey:#"commandQueue"] count]);
//more tests
}
KVC allows you to do KVO: That is, if you are observing a variable, you will only be notified of its changes if and only if the changes take place using KVC. If you modify a variable directly using its setter you are not going to be notified of its changes
So I want to have a "property" on a class but I don't want to just hold that property in memory, I want to actually store it as an NSUserDefault and retrieve it when you get that property.
So as such I have methods like this:
- (void)setUser:(User *)user {
// actually set the user as an NSUserDefault here
}
- (User *)user {
// get the user from the NSUserDefaults and return it
}
As I'm building these methods to do the work for me is there any point in having an #property declaration in the header file?
I'm getting mixed messages. Some people say that you should declare the property to force people to use the getter/setter methods, but I can't see why people wouldn't be forced to use those methods if they're all that are available?
Just looking for a bit of clarification.
Many thanks.
You should use #property because that's the modern way to define properties on Objective-C objects, even if you implement the setter and getter yourself.
Rather than relying on convention you are making your intentions much clearer to the compiler. You will also get better syntax highlighting when using dot-notation in the IDE (although that's arguably an Xcode bug).
This is an observation and a question:
I am loading some json data into a class (json already converted into an NSDictionary). The values will be read-only from the outside:
#interface Checklist
-(id)initWithJSON:(NSDictionary *)json;
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
etc....
#end
With the corresponding method bodies in the .m file.
As a test, I created a class for another data element:
#interface ChecklistItem
-(id)initWithJSON:(NSDictionary *)json;
#property (readonly) NSInteger item_id;
#property (readonly) NSString *item_name;
#end
Functionally, the two classes have similar methods in the #implementation. In both cases they basically pull the appropriate value from the json and return the result. And as far as the rest of the program was concerned, the two approaches seem to be interchangeable.
So my question is:
Which approach is the best one to use?
I find either way equally readable and so far I can not find any code-reason to prefer one way over the other. I can kind of see the second option as nice since it kind-of documents the json.
You should use properties, they come in handy once you use KVO.
Also you can define public readonly properties and overwrite them in a class extension with a readwrite property that is only usable in the same class. If you try to achieve something similar you will have to deal with private helper methods — the code gets ugly.
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
This isn't standard Objective-C naming. If you want to do things properly, follow the platform conventions. Apple document this in their coding guidelines documentation.
Which approach is the best one to use?
They are equivalent as far as Objective-C is concerned. The property syntax expresses your intent at a higher level than manually creating the methods, so I would prefer that approach. It's also less code.
This is less important now that ARC will clean up memory which would have been managed
inside the setter but this is still very much best practice. The performance overhead of
calling a setter method is also negligible compared to the safety gained from always
going through the setter.
this is a subjective question and you'll get nothing but opinions back, but here is mine:
the read only properties will just write the getters for you. if you don't write a private read write propertly in your .m file or wherever and just set the ivar's directly you don't even get the will/did change value for key calls and will have to call those yourself also.
#interface ChecklistItem ()
#property (readwrite) NSInteger item_id;
#property (readwrite) NSString *item_name;
#end
To access them KVO complient inside the object you'll have to do:
self.item_id = 13;
And not:
_item_id = 13;
Of course you could just have getter methods:
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
And just wrap all changes in in your KVO methods:
[self willChangeValueForKey:#"checklist_id"];
_item_id = 13;
[self didChangeValueForKey:#"checklist_id"];
it's just a coding style choice, and sometimes leveraging what the compiler will write for you. but either option works the same.
If the values are read only, I'd think you'd want them as methods rather than as read-only properties to avoid any confusion that the values might be able to be set. Unless of course you want the subscribers to be able to use the dot notation for accessing the properties, but if you're just returning the values in the NSDictionary, the method form would be better as you're not keeping around another copy of the data.
Are there side-effects to calling a custom getter with dot notation?
I had been using a synthesized getter in Objective-C via the dot notation, i.e.
tree.fruitnumber
returned the number of fruits in tree. I had to customize the getter (for reasons not pertinent to this question). I wrote it as
-(int) fruitnumber
{
//climb into tree and hand count fruits. Get n;
return n;
}
Suprisingly, the dotted getter still works. Is this legit, or there is a nasty bug (which will infect all my fruits down the road (to the market?)).
Dot notation is really just syntactic-sugar for bracket notation. So both messages are the same:
int x = [self fruitNumber];
int x = self.fruitNumber;
The nice thing is, you can #synthesize your properties and the setter/getter methods will be built for you (depending on your property options, of course) but you can write your own instead and they will be used.
In the case where you are providing your own setters/getters, you can alternatively use the #dynamic propertyName line instead of #synthesize to tell the compiler these are being provided by you.
There's are some side effects that no one has mentioned:
Atomicity - if you don't declare a property as nonatomic, then (by default) it is an atomic property, which means that the value of the property will be full retrieved regardless of what other threads might be doing to mutate the property at the same time. If you have an atomic property and then override the getter or setter, you lose the atomicity (unless you implement it yourself).
Key-Value observation - by using the #synthesized methods, you are ensuring KVO compliance, which makes it very easy to observe values of the object as they change (and be notified of such changes). If you override the synthesized methods, you risk breaking that compliance.
So it is generally safe to override synthesized getters and setters, but there are caveats, and it is very important that you understand what they are so that if/when things break, you know why.
You can specify a custom getter when declaring the property, i.e.:
#property (readwrite, getter=numberOfFruitsCountedByTheCustomGetter) int fruitnumber;
In your implementation, synthesize it as usual:
#synthesize fruitnumber;
Then implement the getter:
- (int) numberOfFruitsCountedByTheCustomGetter {
return fruitnumber;
}
It doesn't matter whether you write the getter or it is synthesized, it gets called when you use the dotted notation (or the bracket notation). This is the way it is supposed to work.
The dot notation is just shorthand for calling the getter or setter method. There is no difference beyond how it looks.
A common side effect used in getters is a lazy getter.
-(id) something {
if ( nil == something ) {
something = ...;
}
return something;
}
A getter does not have to be related to a specific member. It can return the result of a calculation or lookup, or pass on something from a member object.
Progrmr is correct. However I'd consider putting in the #dynamic declaration to explicitly tell the compiler you are creating the getter. Here's a link to the documentation om properties. It's worth a wad if you have had a chance.
http://developer.apple.com/mac/library/iPad/index.html#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html