Skip to content

Instantly share code, notes, and snippets.

@trivektor
Forked from seanlilmateus/gist:3187192
Created March 8, 2014 09:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trivektor/9427630 to your computer and use it in GitHub Desktop.
Save trivektor/9427630 to your computer and use it in GitHub Desktop.

Using Obj-C with MacRuby/Rubymotion

This little post aims to help you to translate Objective-C Blocks into Ruby blocks. Let's start by taking a look at few examples of iOS API call where blocks are used for animations and enumeration

Ruby Lambda Syntaxes:

Im Rubymotion and MacRuby you can use all the Ruby Lambda syntaxes that are:

block = lambda { |param|  ... }
block = lambda do |param|
	...
end

block = -> param { ... }
block = -> param do
	...
end

block = Proc.new{ |param| ... }
block = Proc.new do |name|
	....
end

block = proc { ... }
block = proc do |name|
  ...
end

####Objective-C Blocks with no arguments

[UIView animateWithDuration:0.2
     animations:^{view.alpha = 0.0;}]

this is how the Method looks like: __ + animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations__, this method takes two arguments duration and animations, where animations where animations is block (lambda) that takes no arguments

UIView.animateWithDuration(0.2, animations:-> { view.alpha = 0.0 })

####Objective-C Blocks with one argument

[UIView animateWithDuration:0.2
     animations:^{view.alpha = 0.0;}
     completion:^(BOOL finished){ [view removeFromSuperview]; }];

this is how the Method looks like: animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion, this method takes three arguments duration, animations and completion where animations and completion are blocks. the animations blocks does not take an argument, but completion does.

# we use the Ruby 1.9 Lambda sytax
UIView.animateWithDuration(0.2,
     animations:-> { view.alpha = 0.0 },
     completion:-> finished { view.removeFromSuperview })

Since we don't use the finished variable, we could also do this:

# we use the Ruby 1.9 Lambda sytax
UIView.animateWithDuration(0.2,
     animations:-> { view.alpha = 0.0 },
     completion:-> _ { view.removeFromSuperview })

####Objective-C Blocks with two arguments

NSSet *aSet = [NSSet setWithObjects: @"X", @"Y", @"Z", @"Pi", nil];
NSString *aString = @"z";
 
[aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop){
     if ([obj localizedCaseInsensitiveCompare:aString]==NSOrderedSame) {
          NSLog(@"Object Found: %@", obj);
          *stop = YES;
     }
} ];

The method enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block of NSSet is an enumeration method that takes a block with two arguments this is how it would look like in Ruby

the_set = NSSet.setWithObjects("X", "Y", "Z", "Pi", nil)
the_str = "z"

the_set.enumerateObjectsUsingBlock(lambda do |obj, stop|
  if obj.localizedCaseInsensitiveCompare(the_str) == NSOrderedSame
    NSLog("Object Found: %@", obj)
    stop.assign(true)
  end
end)

####Objective-C Blocks with three arguments

Using Block-Based Enumeration

The NSArray method (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block

NSArray *anArray = [NSArray arrayWithObjects:@"A", @"B", @"D", @"M", nil];
NSString *string = @"c";
 
[anArray enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop){
     if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) {
          NSLog(@"Object Found: %@ at index: %i",obj, index);
          *stop = YES;
     }
} ];

the Ruby Version

the_array = ["A", "B" ,"D", "C", "M"]
the_str = "c"

the_array.enumerateObjectsUsingBlock(-> obj, index, stop {
    if (obj.localizedCaseInsensitiveCompare(the_str) == NSOrderedSame)
        NSLog("Object Found: %@ at index: %@", obj, index)
		stop.assign(true)
	end
})

Now let's get crazy :-), you will be able to explain it yourself

strings = ["string 1", "String 21", "string 12", "String 11", "String 02"]

comparison_opts = NSCaseInsensitiveSearch | NSNumericSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch
current_locale = NSLocale.currentLocale

result = strings.sortedArrayUsingComparator(lambda do |first, second|
  first_range = NSMakeRange(0, first.length)
  first.compare(second, options:comparison_opts, range:first_range, locale:current_locale)
end
)
NSLog("finderSortArray: %@", result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment