I would like to have a method along the lines of
setData:(SomeClassName *)data inPosition:(NSInteger)position
and in the implementation, check for nil as position. The idea is that if the position is provided, I will use it, and if not, I will allocate it automatically.
The problem is I can't pass either NULL or nil into this without a compiler warning.
I believe I have seen this pattern elsewhere (optional parameters). I think it might have been related to an NSIndexPath.
Should I use an NSNumber as a wrapper? or is there some other secret?
As an aside, I considered using separate methods - setData: and setData:inPosition:. But the problem is that 'data' is a core data created attribute, not a regular ivar, so when I actually want to set the value I would have to remember to send all the KVO messages. For example, inside setData:withPosition, I can't call the standard setData: - it would overwrite any work I did with the position.
Would also be interested in knowing which is the 'better' solution of these two.
#Justin's approach is generally the most appropriate. However, to your question about setData: and KVO, there are several things to note:
KVO notifications are sent automatically as long as the method is named setFoo:. Even if you override setFoo:, KVO will wrap your implementation with the correct KVO notification calls for the property. This is very likely the most magical thing in Cocoa. (I used to be certain it was the most magical thing, but I'm starting to wonder about block variable scoping, and especially how blocks are moved from the stack to the heap; that may be more magical.)
If you need to set a Core Data attribute directly, bypassing KVO and every other piece of possible magic, you can use the primitive accessor. setPrimitiveData: is the underlying method that setData: uses to set the property. You should not override the primitive accessors.
#Justin appears to have deleted his answer. The typical solution here would be to declare setData: and setData:inPosition: (btw, as a reader, I have no idea what "inPosition" means. I hope that it makes sense in context). setData: would call setData:inPosition: applying whatever is necessary to figure out "position."
Using the NSNumber wrapper is pretty standard.
Of course, you could always pass -1, NSNotFound, or define your own n/a value too.
There are three options:
Pass -1 or some such for "no value"
Use an NSNumber wrapper and pass nil for "no value"
Overload
You could try to use the Objective-C optional parameter mechanism, but that requires some sort of sentinel to mark the end of the list, so it's no better than any of the others.
Related
I would like to set a symbolic breakpoint on "objectAtIndex:" method of a specific property in a specific class.
See the following code :
#interface Foo
...
#property (strong,nonatomic) NSMutableArray *fooArray;
...
#end
I 've tried the following things:
-[[Foo fooArray] objectAtIndex:]
-[Foo::fooArray objectAtIndex:]
-[Foo::fooArray objectAtIndex]
Foo::fooArray::objectAtIndex:
Foo::fooArray::objectAtIndex
Foo::fooArray::objectAtIndex()
None of theses solutions work.
Any ideas to do the trick ?
Unfortunately, while this would be useful, it cannot work, for multiple reasons.
The first involves how methods are specified. A method signature for identifying a method in a breakpoint has three parts:
-¹[NSDictionary² objectForKey:³]
+¹[NSString² stringWithContentsOfURL:encoding:error:³]
Is this an instance method (-) or a class method (+)?
Which class's implementation of this method?
What's the selector of this method?
So your first problem is that what you have written for #2 is not a class.
What you do have is a class, followed in some fashion by a property name. This cannot work, because the debugger has no way to know whether that is a pure accessor—it cannot be sure that you, or whoever implemented that property, didn't write a custom accessor that does something else. This means that the debugger has no good, reliable way to obtain that value, or to know when that value changes, without potentially incurring side effects.
Moreover, the role of a class in a method signature is to identify which class provides the implementation you're setting a breakpoint on. That goes out the window as soon as you start trying to refer to a property that holds an object instead, because the debugger needs a class, and will have to get it from the object—and see the previous paragraph for some of the difficulties of knowing which object that is at all times.
(To be fair, it would indeed be possible for the debugger to watch the value of an instance variable—IIRC, both debuggers can already do this in a watchpoint, though reliability of watchpoints was flaky the last time I tried one. If the debugger could translate the property into its backing ivar, if it has one, and watch that, it would be a decent 90% solution for the majority of properties, which aren't backed by imaginative storage implementations and custom accessors. But the debuggers cannot do this today.)
The second reason is that NSArray is a class cluster.
You probably already know the first part of this (I suspect it's why you're trying to specify a single object by a property of another):
NSArray and NSMutableArray are both abstract classes, which in turn means that neither one implements the business of being an array; each one implements a bunch of convenience methods, while leaving a select set of core methods unimplemented, for subclasses to implement.
So, when you create an NSArray, you do not create an NSArray. The object you get back will be an instance of some private subclass of NSArray, with its own implementation of all of the details of how it manages an ordered list of objects.
So you could set a breakpoint on, say, -[NSArray objectAtIndex:], but it would never get hit, because nothing uses NSArray's implementation of objectAtIndex:—it would not make sense to use that implementation, because that implementation raises an exception (intended to catch subclasses that forget to implement it).
The part that breaks your question is:
While NSArray's implementations of various non-essential methods are defined ultimately in terms of the core methods, such as objectAtIndex:, that does not mean that subclasses are bound to use those implementations. A subclass could very well have its own implementations that don't use objectAtIndex:, if objectAtIndex: is not the most efficient way to do what they do (e.g., if the array is backed by a linked list rather than a C array).
So, to summarize this long answer:
It is not possible for the debugger to reliably watch the value of a property.
As such, it is not possible for the debugger to break when a method in the class of the object that is the value of that property is called, because the correct method to set the breakpoint on may change at any time, and the debugger cannot know when that happens.
Even if you could break on objectAtIndex: of some object identified by property, the array may validly never use objectAtIndex:, in which case your breakpoint would never get hit anyway.
You probably should ask another question about whatever you're trying to do by breaking on objectAtIndex:. I assume you're trying to investigate a bug in your app; that bug is probably another interesting question.
After some digging, I found a way to work this out. That's kinda ugly.
It involves creating a conditional breakpoint dynamically, in a command triggered by a first breakpoint.
First, break whenever your fooArray is ready. I settled on the fooArray accessor, but it could be done earlier :
breakpoint set --name "-[Foo fooArray]"
Then, what you want is break when objectAtIndex: is called on this specific array object. First let's put its pointer in a variable :
expr id $watch = self->_fooArray
and then create a new breakpoint, using this variable in the condition :
breakpoint set --name "-[__NSArrayI objectAtIndex:]" --condition "$rdi == $watch"
$rdi contains self, at least on x86_64. Use $r0 on ARM. (See Clark Cox's great post on the topic.)
-[NSArray objectAtIndex:] is never called. As Peter mentioned, NSArray is a class cluster, and your array is actually an __NSArrayI.
Or, in Xcode :
(Don't forget to check the "continue" box.)
It's not really beautiful, but it seems to work !
I am not at my Mac, so I cannot try this myself, but how about:
breakpoint set -n "-[[Foo fooArray] objectAtIndex:]"
I have static global NSNumber value and i need to observe it. If it was member of some object, i would have no problems whatsoever. But what do i do with global scope? I guess i could use
[globalVar addObserver:self forKeyPath:**integerValue** options:... ]
but that seems ugly because i might as well use "intValue" KeyPath and i need to observe NSNumber, not it's int part, even if it's the only part of it i''m using now. Making this particular variable part of some class doesn't seem like a "right" think to do. Thanks!
Easy answer: you can't. Observing is a software mechanism which fundamentally involves method calls, doing a store (i.e. a machine instruction) into a global variable provides no hook to hang the mechanism on.
The best option is to re-think your design. Think of storing the value in a singleton class and accessing/observing it there.
Hard answer: write your own mutable version of NSNumber (an instance of which is immutable) and have this class implement the key-value observing protocol (this class might just be a wrapper with an NSNumber instance variable). Now store and instance of this class in your global variable and add any observers you like to it.
The usual way to do this kind of thing is by making it a value reachable from some globally-available object, such as NSApp, or its delegate.
CRD is right, "In KVO only the property is observed, not the value" Typically dictionaries or custom objects are KVO but not the leaves (values) themselves (numbers, strings). Facing a similar problem, I finally extended the NSNumber class making it KVO compliant.
Now if you are looking for different approaches to achieve notifications in your app, I would strongly suggest to read this article.
The KVC Documentation says
The key-value coding method setNilValueForKey: method is called when you attempt to set an attribute to nil.
Sounds good so far
... uses setValue:forKey: to set the new value. This maintains encapsulation of the model and ensures that any additional actions that should occur as a result of setting the value will actually occur. This is considered better practice than calling an accessor method or setting an instance variable directly.
Why is it better practice to call the -setValue:forKey: inside the -setNilValueForKey: method when setting a 'default' value on a primitive or value type property? Is there a performance or technical advantage to using the KVC method -setValue:forKey: opposed to the property accessor (I'm assuming that when it says accessor method it applies to accessor properties as well since they're just syntatic sugar over the method)? Usually when Apple recommends a 'best practice' there is a performance or reliability concern backing it. Does anybody know a documented reason why?
From your quote:
This maintains encapsulation of the model and ensures that any additional actions that should occur as a result of setting the value will actually occur.
Calling setValue:forKey: instead of an accessor or changing the ivar ensures that all proper side effects are maintained. When the quote mentions maintaining encapsulation, it means staying in KVC methods instead of custom accessors. Calling setValue:forKey: also means that you get the runtime to decide how the property should be set for you. Finally, the "additional actions" is probably referring to key-value observing. It will make sure the right methods are called, and not any that shouldn't be called.
What is better and why ?
What is better in such situations as the class init method and usual variables in a code ?
What is better and why ?
Explicit typing information is always better unless you just can't use it for some reason (see below).
It allows the compiler to much more stringently validate the code and will catch many errors at compile time that would otherwise cause your app to crash at runtime.
A long, long, time ago, everything in the APIs used id. This proved to be a complete pain in the butt; fragile and led to many crashes that would have been caught with specific types.
So, it was changed. (This was ~1994).
What is better in such situations as
the class init method and usual
variables in a code ?
For init, you have no choice but to use the generic (id) return type. Objective-C does not support either co-variant or contra-variant declarations, nor is there a mechanism for generalizing the declaration of init while also providing support for specific type checking.
Same goes for retain, objectAtIndex:, addObject: and many other methods that take or return one of many kinds of objects (or take 'em as arguments).
And, no, there is absolutely no performance difference whatsoever between id and, say, NSView*.
can you give an example when explicit
typing will cause a problem please?
If you wrote:
- (MyClass *) init;
And in a subclass:
- (MySubclass *) init;
You'd get compiler warnings out the wazoo most likely or you'd have to typecast out the wazoo.
On recent versions of clang (in Lion) you should actually not return id, and instead return instancetype. This is a keyword that is used in return types to specify that the type it returns is an instance of the class receiving the message. It is now the preferred return type for init methods on OS X Lion.
Explicit typing provides build-time protection, informing you of likely problems if you do things such as casting or performing operations on something that probably won't work.
Explicit typing also helps prevent non-obvious transfer of mistyped objects, something traveling through a path in your code you hadn't considered that turns out to be of an unexpected type. This kind of bug often doesn't become clear until the program has been tested a lot, more commonly after its release.
It's also helpful for future programmers (including your future self) trying to work with your code, making to more likely that they'll be able to tell at glance what an object is supposed to be. It makes code more "self-documenting" as a result.
Some things cannot have a meaningful type because no type actually applies. Other times you need to use id because you need to be able to accept any type of object. Cocoa Touch uses it, for example, when referring to the sender of a message because anything could have sent it; specifying an explicit type simply wouldn't work.
The vast majority of the time, though, an explicit type is to your advantage.
Use a type as specific as you can but not more so. Consider how you are using any particular variable, argument, or return type and set its type appropriately.
For example a UITableView's dataSource property is declared as id<UITableViewDataSource> because the table view only cares that its data source is some object which conforms to the UITableViewDataSource protocol. This allows the data source to be flexible enough for use with any specific class which implements the protocol but still allows the compiler to warn you if you attempt to assign an object which does not implement that protocol as the data source.
If you are too specific then your code becomes inflexible, accepting only specific implementations which are not strictly necessary (ie demanding a NSMutableString when you could really work with any NSString).
If you are too vague (typing everything as id for example) then you lose the ability to identify when you are sending unrecognized selectors to a particular instance and the compiler cannot identify any number of invalid statements.
For init methods follow the advice in The Objective-C Programming Language
The return type of an initializer method should be id.
The reason for this is that id gives an indication that the class is purposefully not considered—that the class is unspecified and subject to change, depending on context of invocation. For example, NSString provides a method initWithFormat:. When sent to an instance of NSMutableString (a subclass of NSString), however, the message returns an instance of NSMutableString, not NSString. (See also, though, the singleton example given in “Combining Allocation and Initialization.”)
I don't think there is a performance difference between both.
You can let id return type for init because you can cast the result of your init.
For exemple :
Toto *foo = [[Toto alloc] init];
id foo2 = [[Toto alloc] init];
Both work but you'll have to cast foo2 variable like that (Toto *)foo in order to access property or methods of your instance without creating a compiler warning. Even if it works fine...
I think some developers let id because they just pass there variable trough instance and don't use it. That kind of use allow to not import the .h
Regards,
KL94
I tried to figure out this code referencing: Cocoa: Dictionary with enum keys?
+ (NSValue*)valueWithReference:(id)target
{
return [NSValue valueWithBytes:&target objCType:#encode(id*)];
}
And,
[table setObject:anObject forKey:[NSValue valueWithReference:keyObject]];
But it feels something not good. Any recommendations?
You're absolutely right it's not good.
For one, you're encoding the wrong type (it should be #encode(id), not #encode(id*)), but in most cases this shouldn't cause a big problem.
The bigger problem is that this completely ignores memory management. The object won't be retained or copied. If some other code releases it, it could just disappear, and then your dictionary key will be a boxed pointer to garbage or even a completely different object. This is basically the world's most advanced dangling pointer.
You have two good options:
You could either add NSCopying to the class or create a copyable subclass.
This option will only work for objects that can meaningfully be copied. This is most classes, but not necessarily all (e.g. it might be bad to have multiple objects representing the same input stream)
Implementing copying can be a pain even for classes where it makes sense — not difficult, per se, but kind of annoying
You could instead create the dictionary with the CFDictionary API. Since Core Foundation types don't have a generic copy function, CFDictionary just retains its keys by default (though you can customize its behavior however you like). But CFDictionary is also toll-free bridged with NSDictionary, which means that you can just cast a CFDictionaryRef to an NSDictionary* (or NSMutableDictionary*) and then treat it like any other NSDictionary.
This means that the object you're using as a key must not change (at least not in a way that affects its hash value) while it's in the dictionary — ensuring this doesn't happen is why NSDictionary normally wants to copy its keys
For the later reference.
Now I know that there are some more options.
Override methods in NSCopying protocol, and return the self instead of copying itself. (you should retain it if you are not using ARC) Also you ensure the object to always return same value for -hash method.
Make a copyable simple container class holds strong reference to the original key object. The container is copyable but, it just passes original key when it being copied. Override equality/hash methods also to match semantics. Even just an instance of NSArray contains only the key object works well.
Method #1 looks pretty safe but actually I'm not sure that's safe. Because I don't know internal behavior of NSDictionary. So I usually use #2 way which is completely safe in Cocoa convention.
Update
Now we Have NSHashTable and NSMapTable also in iOS since version 6.0.
I'm not 100% sure about the correctness of this solution, but I'm posting it just in case.
If you do not want to use a CFDictionary, maybe you could use this simple category:
#implementation NSMutableDictionary(NonCopyableKeys)
- (void)setObject:(id)anObject forNonCopyableKey:(id)aKey {
[self setObject:anObject forKey:[NSValue valueWithPointer:aKey]];
}
- (id)objectForNonCopyableKey:(id)aKey {
return [self objectForKey:[NSValue valueWithPointer:aKey]];
}
- (void)removeObjectForNonCopyableKey:(id)aKey {
[self removeObjectForKey:[NSValue valueWithPointer:aKey]];
}
#end
This is a generalization of a similar method I saw online (can't find the original source) for using an NSMutableDictionary that can store objects with UITouch keys.
The same restriction as in Chuck's answer applies: the object you're using as a key must not change in a way that affects its hash value and must not be freed while it's in the dictionary .
Also make sure you don't mix -(void)setObject:(id)anObject forNonCopyableKey:(id)aKey and - (id)objectForKey:(id)aKey methods, as it won't work (the latter will return nil).
This seems to work fine, but there might be some unwanted side effects that I am not thinking of. If anybody finds out that this solution has any additional problems or caveats, please comment.