Hack hack hack...

An open journal-- some of it written for you, but most of it is for me.

RubyMotion Alarm

To Read

Reachability

  • I had all sorts of problems with the reachability pod on the device, while I saw no such problems on the simulator. Pretty frustrating.
  • The reachability methods seemed to be returning true even if there was no connection and it also seemed to screw up my simple requests to an external API.
  • Still not quite sure what was wrong, but as soon as I stripped out reachability the behavior returned to normal.

positioning

  • UI elements in iOS have a frame. Think of it as the frame for a photograph on your wall. When you create elements, you have to specify the frame, in the following format:
    • [[x, y], [width, height]]

CocoaPods

  • like RubyGems for ruby
  • nice summary here

add_periodic_timer

  • run this code every second -> EM.add_periodic_timer 1.0 do
  • add_periodic_timer is actaully an event machine method
  • this is made possible by the bubblewrap which used BW::Reactor
    • BW::Reactor is a simplified, mostly complete implementation of the Event Machine API. In fact BW::Reactor is aliased to EM in the runtime environment.

Leading zeros

Promotion slide menu

  • we started by using this but dropped it and dropped promotion altogether.

Colors with bubble wrap

  • instead of UIColor.whiteColor you can just do 'white'.to_color

Delegates for input field

Delegate pattern
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  def on_load
    @input_field = UITextField.new
    add(@input_field, setting_input_style)
    @input_field.delegate = self
  end

  # - (BOOL)textFieldShouldReturn:(UITextField *)textField
  def textFieldShouldReturn(textField)
    urlString = textField.text
    if urlString.length > 1
      loadRequest(urlString)
    end
    textField.resignFirstResponder
    true
  end

initWithFrame

  • Can’t pass in parameters to initWithFrame and having trouble setting variables. So invoke a new method called ‘initWithFrameAndImage’ passing the neccessary parameters and then call initWithFrame within that method.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def initWithFrameAndImage(frame, picture)
  initWithFrame(frame)
  @time_pic = UIImageView.alloc.initWithImage(UIImage.imageNamed(picture))
  add(@time_pic) #, tile_style)

  set_attributes self, {
    background_color: hex_color("F6F6F6"),
    layer: {
      shadow_radius: 4.0,
      shadow_opacity: 0.4,
      shadow_color: UIColor.blackColor.CGColor
    }
  }
  self
end

Scrolling

  • adding elements to a scroll is rather easy with promotion. Keep in mind that you can’t be adding multiple elements as a splat or anything. If you are iterating over a bunch of tiles, for example, they need to be added to the UIScrollView individually.
1
2
3
4
5
6
def on_load
  @scroll = add UIScrollView.alloc.initWithFrame(self.view.bounds)
  add_to @scroll, element
  @scroll.frame = self.view.bounds
  @scroll.contentSize = CGSizeMake(@scroll.frame.size.width, content_height(@scroll) + 20)
end

Stuff I didn’t understand

  • makeKeyAndVisible specifies which window is current. Despite the fact that most apps only have one window, there is no way to assume that your primary window is to be the key window. Therefore you must explicitly call makeKeyAndVisible. see
  • Use a UIScrollView with pagingEnabled=YES to switch between pages, but you need pagingEnabled=NO to scroll vertically. see
  • The purpose of dequeueReusableCellWithIdentifier is to use less memory. If the screen can fit 4 or 5 table cells, then with reuse you only need to have 4 or 5 table cells allocated in memory even if the table has 1000 entries.see
  • can’t add a target to a UIView. Need to add a UIButton to the UIView and THEN add a target to the UIButton.
  • bringSubviewToFront
  • clipsToBounds -> like overflow hidden. great for circular mask type images.
  • toll-free bridge => ruby class inheriting from objective-c ancestors so that both ruby and objective-c methods can be called on an object.

CALayers

  • CALayers are simply classes representing a rectangle on the screen with visual content. A tutorial

RMQ => JQuery for RubyMotion

Garbage Collection

  • RubyMotion’s memory management system is designed to simplify the development process. Unlike traditional Objective-C programming, object references are automatically created and destroyed by the system. It is very similar to Objective-C’s ARC, in design, but it is differently implemented. via

Observer Pattern vs. NSNotificationCenter vs. Key/Value Observing (KVO)

  • micheal erasmus has a gem observable, which is a compatible implementation of the ruby stdlib Observable library.
  • bubblewrap provides helper methods to give NSNotificationCenter a Ruby-like interface.
  • bubblewrap also allows you to observe for object’s changes and trigger blocks.

Deploy to device

  • This was a tremendous help. I did all the steps up to step 6.
  • we also created dot files which stored the dev cert and the path of the mobile provision

Obj-c to rubymotion

1
UIWindow *window = [[UIWindow alloc] initWithFrame:frame]

UIWindow is the type of the variable pointer. *window is the pointer. UIWindow alloc allocates memory and returns a new object. initWithFrame is calling on the new object that is created via the UIWindow alloc.

1
@window = UIWindow.alloc.initWithFrame(frame)

We are setting @window as an instance variable to prevent premature garbare collection.

Another Example

Method in Obj-C
1
2
3
  UITapGestureRecognizer *recognizer =
    [[UITapGestureRecognizer alloc] initWithTarget:self
                                    action:@selector(tapped_purchase_button:)];
  • This is a two parameter method. This first parameter is the target, which is self. Second param, is the action or method that we want to send to that target.
  • to call methods dynamically in objective-c you use the @selector(method_name). This is how it is invoked in objective-c
In Ruby
1
recognizer = UITapGestureRecognizer.alloc.initWithTarget(self, action:'tapped_purchase_button')

Loading a json file

  • need to create a NSData Object and read in the data.
  • need to use a pointer for error handling.
  • NSDataSerialization.JSONObjectWithData(raw_data, options:NSDataReadingUncached, error:errorPointer)
  • 38:04 in prag screencast
1
2
3
4
5
6
7
8
def loadAnswers
  answerFile = NSBundle.mainBundle.pathForResource('answers', ofType:'json')
end

errorPointer = Pointer.new(:object)
data = NSData.alloc.initWithContentOfFile(answerFile, options:NSDataReadUncached, error:errorPointer)

NSDataSerialization.JSONObjectWithData(data, options:NSDataReadingUncached, error:errorPointer)

Push Notifications

  • Your service (a.k.a. the publisher of the app) sends a message with a token that is wants to send a push notifcation to Apple Push Notification Service (APNS).
  • APNS then decides whether to relay your push notification onto the app.
  • there a good tutorial at parse

Testing

  • RubyMotion uses MacBacon and the UIAnimation framework to do UI testing.
  • quick tutorial
  • subviews are not found the same way as top level views

Location

  • bubblewrap provides the call BW::Location.get_once { |location|} which get the location just once and returns a CLLManager object. Bubblewrap offers a number of methods that can be called on the this object such as latitude and longitude.

NSData

  • Getting back NSConcreteData from an API call.

Basic web service

  • users will be able to receive random motivational messages from other users

  • set up sinatra to post .json from DB

  • BW::HTTP get (URL) data

  • BW::HTTP post (URL) data

  • sinatra receives message and writes to DB

  • BW::HTTP also has methods to make sure the response comes back ok. Not surprisingly, this is response.ok?. Just make sure to use this to quasi-rescue a method that depends on a request.

Comments