PDA

View Full Version : if ( self == whiner ) B****rds! ;




Sydde
May 14, 2011, 02:32 PM
So I thought, how convenient, I can just save a NSRect using NSValue ó except it was not working, the console said "... this archiver cannot encode structs". Well, dammit, NSValue says it conforms to NSCoding protocol, but when it comes to encoding a NSRect, it chooses not to. Where in the docs does it say that? I looked around but it was not evident anywhere.

Suffice it to say, I simply created my own specific NSRect wrapper object that encodes the elements as NSNumbers, took me all of 20 minutes (because I had to put in every possible method I could think of for the object).

But why can they not at least put a line in somewhere to let a poor, lazy coder know that this will spit up on you?



kainjow
May 14, 2011, 05:30 PM
I guess you missed NSStringFromRect() and NSRectFromString() ;)

And the reason it probably doesn't archive structs is because archives work on all architectures and dumping raw structs to file would fail to work for all cases across 32/64-bit due to padding.

jiminaus
May 14, 2011, 05:49 PM
Hmmm... NSValue's valueWithRect: didn't work? What about NSCoder's encodeRect: or encodeRect:forKey:? Which archiver are trying to use?

Sydde
May 14, 2011, 06:04 PM
I guess you missed NSStringFromRect() and NSRectFromString() ;)
What, use functions? zomg, this is Objective-C, I am supposed to use objects.;)
And the reason it probably doesn't archive structs is because archives work on all architectures and dumping raw structs to file would fail to work for all cases across 32/64-bit due to padding.
Yes, I do understand the issues with just flat laying out bytes and hoping that they will never be used on a different type of machine. But I figured NSValue might at least be smart enough to know what it contains and encode appropriately. Or maybe that Apple would have the courtesy to let me know that this was going to spit up on me. Just one little sentence in the overview that tells you NSValue might not be able to encode non-primitives.

jiminaus
May 14, 2011, 06:11 PM
Or maybe that Apple would have the courtesy to let me know that this was going to spit up on me. Just one little sentence in the overview that tells you NSValue might not be able to encode non-primitives.


But it's not NSValue's fault. The message says the archiver cannot encode structs. The archiver is the NSCoder object, not the NSCoding object. The fault is with the NSCoder object being used. And both NSValue and NSCoder both explicitly support rects. So what are you doing wrong?

Sydde
May 14, 2011, 06:50 PM
But it's not NSValue's fault. The message says the archiver cannot encode structs. The archiver is the NSCoder object, not the NSCoding object. The fault is with the NSCoder object being used. And both NSValue and NSCoder both explicitly support rects. So what are you doing wrong?
No, actually, if you look at the docs for NSCoder:

encodeRect:
Encodes rect.

- (void)encodeRect: (NSRect)rect

Discussion
NSCoderís implementation invokes encodeValueOfObjCType:at: to encode rect.
.
.
.
encodeValueOfObjCType:at:
Must be overridden by subclasses to encode a single value residing at address, whose Objective-C type is given by valueType.

- (void)encodeValueOfObjCType: (const char *)valueType at: (const void *)address

Naturally, I am using NSKeyedArchiver, which is a subclass of NSCoder. NSCoder is an abstract class, meaning any methods it actually implements are placeholders or exception throwers. Apparently, NSKeyedArchiver does not support archiving NSRect structs, probably for the reasons kainjow put forth. Perhaps it did in 10.3 or 10.2, when the architecture was homogenous (all 32 bit BE), but now it does not.

jiminaus
May 14, 2011, 10:10 PM
No, actually, if you look at the docs for NSCoder.

Slap, ow! But rightly deserved.



NSCoder is an abstract class, meaning any methods it actually implements are placeholders or exception throwers.

It's not necessarily a pure abstract class. Some of the methods could be implemented in terms of a subset of the API that is actually abstract. For example, encodeRect:forKey: could have been implemented in terms of encodePoint:forKey: and encodeSize:forKey:. These in turn could have been implemented in terms of either encodeFloat:forKey: or encodeDouble:forKey:.

But now I completely agree with your rant. How hard would it have been for Apple to implement encodeRect:forKey: and decodeRect:forKey: using NSStringForRect and NSRectForString respectively. These wouldn't have had any platform dependencies because the numbers would have been written and read as text not binary.