Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behavior with App::Persistence and BW::JSON #118

Closed
bensie opened this issue Jul 24, 2012 · 4 comments
Closed

Unexpected behavior with App::Persistence and BW::JSON #118

bensie opened this issue Jul 24, 2012 · 4 comments
Assignees

Comments

@bensie
Copy link
Contributor

bensie commented Jul 24, 2012

It seems that BubbleWrap::JSON can't parse a string that comes from persisted storage:

> App::Persistence["foo"] = BubbleWrap::JSON.generate({"foo"=>nil,"bar"=>nil})
=> "{\"foo\":null,\"bar\":null}"

> BubbleWrap::JSON.parse App::Persistence["foo"]
2012-07-24 12:03:57.789 Amigo Booth[72204:11603] -[__NSCFString bytes]: unrecognized selector sent to instance 0x9d68c80
2012-07-24 12:03:57.874 Amigo Booth[72204:11603] json.rb:19:in `parse:': NSInvalidArgumentException: -[__NSCFString bytes]: unrecognized selector sent to instance 0x9d68c80 (RuntimeError)
=> #<RuntimeError: NSInvalidArgumentException: -[__NSCFString bytes]: unrecognized selector sent to instance 0x9d68c80>
@dmarkow
Copy link
Contributor

dmarkow commented Jul 28, 2012

This is a RubyMotion bug specifically, I just filed a ticket.

(main)> NSUserDefaults.standardUserDefaults["foo"] = "bar"
=> "bar"
(main)> NSUserDefaults.standardUserDefaults["foo"].class
=> String
(main)> other_string = "bar"
=> "bar"
(main)> other_string.class
=> String
(main)> NSUserDefaults.standardUserDefaults["foo"].class.ancestors
=> [String, NSMutableString, NSString, Comparable, NSObject, Kernel]
(main)> other_string.class.ancestors
=> [String, NSMutableString, NSString, Comparable, NSObject, Kernel]
(main)> other_string.methods - NSUserDefaults.standardUserDefaults["foo"].methods
=> [:"transform:", :each_codepoint, :codepoints, :each_byte, :bytes, :ascii_only?, :valid_encoding?, :"force_encoding:", :pointer, :to_data, :"setbyte:", :"getbyte:", :bytesize, :"camelize:", :camelize, :underscore, :to_color]
# WTF?

So while the string that RubyMotion returns for standardUserDefaults["foo"] is a String, it's missing a couple methods that a other RubyMotion Strings have (in this case, we specifically need to_data).

I'll look into a temporary workaround until this gets fixed upstream.

@ghost ghost assigned dmarkow Jul 28, 2012
@dmarkow
Copy link
Contributor

dmarkow commented Jul 28, 2012

To clarify, this doesn't just affect the JSON parsing. For example, you can't use camelize on strings returned from standardUserDefaults either.

@bensie
Copy link
Contributor Author

bensie commented Jul 29, 2012

Thanks for taking the time to investigate and come up with a workaround!

@dmarkow
Copy link
Contributor

dmarkow commented Jul 29, 2012

Update from Laurent, looks like we'll need to keep the dup in there indefinitely.

Strings created in Ruby do respond to these additional methods because they are differently implemented: they use a binary storage to conform to the Ruby specs. Pure NSStrings do not have a binary storage (they are character-based) which is why to_data & friends are not there.

I agree it can be confusing at the first glance (especially since the same class is returned, again for spec conformance) but this is a historical heritage from MacRuby.

I believe that to_s or dup will return a "ruby" string if called on an NSString. You can use that before calling to_data to make sure it will always work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants