Fun with Distributed Objects
Here’s how you can use Distributed Objects to remotely evaluate code on your simulated iPhone. This is obviously not for shipping applications, but I think you’re going to want to know how to do this when you’re debugging your app.
I’m assuming that you’re building your iPhone app with Nu. That’s a stretch, since I haven’t released a version of Nu for the iPhone other than the demo that I put out Thursday night. But start with that one for now.
Add this to your main.nu:
(class Server is NSObject
(- (void) print:(id) message is
(puts (+ "master says: " message)))
(- (id) eval:(id) command is
(eval (parse command))))
Then put this near the end of your applicationDidFinishLaunching::
(set receivePort ((NSSocketPort alloc) initWithTCPPort:8080)) (set $connection (NSConnection connectionWithReceivePort:receivePort sendPort:nil)) (set $server ((Server alloc) init)) ($connection setRootObject:$server) (puts (NSString stringWithShellCommand:"ifconfig"))Now run your iPhone app. Open the console in Xcode (use the Run – Console menu item). You should see something like this at the end of your log:
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
inet 127.0.0.1 netmask 0xff000000
inet6 ::1 prefixlen 128
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet6 fe80::219:e3ff:fe66:8ca6%en0 prefixlen 64 scopeid 0x4
inet 192.168.0.104 netmask 0xffffff00 broadcast 192.168.0.255
ether 00:19:e3:66:8c:a6
media: autoselect (100baseTX <full-duplex,flow-control>) status: active
supported media: autoselect 10baseT/UTP <half-duplex> 10baseT/UTP <full-duplex> 10baseT/UTP <full-duplex,hw-loopback> 10baseT/UTP <full-duplex,flow-control> 100baseTX <half-duplex> 100baseTX <full-duplex> 100baseTX <full-duplex,hw-loopback> 100baseTX <full-duplex,flow-control> 1000baseT <full-duplex> 1000baseT <full-duplex,hw-loopback> 1000baseT <full-duplex,flow-control>
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 00:19:e3:66:8c:a7
media: autoselect status: inactive
supported media: autoselect 10baseT/UTP <half-duplex> 10baseT/UTP <full-duplex> 10baseT/UTP <full-duplex,hw-loopback> 10baseT/UTP <full-duplex,flow-control> 100baseTX <half-duplex> 100baseTX <full-duplex> 100baseTX <full-duplex,hw-loopback> 100baseTX <full-duplex,flow-control> 1000baseT <full-duplex> 1000baseT <full-duplex,hw-loopback> 1000baseT <full-duplex,flow-control>
fw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 2030
lladdr 00:19:e3:ff:fe:80:5f:8e
media: autoselect <full-duplex> status: inactive
supported media: autoselect <full-duplex>
vmnet8: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 172.16.53.1 netmask 0xffffff00 broadcast 172.16.53.255
ether 00:50:56:c0:00:08
vmnet1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 172.16.159.1 netmask 0xffffff00 broadcast 172.16.159.255
ether 00:50:56:c0:00:01
Look near the end of the log. For me, “172.16.53.1” appears to be the local address of my simulated iPhone.
Now open a terminal and type “nush” (Yeah, you need Nu for this).
Type the following commands, subsituting whatever your iPhone’s address happens to be:
% (set sendPort ((NSSocketPort alloc) initRemoteWithTCPPort:8080 host:"172.16.53.1")) <NSSocketPort:1347f0> % (set connection (NSConnection connectionWithReceivePort:nil sendPort:sendPort)) <NSConnection:152b80> % (set iphone (connection rootProxy)) <NSDistantObject:1430a0>
Now you have a proxy for the Server object that’s running on your iPhone. Send it a command:
% (iphone print:"hello") ()Now go look in your console window. See it?
master says: hello
Now go back to your console window.
% (set delegate (iphone eval:"((UIApplication sharedApplication) delegate)")) <NSDistantObject:14b600>
Now your delegate variable is a proxy for the application delegate on your iPhone. Let’s ask it a few things. Follow along:
% (delegate valueForKey:"contentView") <NSDistantObject:168bb0> % ((delegate valueForKey:"contentView") subviews) <NSCFArray:140ac0> % (((delegate valueForKey:"contentView") subviews) count) 3 % ((((delegate valueForKey:"contentView") subviews) objectAtIndex:0) description) <UIButton: 0x1261c70> % ((((delegate valueForKey:"contentView") subviews) objectAtIndex:1) description) <UITextField: 0x1263700> % ((((delegate valueForKey:"contentView") subviews) objectAtIndex:2) description) <UILabel: 0x126fde0> % ((((delegate valueForKey:"contentView") subviews) objectAtIndex:2) setText:"pwned") ()
Having fun?
Obviously, this is FOR DEBUGGING AND DEVELOPMENT USE ONLY (sorry to shout, I just wanted to be clear about that) and remember, Apple has final say over what gets onto its platform. Our ability to use this during development does not at all imply that we can or should build it into applications.
Comments (4) post a reply
I suggest anyone getting excited by the apparent possibilities takes a look at section 3.3.2 of the iPhone SDK Agreement.
Jens,
That’s a valid concern. Please also see my comments at the end of this post.
A number of things:
An update: this works on the simulator only. There’s currently no Distributed Objects support on the iPhone. At least not until someone writes it.