Re: NSDictionary trouble
On Jan 20, 2010, at 5:22 AM, Jens Miltner wrote: > Am 20.01.2010 um 11:34 schrieb Jeremy Pereira: > >> On 19 Jan 2010, at 23:06, Jens Alfke wrote: >> >>> On Jan 19, 2010, at 10:46 AM, Kirk Kerekes wrote: >>> NSDictionary will use almost any object as a key: From the docs: "In general, a key can be any object (provided that it conforms to the NSCopying protocol...)" -- and if it is an immutable object, that -copy is just a -retain. >>> >>> Yes, but he said he wants to use a view as the key. Views are not >>> immutable, and do copy themselves in response to -copy. Having a dictionary >>> whose key objects are copies of your live views is not very useful. >>> (Especially since the copied view will have a different hashcode from the >>> original one, so you can't even look it up using the original view >>> anymore...) >> >> Well he could write a category to give him an object that satisfies all the >> criteria e.g (written in Mail). >> >> >> @interface NSView(DictionaryKey) >> >> -(NSNumber*) dictionaryKey; >> >> @end >> >> @implementation NSView(DictionaryKey) >> >> -(NSNumber*) dictionaryKey >> { >> return [NSNumber numberWithUnsignedLongLong: (unsigned long long) self]; >> } > > Slightly safer (because it does not make explicit assumptions about pointer > sizes): > > -(id) dictionaryKey > { > return [NSString stringWithFormat:@"%p", self]; > } > > > Sorry, couldn't resist ;-) Um, if you're going to go that route, use +[NSValue valueWithNonretainedObject:]. Playing with strings or NSNumbers is doing it the hard way. But, if you can use it, NSMapTable (as mentioned previously) is probably more appropriate. Regards, Ken ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
Am 20.01.2010 um 11:34 schrieb Jeremy Pereira: On 19 Jan 2010, at 23:06, Jens Alfke wrote: On Jan 19, 2010, at 10:46 AM, Kirk Kerekes wrote: NSDictionary will use almost any object as a key: From the docs: "In general, a key can be any object (provided that it conforms to the NSCopying protocol...)" -- and if it is an immutable object, that -copy is just a -retain. Yes, but he said he wants to use a view as the key. Views are not immutable, and do copy themselves in response to -copy. Having a dictionary whose key objects are copies of your live views is not very useful. (Especially since the copied view will have a different hashcode from the original one, so you can't even look it up using the original view anymore...) Well he could write a category to give him an object that satisfies all the criteria e.g (written in Mail). @interface NSView(DictionaryKey) -(NSNumber*) dictionaryKey; @end @implementation NSView(DictionaryKey) -(NSNumber*) dictionaryKey { return [NSNumber numberWithUnsignedLongLong: (unsigned long long) self]; } Slightly safer (because it does not make explicit assumptions about pointer sizes): -(id) dictionaryKey { return [NSString stringWithFormat:@"%p", self]; } Sorry, couldn't resist ;-) ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On 19 Jan 2010, at 23:06, Jens Alfke wrote: > > On Jan 19, 2010, at 10:46 AM, Kirk Kerekes wrote: > >> NSDictionary will use almost any object as a key: >> >> From the docs: >> "In general, a key can be any object (provided that it conforms to the >> NSCopying protocol...)" >> >> -- and if it is an immutable object, that -copy is just a -retain. > > Yes, but he said he wants to use a view as the key. Views are not immutable, > and do copy themselves in response to -copy. Having a dictionary whose key > objects are copies of your live views is not very useful. (Especially since > the copied view will have a different hashcode from the original one, so you > can't even look it up using the original view anymore...) Well he could write a category to give him an object that satisfies all the criteria e.g (written in Mail). @interface NSView(DictionaryKey) -(NSNumber*) dictionaryKey; @end @implementation NSView(DictionaryKey) -(NSNumber*) dictionaryKey { return [NSNumber numberWithUnsignedLongLong: (unsigned long long) self]; } @end Then he could do things like: [myDictionary setObject: foo forKey: [myView dictionaryKey]]; ... bar = [myDictionary objectForKey [myView dictionaryKey]]; The above creates a key based on the address of the NSView. > > —Jens___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > http://lists.apple.com/mailman/options/cocoa-dev/adc%40jeremyp.net > > This email sent to a...@jeremyp.net __ This email has been scanned by the MessageLabs Email Security System. For more information please visit http://www.messagelabs.com/email __ ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 10:47 PM, Jeff Laing wrote: > I'm assuming you are saying 'don't use the convenience methods because the > autorelease pool won't empty quickly enough'. Certainly Ken said it, though > he seemed to assume that there was only one pool, that people would not be > creating their own in their known trouble-spots. I didn't make that assumption. In fact, you quote me below referring to the "current pool". The word "current" is in there specifically because I kept the possibility of nested pools in mind. I also didn't say "don't use ...". I was explaining Apple's recommendation, to the best of my understanding. > Ken Thomases wrote: >> The autorelease pool is convenient and in some cases necessary, but it >> does come at some cost. It has some overhead in terms of time and >> memory, plus it tends to increase the peak memory usage of your >> program. (Over time, assuming you've got all your memory management >> correct, a program's memory usage will come out the same, but >> autoreleased objects accumulate over the lifetime of the current pool, >> causing spiky memory usage.) > > But implicit in that seems to be that -[NSDictionary initWithObjectsAndKeys:] > won't add to the auto-release pool and I don't see where that's a valid > assumption (or at least a documented assumption). I didn't make that assumption, either, and you're correct that doing so is unsupportable. However, the choice you make about which methods to invoke imposes restrictions on the frameworks. If you use convenience constructors, you're essentially requiring the use of autoreleased objects. (Obligatory caveat: not all results from convenience constructors are necessarily autoreleased. This discussion is about those cases where they are.) If you use alloc+init, you at least allow the frameworks to minimize use of autoreleased objects. Whether or not the frameworks take the opportunity is beyond your control or caring. Given that it's Apple who are making the recommendation, one can hope the frameworks are coded to follow it. I also pointed out that this is a matter of judgments about trade-offs and a recommendation (not a rule) particular to a highly-constrained environment. Personally, I don't develop for the iPhone and so the memory usage side of that tradeoff doesn't weigh as heavily for me. Cheers, Ken ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 8:47 pm, Jeff Laing wrote: > I wrote: >>> No, you should just *retain* the result of dictionaryWithCapacity. > > mmalc wrote: >> No, you shouldn't. > With all due respect, why not? > Because it's difficult to imagine a common situation in which your advice will be valid, for example: NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:x]; // Add to the dictionary. myInstanceVariable = [dict retain]; Wrong, because you're setting an instance variable directly instead of using an accessor. NSMutableDictionary *dict = [[NSMutableDictionary dictionaryWithCapacity:x] retain]; // Use the dictionary. [dict release]; Retaining the dictionary is pointless. > Apple gives us all those convenience methods but you say we shouldn't use > them? > Please don't misrepresent what I wrote. I didn't say that. There are situations in which the convenience API is useful and not discouraged. In particular, for example, if you're creating a dictionary as a return value from a method, then it's perfectly reasonable to use a convenience method: - (NSDictionary *)dictionaryRepresentation { NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:5]; // Use the dictionary. return dict; } (Also if you're using garbage collection, any of the convenience methods are perfectly reasonable.) In most other cases, however, Jens and Ken have already addressed the principal issue: performance. You don't want to needlessly prolong the lifetime of objects. >> If you want to assign the dictionary to an instance variable, you >> should use an accessor method. In this case, it's still better to use >> alloc/init then release the dictionary when you've finished with it. > That's seems a really aberrant case, where you are creating an empty > dictionary with a nominated capacity. I can't visualize a case where you > would do such a thing, outside of the initialiser. > This pattern is shown commonly in iPhone sample code: NSMutableDictionary *aDictionary = [[NSMutableDictionary alloc] initWithCapacity:x] // Add to the dictionary. self.dictionary = aDictionary; [aDictionary release]; > There are cases like the NSFileManager where you need to pass in a dictionary > of options that describe the directory being created (for example) - should I > really be creating temporary variables for those, or using the convenience > methods (dictionaryWithObject:forKey:)? > The same applies as above. Following best practices, you should use alloc/init+release. How important this is to adhere to depends on how performance-sensitive your code and platform are... To reiterate Jens' succinct formula: Convenience ≠ performance. mmalc ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 8:47 PM, Jeff Laing wrote: > With all due respect, why not? Apple gives us all those convenience methods > but you say we shouldn't use them? Convenience ≠ performance. The autoreleased factory methods are very convenient when you're using the result temporarily, so you don't have to remember to release it. But when the point of the call is to get a reference, and you're not releasing right away anyway, it's just as easy and more efficient to use alloc/init. —Jens___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
RE: NSDictionary trouble
> >> Yes, and it autoreleases it too. :-o That means it'll conveniently be > >> released later on, which is exactly what you're running into. If you > >> want to keep a reference to the dictionary, you should call alloc and > >> init yourself. I wrote: > > No, you should just *retain* the result of dictionaryWithCapacity. mmalc wrote: > No, you shouldn't. With all due respect, why not? Apple gives us all those convenience methods but you say we shouldn't use them? (Note, my first kneejerk response was of course because I'm sure you'll find Apple docs that say explicitly "if you want to keep a reference to , you should retain it" whereas it's unlikely you'll find anything that says "if you want to keep a reference to , you're probably using the wrong design pattern") (Oh, and, dictionaryWithCapacity: is really not one I'd get in a fuss about. But some of the other dictionaryWithObjects: convenience methods are too damned handy to lose. I just don't think that "best practice" should be something that changes depending on which particular convenience method you are talking about) > If you're writing an init method and want to assign the dictionary to > an instance variable, you should use alloc/init. > > If you want to assign the dictionary to an instance variable, you > should use an accessor method. In this case, it's still better to use > alloc/init then release the dictionary when you've finished with it. That's seems a really aberrant case, where you are creating an empty dictionary with a nominated capacity. I can't visualize a case where you would do such a thing, outside of the initialiser. > If you want to create the dictionary, use it temporarily, then forget > about it, then dictionaryWithCapacity is OK, but again (particularly on > iPhone) best practice is still to use alloc/init+release. There are cases like the NSFileManager where you need to pass in a dictionary of options that describe the directory being created (for example) - should I really be creating temporary variables for those, or using the convenience methods (dictionaryWithObject:forKey:)? I'm assuming you are saying 'don't use the convenience methods because the autorelease pool won't empty quickly enough'. Certainly Ken said it, though he seemed to assume that there was only one pool, that people would not be creating their own in their known trouble-spots. Ken Thomases wrote: > The autorelease pool is convenient and in some cases necessary, but it > does come at some cost. It has some overhead in terms of time and > memory, plus it tends to increase the peak memory usage of your > program. (Over time, assuming you've got all your memory management > correct, a program's memory usage will come out the same, but > autoreleased objects accumulate over the lifetime of the current pool, > causing spiky memory usage.) But implicit in that seems to be that -[NSDictionary initWithObjectsAndKeys:] won't add to the auto-release pool and I don't see where that's a valid assumption (or at least a documented assumption). If you look at some of the stack traces in Instruments, you find things being created way down in the bowels of the frameworks that you wouldn't necessarily expect. (Date Formatter, I'm looking at you) I'm increasingly of the opinion that to be properly paranoid (that is, to not assume anything about the behavior of 3rd party (including Apple) classes) and survive in the limited memory world of the iPhone, you should be writing your initialisers like this: - (id)initLikeJeffThinksYouShould { if (self = [super init]) { // Assume incompetence in others and you'll never be disappointed, only pleasantly surprised. NSAutoreleasePool *pool = [NSAutorelease pool new]; _var = [[SomeoneElsesClass someMethodWhichMightFillThePool] retain]; [pool drain]; } return(self); } That's all putting aside that by calling dictionaryWithCapacity: it seems to me that the NSMutableDictionary framework has more chance of re-using one it had lying around in some cache - yes, initWithCapacity: could do that as well, but there would still be the memory-churn expense of the alloc/release that would not be needed by dictionaryWithCapacity It might not do it today but if I give the system the clearest possible indication of what I want (and not just the steps I think it should go through), I leave more scope for clever software engineers to add extra optimizations under the covers in future revisions. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 9:21 PM, Shawn Rutledge wrote: > On Tue, Jan 19, 2010 at 7:01 PM, mmalc Crawford wrote: >>> No, you should just *retain* the result of dictionaryWithCapacity. >>> >> No, you shouldn't. >> >> If you're writing an init method and want to assign the dictionary to an >> instance variable, you should use alloc/init. > > Why? The autorelease pool is convenient and in some cases necessary, but it does come at some cost. It has some overhead in terms of time and memory, plus it tends to increase the peak memory usage of your program. (Over time, assuming you've got all your memory management correct, a program's memory usage will come out the same, but autoreleased objects accumulate over the lifetime of the current pool, causing spiky memory usage.) In general, it's always good to be aware of such trade-offs and make judgments with them in mind. In a highly constrained environment like the iPhone, the recommendation is to avoid the autorelease pool in the simple cases where it's easy to do so. Like, the difference between the following: someIvar = [[NSMutableDictionary dictionaryWithCapacity:5] retain]; and someIvar = [[NSMutableDictionary alloc] initWithCapacity:5]; is not hard on the developer, but keeps usage of the autorelease pool to a minimum. Regards, Ken ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Tue, Jan 19, 2010 at 7:01 PM, mmalc Crawford wrote: >> No, you should just *retain* the result of dictionaryWithCapacity. >> > No, you shouldn't. > > If you're writing an init method and want to assign the dictionary to an > instance variable, you should use alloc/init. Why? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 5:50 pm, Jeff Laing wrote: >> Yes, and it autoreleases it too. :-o That means it'll conveniently be >> released later on, which is exactly what you're running into. If you >> want to keep a reference to the dictionary, you should call alloc and >> init yourself. > > No, you should just *retain* the result of dictionaryWithCapacity. > No, you shouldn't. If you're writing an init method and want to assign the dictionary to an instance variable, you should use alloc/init. If you want to assign the dictionary to an instance variable, you should use an accessor method. In this case, it's still better to use alloc/init then release the dictionary when you've finished with it. If you want to create the dictionary, use it temporarily, then forget about it, then dictionaryWithCapacity is OK, but again (particularly on iPhone) best practice is still to use alloc/init+release. mmalc ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
RE: NSDictionary trouble
> > I think dictionaryWithCapacity should both alloc and init it, right? > > Yes, and it autoreleases it too. :-o That means it'll conveniently be > released later on, which is exactly what you're running into. If you > want to keep a reference to the dictionary, you should call alloc and > init yourself. No, you should just *retain* the result of dictionaryWithCapacity. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
Le 20 janv. 2010 à 00:18, Kyle Sluder a écrit : > On Tue, Jan 19, 2010 at 3:09 PM, Shawn Rutledge > wrote: >> Well yeah, that's one of the reasons java.lang.String is immutable. >> But it helps that java.lang.Object has both hashCode and equals, so >> any object can be put into a collection that depends on those... you >> just have the option of improving the implementation of those for >> better hash distribution, comparing two objects by content rather than >> reference location, etc. I just wanted a hashtable that uses keys by >> pointer rather than expecting to copy them. Nice to know that copying >> protocol doesn't mean you have to actually copy it though. > > NSObject has -hash and -isEqual:. If you want a pointer-based > dictionary, create a CFDictionary with the appropriate options, and > cast it to NSDictionary* (read the documentation on Toll-Free Bridging > to see why this is possible). An other solution can be to use NSMapTable class. I prefer it to CFDictionary because the later is not really toll-free bridged when using custom key/value callbacks. Even with a NULL or CFType Key callback, if you use NSMutableDictionary methods, is will try to copy the keys. >> As for C++, you can use template containers to store either pointers >> or copies of objects, whichever you like. > > STL containers are far more explicit about their internal behavior. > It's possible to write a collection class that has the same > restrictions as NSDictionary. > > --Kyle Sluder > ___ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > http://lists.apple.com/mailman/options/cocoa-dev/devlists%40shadowlab.org > > This email sent to devli...@shadowlab.org > -- Jean-Daniel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Tue, Jan 19, 2010 at 3:09 PM, Shawn Rutledge wrote: > Well yeah, that's one of the reasons java.lang.String is immutable. > But it helps that java.lang.Object has both hashCode and equals, so > any object can be put into a collection that depends on those... you > just have the option of improving the implementation of those for > better hash distribution, comparing two objects by content rather than > reference location, etc. I just wanted a hashtable that uses keys by > pointer rather than expecting to copy them. Nice to know that copying > protocol doesn't mean you have to actually copy it though. NSObject has -hash and -isEqual:. If you want a pointer-based dictionary, create a CFDictionary with the appropriate options, and cast it to NSDictionary* (read the documentation on Toll-Free Bridging to see why this is possible). > As for C++, you can use template containers to store either pointers > or copies of objects, whichever you like. STL containers are far more explicit about their internal behavior. It's possible to write a collection class that has the same restrictions as NSDictionary. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Tue, Jan 19, 2010 at 2:33 PM, Jeremy Pereira wrote: > > On 19 Jan 2010, at 16:53, Shawn Rutledge wrote: > >> I'm accustomed to >> things like Qt and Java where hashtables can contain anything for both >> key and value. > > This is not true (at least for Java and probably for QT for the same reason). > From the API docs for the Map abstract class: > > "Note: great care must be exercised if mutable objects are used as map keys. > The behavior of a map is not specified if the value of an object is changed > in a manner that affects equals comparisons while the object is a key in the > map. " Well yeah, that's one of the reasons java.lang.String is immutable. But it helps that java.lang.Object has both hashCode and equals, so any object can be put into a collection that depends on those... you just have the option of improving the implementation of those for better hash distribution, comparing two objects by content rather than reference location, etc. I just wanted a hashtable that uses keys by pointer rather than expecting to copy them. Nice to know that copying protocol doesn't mean you have to actually copy it though. As for C++, you can use template containers to store either pointers or copies of objects, whichever you like. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 10:46 AM, Kirk Kerekes wrote: NSDictionary will use almost any object as a key: From the docs: "In general, a key can be any object (provided that it conforms to the NSCopying protocol...)" -- and if it is an immutable object, that -copy is just a -retain. Yes, but he said he wants to use a view as the key. Views are not immutable, and do copy themselves in response to -copy. Having a dictionary whose key objects are copies of your live views is not very useful. (Especially since the copied view will have a different hashcode from the original one, so you can't even look it up using the original view anymore...) —Jens___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 2:57 PM, Shawn Rutledge wrote: I think dictionaryWithCapacity should both alloc and init it, right? Yes, and it autoreleases it too. :-o That means it'll conveniently be released later on, which is exactly what you're running into. If you want to keep a reference to the dictionary, you should call alloc and init yourself. Sounds like you need to read over the memory management rules again :) Remember the cardinal rule: The only methods that return references you own and have to release are "alloc", "copy", "mutableCopy", "new", and of course "retain". —Jens___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On 20/01/2010, at 9:57 AM, Shawn Rutledge wrote: > I think dictionaryWithCapacity should both alloc and init it, right? Why do you think that? I repeat: "You MUST learn the memory management rules and have them down pat so you can write correctly managed code without having to really think about it." --Graham ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Tue, Jan 19, 2010 at 2:57 PM, Shawn Rutledge wrote: > I think dictionaryWithCapacity should both alloc and init it, right? Please stop making conjectures. The documentation explains all of this. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Tue, Jan 19, 2010 at 2:38 PM, Graham Cox wrote: > > On 20/01/2010, at 5:33 AM, Shawn Rutledge wrote: > >> I forgot to mention, another problem I ran into was that my dictionary >> is a member variable of my UIViewController, I inited it in >> initWithNibName, then later when I go to use it in another member >> function, I found that it had been garbage-collected. I used other >> member variables the same way, but only the dictionary got >> garbage-collected. So I fixed it by doing [myDict retain]; in the >> initWithNibName, but didn't understand why such a thing should be >> necessary. > > > Uh-oh, category error. > > UIViewController is an iPhone class, therefore you must be programming on > iPhone, right? Which does not have garbage collection. Oops, I guess you're right. I'm a n00b both on Objective-C and the iphone (obviously). > Therefore your assumptions about what is happening are wrong. You MUST learn > the memory management rules and have them down pat so you can write correctly > managed code without having to really think about it. Yes I will read more about that. Anyway, the NSMutableDictionary* member variable was inited fine, I can see that if I set a breakpoint in the VC's init method, but by the time I use it in another member function, it's pointing to unallocated memory. I verified that with the NSZombie trick. But retaining the dictionary fixed it. Any idea why? I think dictionaryWithCapacity should both alloc and init it, right? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On 20/01/2010, at 5:33 AM, Shawn Rutledge wrote: > I forgot to mention, another problem I ran into was that my dictionary > is a member variable of my UIViewController, I inited it in > initWithNibName, then later when I go to use it in another member > function, I found that it had been garbage-collected. I used other > member variables the same way, but only the dictionary got > garbage-collected. So I fixed it by doing [myDict retain]; in the > initWithNibName, but didn't understand why such a thing should be > necessary. Uh-oh, category error. UIViewController is an iPhone class, therefore you must be programming on iPhone, right? Which does not have garbage collection. Therefore your assumptions about what is happening are wrong. You MUST learn the memory management rules and have them down pat so you can write correctly managed code without having to really think about it. --Graham ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On 19 Jan 2010, at 16:53, Shawn Rutledge wrote: > I'm accustomed to > things like Qt and Java where hashtables can contain anything for both > key and value. This is not true (at least for Java and probably for QT for the same reason). From the API docs for the Map abstract class: "Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map. " From the docs for Object.hashCode() "Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified." The Cocoa "restriction" on keys actually makes things a little easier. For instance, you can use NSMutableString as a key in an NSDictionary with no problems. However, if you try to use a StringBuffer or StringBuilder as a key in a Java map, you won't get the "natural" behaviour - two distinct StringBuffers with the same character sequence in them do not compare equal and if you override equals() in a subclass to make sure they do, you'd better not change a StringBuffer that happens to be a key in a map.___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
RE: NSDictionary trouble
> I wish NSDictionary (NSMutableDictionary actually) could handle > arbitrary mappings of one type of object to another, without copying > the keys. A string makes a good key most of the time but what about > the case where you want to do the reverse mapping, to find the string > which you have associated with a particular object? I'm accustomed to > things like Qt and Java where hashtables can contain anything for both > key and value. Is there an alternative which does work that way? I > didn't try CFDictionary yet; is that appropriate for an iPhone app? NSDictionary will use almost any object as a key: From the docs: "In general, a key can be any object (provided that it conforms to the NSCopying protocol...)" -- and if it is an immutable object, that -copy is just a -retain. Only if you want to use KVC with the NSDictionary to the keys need to be strings. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Tue, Jan 19, 2010 at 1:24 PM, Jens Alfke wrote: > On Jan 19, 2010, at 8:53 AM, Shawn Rutledge wrote: >> I didn't try CFDictionary yet; is that appropriate for an iPhone app? > > But try NSMapTable first. It's sort of halfway between the two — it's an > Objective-C class but it has greater flexibility in what it can store and > how it stores it. Is NSMapTable available in Cocoa Touch? I was under the impression that that was Mac-only. Sixten ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Tue, Jan 19, 2010 at 11:24 AM, Jens Alfke wrote: > > On Jan 19, 2010, at 8:53 AM, Shawn Rutledge wrote: > >> I wish NSDictionary (NSMutableDictionary actually) could handle >> arbitrary mappings of one type of object to another, without copying >> the keys. > > It can. If you have a custom class you want to be able to use as a > dictionary key without copying, then make it implement the NSCopying > protocol and add this method: > - (id) copyWithZone: (NSZone*)zone { > return [self retain]; > } > This enables -copy but turns it into a no-op that returns the original > object. (This is perfectly kosher. Most immutable Foundation objects do the > same thing, i.e. copying an immutable NSString returns the same object.) OK thanks, that's good to know. However in this case I wanted to add NSSwitch objects to the dictionary. So it would have to be a subclass then I guess. > Of course you also have to implement -hash and -isEqual: to make your class > play nicely with dictionaries. Make sure these have immutable semantics: if > the values returned by these can ever change, you'll screw up any dictionary > or set the object is in. > >> I didn't try CFDictionary yet; is that appropriate for an iPhone app? > > Yes, you can use CF. Remember that a CFXXXRef is the same as an NSXXX*, you > can just typecast between them. If you create a CFDictionary you'll have to > define your own callbacks, and make the copy callback just retain the > object. > > But try NSMapTable first. It's sort of halfway between the two — it's an > Objective-C class but it has greater flexibility in what it can store and > how it stores it. Oh that looks good too, thanks again, I will try it. I forgot to mention, another problem I ran into was that my dictionary is a member variable of my UIViewController, I inited it in initWithNibName, then later when I go to use it in another member function, I found that it had been garbage-collected. I used other member variables the same way, but only the dictionary got garbage-collected. So I fixed it by doing [myDict retain]; in the initWithNibName, but didn't understand why such a thing should be necessary. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 10:09 AM, Paul Bruneau wrote: When I want to find the key(s) for a given object, I use the - allKeysForObject method This is fine, but keep in mind that it's a lot slower since it does a linear search instead of a hash lookup. (It's O(n) instead of O(1).) If you're putting this in code you know in advance is extremely performance sensitive, or will operate on huge data sets; or if you profile it later and find this is a bottleneck; you should go to a reverse dictionary mapping instead. —Jens___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 8:53 AM, Shawn Rutledge wrote: I wish NSDictionary (NSMutableDictionary actually) could handle arbitrary mappings of one type of object to another, without copying the keys. It can. If you have a custom class you want to be able to use as a dictionary key without copying, then make it implement the NSCopying protocol and add this method: - (id) copyWithZone: (NSZone*)zone { return [self retain]; } This enables -copy but turns it into a no-op that returns the original object. (This is perfectly kosher. Most immutable Foundation objects do the same thing, i.e. copying an immutable NSString returns the same object.) Of course you also have to implement -hash and -isEqual: to make your class play nicely with dictionaries. Make sure these have immutable semantics: if the values returned by these can ever change, you'll screw up any dictionary or set the object is in. I didn't try CFDictionary yet; is that appropriate for an iPhone app? Yes, you can use CF. Remember that a CFXXXRef is the same as an NSXXX*, you can just typecast between them. If you create a CFDictionary you'll have to define your own callbacks, and make the copy callback just retain the object. But try NSMapTable first. It's sort of halfway between the two — it's an Objective-C class but it has greater flexibility in what it can store and how it stores it. —Jens___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSDictionary trouble
On Jan 19, 2010, at 11:53 AM, Shawn Rutledge wrote: I wish NSDictionary (NSMutableDictionary actually) could handle arbitrary mappings of one type of object to another, without copying the keys. A string makes a good key most of the time but what about the case where you want to do the reverse mapping, to find the string which you have associated with a particular object? When I want to find the key(s) for a given object, I use the - allKeysForObject method ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
NSDictionary trouble
I wish NSDictionary (NSMutableDictionary actually) could handle arbitrary mappings of one type of object to another, without copying the keys. A string makes a good key most of the time but what about the case where you want to do the reverse mapping, to find the string which you have associated with a particular object? I'm accustomed to things like Qt and Java where hashtables can contain anything for both key and value. Is there an alternative which does work that way? I didn't try CFDictionary yet; is that appropriate for an iPhone app? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com