[macruby-changes] [4270] MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt

source_changes at macosforge.org source_changes at macosforge.org
Wed Jun 23 14:30:13 PDT 2010


Revision: 4270
          http://trac.macosforge.org/projects/ruby/changeset/4270
Author:   pthomson at apple.com
Date:     2010-06-23 14:30:12 -0700 (Wed, 23 Jun 2010)
Log Message:
-----------
Adding documentation on the essential differences between RubyCocoa and MacRuby.

Added Paths:
-----------
    MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt

Added: MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt
===================================================================
--- MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt	                        (rev 0)
+++ MacRubyWebsite/trunk/content/documentation/rubycocoa-to-macruby.txt	2010-06-23 21:30:12 UTC (rev 4270)
@@ -0,0 +1,185 @@
+h1. Essential Differences between RubyCocoa and MacRuby
+
+h2. Importing Frameworks
+
+To import a framework in RubyCocoa, you use a combination of Ruby's @require@ method and RubyCocoa's @require_framework@ addition:
+<pre class="commands">
+	# RubyCocoa code
+	require 'osx/cocoa'
+	OSX.require_framework('CoreData')
+</pre>
+MacRuby unifies these methods with the @framework@ method added to the @Kernel@ module:
+<pre class="commands">
+	# MacRuby code
+	framework 'Cocoa'
+	framework 'CoreData'
+</pre>
+
+h2. Namespaces
+
+In RubyCocoa, all imported Objective-C classes are located inside the @OSX@ module. In MacRuby, Objective-C classes are imported into the main namespace.
+
+h2. Inheritance
+
+Because RubyCocoa is not implemented on top of Objective-C, it requires objects passed to Objective-C APIs to inherit from @NSObject@:
+<pre class="commands">
+	# RubyCocoa code
+	class MyClass < NSObject
+	end
+</pre>
+In MacRuby, the Objective-C @NSObject@ and Ruby @Object@ classes are identical; therefore, because Ruby classes implicitly inherit from @Object@, all objects in MacRuby are valid @NSObjects at . Explicit inheritance is therefore no longer required:
+<pre class="commands">
+	# MacRuby code
+	class MyClass
+	end
+</pre>
+
+h2. Class Compatibility
+
+Many of MacRuby's built-in data structures are toll-free bridged to corresponding Cocoa or CoreFoundation equivalents:
+
+* MacRuby's @String@ class is bridged to @NSString@, @NSMutableString@, @CFStringRef@, and @CFMutableStringRef at .
+* MacRuby's @Array@ class is bridged to @NSArray@, @NSMutableArray@, @CFArrayRef@, and @CFMutableArrayRef at .
+* MacRuby's @Hash@ class is bridged to @NSDictionary@, @NSMutableDictionary@, @CFDictionaryRef@, and @CFMutableDictionaryRef@
+* MacRuby's @Integer@ and @Float@ classes are bridged to @NSNumber@ and @CFNumberRef at .
+
+Because these classes are toll-free bridged, the @#to_ns@ and @#to_ruby@ converters present in RubyCocoa code are no longer necessary and have been removed.
+
+Certain Cocoa data types, such as @NSRect@, @NSSize@, and @NSPoint@ are C-style structs, not Objective-C objects. Functions that return structures of these types will return them wrapped in corresponding @NSRect@, @NSSize@, and @NSPoint@ classes:
+<pre class="commands">
+	$ macirb --simple-prompt
+	>> framework 'Foundation'
+	=> true
+	>> rng = NSMakeRange(0, 10)
+	=> #<NSRange location=0 length=10>
+	>> rng.class
+	=> NSRange 
+</pre>
+Because Cocoa code often requires working with C struct types, MacRuby allows you to pass in an @Array@ containing the required data where a C struct would normally be expected. Some examples follow: 
+<pre class="commands">
+	# MacRuby code
+	window.frame = NSMakeRect(0, 0, 100, 200) # Using the NSMakeRect function
+	window.frame = NSRect.new(NSPoint.new(0, 0), NSSize.new(100, 200)) # Using the MacRuby NSRect class
+	window.frame = [0, 0, 100, 200]			  # Using a array in flat style 
+	window.frame = [[0, 0], [100, 200]]		  # Using an array [point, size] style
+</pre>
+Please note that MacRuby's @Range@, @Set@, and @Enumerator@ classes are *not* bridged to their Cocoa or CoreFoundation equivalents.
+
+h2. Keyword Arguments
+
+Objective-C's interleaved-keyword syntax is not compatible with traditional Ruby syntax. To be able to call Cocoa API's from RubyCocoa, you use the "underscore hack", which translates Ruby-style function calls into ObjC calls by joining the selector's components together with underscores:
+<pre class="commands">
+	# RubyCocoa code
+	NSFileManager.defaultManager.createFileAtPath_contents_attributes(p, c, a)
+</pre>
+In order to make the use of Objective-C methods from MacRuby as natural as possible, the MacRuby team extended standard Ruby syntax to support Objective-C style interleaved arguments:
+<pre class="commands">
+	# MacRuby code
+	NSFileManager.defaultManager.createFileAtPath(p, contents:c, attributes:a)
+</pre>
+This is the best way to call Objective-C methods; code written using the underscore hack or RubyCocoa's @objc_send@ function will fail to run under MacRuby.
+MacRuby allows you to use this syntax in your own method declarations, too:
+<pre class="commands">
+	# MacRuby code
+	def saveWorld(planet, fromVillain: badguy, withHero:superhero)
+		superhero.fight(badguy)
+		planet.thank(superhero)
+	end
+</pre>
+However, it's important to note that this syntax is unique to MacRuby; code written in that uses this syntax will fail to run on any other implementation of Ruby.
+
+h2. Interface Builder
+
+MacRuby's integration with Interface Builder is significantly cleaner than RubyCocoa's. Previously, declaring an instance variable that also functioned as an Interface Builder outlet required two declarations, one to declare Ruby-style accessors and another to declare a key-value compliant accessor:
+<pre class="commands">
+	# RubyCocoa code
+	class MyView < NSView
+		attr_accessor :pdfView
+		ib_outlet :pdfView
+	end
+</pre>
+MacRuby extends the semantics of @attr_accessor@ and @attr_writer@ to provide a key-value compliant setter method that Interface Builder will recognize. As such, all references to the @ib_outlet@ method can be removed:
+<pre class="commands">
+	# MacRuby code
+	class MyView < NSView
+		attr_accessor :pdfView
+	end
+</pre>
+Another significant improvement comes in the form of transparent support for Interface Builder actions. RubyCocoa required that IB actions be declared with the @ib_action@ helper method:
+<pre class="commands">
+	# RubyCocoa code
+	class MyController < NSObject
+		ib_action(:firstPage) do |sender|
+			currentPDFView.setPageNumber(1)
+		end
+	end
+</pre>
+Because of MacRuby's tight integration with the Objective-C runtime, there is no special syntax required to declare an IB action: any Ruby method can serve as an IB action, though it must have a @sender@ parameter like in Objective-C:
+<pre class="commands">
+	# MacRuby code
+	class MyController
+		def firstPage(sender)
+			currentPDFView.pageNumber = 1
+		end
+	end
+</pre>
+
+h2. super()
+
+In RubyCocoa, the @super()@ function did not work correctly if the superclass method being called was implemented in Objective-C. A further extension to the underscore hack became necessary:
+<pre class="commands">
+	# RubyCocoa code
+	class MyClass < NSObject
+		def init
+			super_init() # Calls [NSObject init]
+			p 'Initializing!'
+			self		# Always return self from init!
+		end
+	end
+</pre>
+MacRuby rectifies this inconsistency, allowing the @super()@ function to call both Ruby and Objective-C methods:
+<pre class="commands">
+	# MacRuby code
+	class MyClass
+		def init
+			super() # Also calls [NSObject init]
+			p 'Initializing!'
+			self	# Always return self from init!
+		end
+	end
+</pre>
+
+h2. Exception Handling
+
+Though Ruby's @Exception@ class and Objective-C's @NSException@ class are not technically bridged classes, @begin...rescue@ blocks in MacRuby can catch both Ruby @Exceptions@ and Cocoa @NSExceptions at . Conversely, you can catch MacRuby @Exceptions@ with Objective-C's @try@@/@catch at .
+
+h2. Other Syntactic Extensions
+
+The MacRuby team has ported the syntactic extensions present in RubyCocoa for cases when Objective-C idioms differ with Ruby idioms, such as in the case of mutator methods and boolean accessor methods:
+<pre class="commands">
+	layer.setPosition = [100, 100]	# Objective-C style
+	layer.position = [100, 100]		# Ruby style; calls the same method the Objective-C one does
+	layer.isHidden					# Objective-C style
+	layer.hidden?					# Ruby allows the '?' character in method names
+</pre>
+MacRuby provides additional syntax for the commonly-used @objectForKey:@ and @setObject:forKey:@ methods:
+<pre class="commands">
+	obj.objectForKey('data')	# Objective-C style
+	obj['data']					# Ruby style
+	obj.setObject('mystery', forKey: 'data') # Objective-C style
+	obj['data'] = 'mystery'		# Ruby style
+</pre>
+h2. Property Lists
+
+RubyCocoa added extensions for easy manipulation of property lists:
+<pre class="commands">
+	# RubyCocoa code
+	array_data = ['a', 'b', 'c'].to_plist
+	OSX.load_plist(array_data)
+</pre>
+MacRuby ports these extensions, adding @load_plist@ to the @Kernel@ module and @to_plist@ to @Object@:
+<pre class="commands">
+	# MacRuby code
+	array_data = ['a', 'b', 'c'].to_plist
+	load_plist(array_data)
+</pre>
\ No newline at end of file
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100623/fba4593f/attachment.html>


More information about the macruby-changes mailing list