Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Sydde

macrumors 68030
Original poster
Aug 17, 2009
2,552
7,050
IOKWARDI
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

Moderator emeritus
Jun 15, 2000
7,958
7
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

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
Hmmm... NSValue's valueWithRect: didn't work? What about NSCoder's encodeRect: or encodeRect:forKey:? Which archiver are trying to use?
 

Sydde

macrumors 68030
Original poster
Aug 17, 2009
2,552
7,050
IOKWARDI
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

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
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

macrumors 68030
Original poster
Aug 17, 2009
2,552
7,050
IOKWARDI
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

macrumors 65816
Dec 16, 2010
1,449
1
Sydney
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.