Added wiki docs to /docs in preparation for potential move to ReadTheDocs

This commit is contained in:
Jamon Holmgren
2015-01-29 10:48:21 -08:00
parent 021229933d
commit 1df60dfb50
21 changed files with 2218 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
ProMotion comes bundled with an executable called `promotion`. For now, it just creates a scaffold ProMotion project. We may extend it to include generators and other helpful utilities down the road.
#### promotion new `appname`
Creates a new ProMotion app in a new `appname` folder.
```shell
$ gem install ProMotion
Successfully installed ProMotion
1 gem installed
$ promotion new mytestapp
Creating new ProMotion iOS app mytestapp
From github.com:jamonholmgren/promotion-template
* branch master -> FETCH_HEAD
a3f98a9..676fd71 master -> origin/master
Create mytestapp
Create mytestapp/.gitignore
Create mytestapp/app/app_delegate.rb
Create mytestapp/app/layouts/.gitkeep
Create mytestapp/app/models/.gitkeep
Create mytestapp/app/screens/help_screen.rb
Create mytestapp/app/screens/home_screen.rb
Create mytestapp/app/styles/.gitkeep
Create mytestapp/app/views/.gitkeep
Create mytestapp/Gemfile
Create mytestapp/Rakefile
Create mytestapp/resources/Default-568h@2x.png
Create mytestapp/spec/main_spec.rb
Create mytestapp/spec/screens/home_screen_spec.rb
```

View File

@@ -0,0 +1,161 @@
### Contents
* [Usage](?#usage)
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
### Usage
The PM::Delegate gives you ProMotion's nice API for your AppDelegate class.
```ruby
# app/app_delegate.rb
class AppDelegate < PM::Delegate
status_bar false, animation: :none
def on_load(app, options)
open HomeScreen.new(nav_bar: true)
end
end
```
If you need to inherit from a different AppDelegate superclass, do this:
```ruby
class AppDelegate < JHMyParentDelegate
include PM::DelegateModule
status_bar false, animation: :none
def on_load(app, options)
open HomeScreen.new(nav_bar: true)
end
end
```
### Methods
#### on_load(app, options)
Main method called when starting your app. Open your first screen, tab bar, or split view here.
```ruby
def on_load(app, options)
open HomeScreen
end
```
#### on_unload
Fires when the app is about to terminate. Don't do anything crazy here, but it's a last chance
to save state if necessary.
```ruby
def on_unload
# Unloading!
end
```
#### will_load(app, options)
Fired just before the app loads. Not usually necessary.
#### on_activate
Fires when the app becomes active.
#### will_deactivate
Fires when the app is about to become inactive.
#### on_enter_background
Fires when the app enters the background.
#### will_enter_foreground
Fires just before the app enters the foreground.
#### open_tab_bar(*screens)
Opens a UITabBarController with the specified screens as the root view controller of the current app.
iOS doesn't allow opening a UITabBar as a sub-view.
```ruby
def on_load(app, options)
open_tab_bar HomeScreen, AboutScreen, ThirdScreen, HelpScreen
end
```
#### open_split_screen(master, detail)
**iPad apps only**
Opens a UISplitScreenViewController with the specified screens as the root view controller of the current app
```ruby
def on_load(app, options)
open_split_screen MasterScreen, DetailScreen,
icon: "split-icon", title: "Split Screen Title" # optional
end
```
#### on_open_url(args = {})
Fires when the application is opened via a URL (utilizing [application:openURL:sourceApplication:annotation:](http://developer.apple.com/library/ios/#documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:openURL:sourceApplication:annotation:)).
```ruby
def on_open_url(args = {})
args[:url] # => the URL used to fire the app (NSURL)
args[:source_app] # => the bundle ID of the app that is launching your app (string)
args[:annotation] # => hash with annotation data from the source app
end
```
---
### Class Methods
#### status_bar
Class method that allows hiding or showing the status bar.
```ruby
class AppDelegate < PM::Delegate
status_bar true, animation: :none # :slide, :fade
end
```
#### tint_color
Class method that allows you to set the application's global tint color for iOS 7 apps.
```ruby
class AppDelegate < ProMotion::Delegate
tint_color UIColor.greenColor
end
```
---
### Accessors
#### window
References the UIWindow that is auto-created with the first `open`, `open_tab_bar`, or `open_split_screen` call.
```ruby
def some_method
self.window #=> UIWindow instance
end
```
#### home_screen
References the root screen for the app.
```ruby
def some_method
self.home_screen #=> PM::Screen instance
end
```

View File

@@ -0,0 +1,79 @@
### Contents
* [Usage](?#usage)
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
### Usage
The ProMotion logger handles debugging and informational output to the REPL. It is accessible from ProMotion.logger or PM.logger. You can also set a new logger by setting `PM.logger = MyLogger.new`.
```ruby
def some_method
PM.logger.error "My error"
PM.logger.deprecated "Deprecation warning"
PM.logger.warn "My warning"
PM.logger.debug @some_object
PM.logger.info "Some info #{@object}"
PM.logger.log("My Custom Error", "My Message", :red)
end
```
### Methods
#### log(label, message_text, color)
Output a colored console message.
```ruby
PM.logger.log("TESTING", "This is red!", :red)
```
#### error(message)
Output a red colored console error.
```ruby
PM.logger.error("This is an error")
```
#### deprecated(message)
Output a yellow colored console deprecated.
```ruby
PM.logger.deprecated("This is a deprecation warning.")
```
#### warn(message)
Output a yellow colored console warning.
```ruby
PM.logger.warn("This is a warning")
```
#### debug(message)
Output a purple colored console debug message.
```ruby
PM.logger.debug(@some_var)
```
#### info(message)
Output a green colored console info message.
```ruby
PM.logger.info("This is an info message")
```
### Class Methods
**None.**
### Accessors
**None.**

View File

@@ -0,0 +1,3 @@
**Note: PM::MapScreen has been extracted into its own gem, [ProMotion-map](https://github.com/clearsightstudio/ProMotion-map)**.
View documentation: https://github.com/clearsightstudio/ProMotion-map/blob/master/README.md

View File

@@ -0,0 +1,3 @@
ProMotion::PushNotification has been extracted into the new [ProMotion-push](https://github.com/clearsightstudio/ProMotion-push) add-on gem.
Documentation: https://github.com/clearsightstudio/ProMotion-push/blob/master/README.md

View File

@@ -0,0 +1,458 @@
### Contents
* [Usage](?#usage)
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
### Usage
PM::Screen is the primary object in ProMotion and a subclass of UIViewController. It adds some abstraction to make your life easier while still allowing the full power of a UIViewController.
```ruby
class HomeScreen < PM::Screen
title "Home"
tab_bar_item item: "home-screen-tab", title: "Home"
status_bar :light
def on_load
# set up subviews here
add MyCustomView, frame: [[ 50, 50 ], [ 100, 100 ]]
set_nav_bar_button :right, title: "Next", action: :go_to_next
end
# custom method, triggered by tapping right nav bar button set above
def go_to_next
open NextScreen # opens in same navigation controller, assuming we're in one
end
def will_appear
# just before the view appears
end
def on_appear
# just after the view appears
end
def will_disappear
# just before the view disappears
end
def on_disappear
# just after the view disappears
end
end
```
---
### Methods
#### modal?
Returns if the screen was opened in a modal window.
```ruby
m = ModalScreen.new
open_modal m
m.modal? # => true
```
#### nav_bar?
Returns if the screen is currently contained in a navigation controller.
```ruby
open s = HomeScreen.new(nav_bar: true)
s.nav_bar? # => true
```
#### will_appear
Runs before the screen appears.
```ruby
def will_appear
# just before the screen appears
end
```
#### on_appear
Runs when the screen has appeared.
```ruby
def on_appear
# screen has just appeared
end
```
#### will_present
Runs just before the screen is pushed onto the navigation controller.
```ruby
def will_present
# About to present
end
```
#### on_present
Runs just after the screen is pushed onto the navigation controller.
```ruby
def on_present
# Presented
end
```
#### will_disappear
Runs just before the screen disappears.
#### will_dismiss
Runs just before the screen is removed from its parent. Usually happens when getting popped off a navigation controller stack.
#### on_dismiss
Runs just after the screen is removed from its parent.
#### will_rotate(orientation, duration)
Runs just before the screen rotates.
#### set_nav_bar_button(side, args = {})
Set a nav bar button. `args` can be `image:`, `title:`, `system_item:`, `button:`, `custom_view:`.
You can also set arbitrary attributes in the hash and they'll be applied to the button.
```ruby
set_nav_bar_button :left, {
title: "Button Title",
image: UIImage.imageNamed("left-nav"),
system_item: :reply,
tint_color: UIColor.blueColor,
button: UIBarButtonItem.initWithTitle("My button", style: UIBarButtonItemStyleBordered, target: self, action: :tapped_button) # for custom button
}
```
`system_item` can be a `UIBarButtonSystemItem` or one of the following symbols:
```ruby
:done,:cancel,:edit,:save,:add,:flexible_space,:fixed_space,:compose,
:reply,:action,:organize,:bookmarks,:search,:refresh,:stop,:camera,
:trash,:play,:pause,:rewind,:fast_forward,:undo,:redo,:page_curl
```
`custom_view` can be any custom `UIView` subclass you initialize yourself
Another example with arbitrary attributes:
```ruby
set_nav_bar_button :right, {
system_item: :add,
action: :add_item,
accessibility_label: "add item",
background_color: UIImage.imageNamed("some-image")
}
```
And finally, you can also set the `:back` nav bar image on a screen and it will render a back arrow icon in the upper left part of the navigation. However, note that doing so will change the back button for all descendants of the screen you set the button on. This behavior is a little unintuitive, but is a result of the underlying Cocoa Touch APIs. For example:
```ruby
class MyScreen < PM::Screen
def on_init
set_nav_bar_button :back, title: 'Cancel', style: :plain, action: :back
end
def go_to_next_screen
open MyScreenChild
end
end
```
The code above will add a "cancel" back button to `MyScreenChild` when it is opened as a descendant of `MyScreen`.
#### set_toolbar_items(buttons = [], animated = true)
Uses an array to set the navigation controllers toolbar items and shows the toolbar. Uses the same hash formatted parameters as `set_nav_bar_button`. When calling this method, the toolbar will automatically be shown (even if the screen was created without a toolbar). Use the `animated` parameter to specify if the toolbar showing should be animated or not.
```ruby
# Will arrange one button on the left and another on the right
set_toolbar_items [{
title: "Button Title",
action: :some_action
}, {
system_item: :flexible_space
}, {
title: "Another ButtonTitle",
action: :some_other_action,
target: some_other_object
}]
```
You can also pass your own initialized `UIBarButtonItem` as part of the array (instead of a hash object).
_EDGE FEATURE:_ You can pass `tint_color` with a `UIColor` to change the tint color of the button item.
#### title
Returns title of current screen.
```ruby
class MyScreen < PM::Screen
title "Mine"
def on_load
self.title # => "Mine"
end
```
#### title=(title)
Sets the text title of current screen instance.
```ruby
class SomeScreen
def on_load
# This sets this instance's title
title = "Something else"
end
end
```
#### app_delegate
Returns the AppDelegate. Alias of `UIApplication.sharedApplication.delegate`.
#### close(args = {})
Closes the current screen, passes `args` back to the previous screen's `on_return` method (if it exists).
```ruby
class ChildScreen < PM::Screen
def save_and_close
save
close({ saved: true })
end
end
class ParentScreen < PM::Screen
def on_return(args={})
if args[:saved]
reload_data
end
end
end
```
If you want to close back to the root screen or any other screen in the navigation stack, use `to_screen:`:
```ruby
class ChildScreen < PM::Screen
def close_to_root
close to_screen: self.navigation_controller.viewControllers.first
# For the rootViewController, you can just use `:root`
close to_screen: :root
end
end
```
#### open_root_screen(screen)
Closes all other open screens and opens `screen` as the root view controller.
```ruby
def reset_this_app
open_root_screen HomeScreen
end
```
#### open(screen, args = {})
Opens a screen, intelligently determining the context.
**Examples:**
```ruby
# In app delegate
open HomeScreen.new(nav_bar: true)
# In tab bar
open HomeScreen.new(nav_bar: true), hide_tab_bar: true
# `modal: true` is the same as `open_modal`.
open ModalScreen.new(nav_bar: true), modal: true, animated: true
# Opening a modal screen with transition or presentation styles
open_modal ModalScreen.new(nav_bar: true,
transition_style: UIModalTransitionStyleFlipHorizontal,
presentation_style: UIModalPresentationFormSheet)
# From any screen (same as `open_root_screen`)
open HomeScreen.new(nav_bar: true), close_all: true
# Opening a screen in a different tab or split view screen
open DetailScreen.new, in_tab: "Tab name" # if you're in a tab bar
open MasterScreen, in_master: true # if you're in a split view (opened in current navigation controller if not)
open DetailScreen, in_detail: true # if you're in a split view (opened in current navigation controller if not)
# Opening a screen with a custom navigation_controller class. (Defaults to PM::NavigationController)
class MyNavigationController < PM::NavigationController; end
open HomeScreen.new(nav_bar: true, nav_controller: MyNavigationController), close_all: true
# Opens a screen with a navigation controller but with the navigation bar hidden
open HomeScreen.new(nav_bar: true, hide_nav_bar: true) # Edge feature
```
##### Setting screen accessors
Any writable attribute (accessor, setter methods etc.) in `screen` can also be set in the `new` hash argument.
```ruby
class HomeScreen < PM::Screen
def profile_button_tapped
open ProfileScreen.new(user: @current_user)
end
end
class ProfileScreen < PM::Screen
attr_accessor :user
def on_load
puts user # => @current_user object
end
end
```
#### open_modal(screen, args = {})
Opens a modal screen. Same as `open HomeScreen, modal: true`
#### should_autorotate
(iOS 6+) return true/false if screen should rotate.
Defaults to true.
#### should_rotate(orientation)
(iOS 5) Return true/false for rotation to orientation. Tries to resolve this automatically
from your `UISupportedInterfaceOrientations` setting. You normally don't override this method.
#### supported_orientation?(orientation)
Returns whether `UISupportedInterfaceOrientations` includes the given orientation.
```ruby
supported_orientation?(UIInterfaceOrientationMaskPortrait)
supported_orientation?(UIInterfaceOrientationMaskLandscapeLeft)
supported_orientation?(UIInterfaceOrientationMaskLandscapeRight)
supported_orientation?(UIInterfaceOrientationMaskPortraitUpsideDown)
```
#### supported_orientations
Returns the value for `UISupportedInterfaceOrientations`.
#### will_rotate(orientation, duration)
Runs just before the device is rotated.
#### on_rotate
Runs just after the device is rotated.
#### supported_device_families
Returns either `:iphone` or `:ipad`. Should probably be named `current_device_family` or something.
#### first_screen?
Boolean representing if this is the first screen in a navigation controller stack.
```ruby
def on_appear
self.first_screen? # => true | false
end
```
---
### Class Methods
#### title(new_title)
Sets the default text title for all of this screen's instances
```ruby
class MyScreen < PM::Screen
title "Some screen"
# ...
end
```
#### title_view(new_title_view)
Sets an arbitrary view as the nav bar title.
```ruby
class MyScreen < PM::Screen
title_view UILabel.new
# ...
end
```
#### title_image(new_image)
Sets an arbitrary image as the nav bar title.
```ruby
class MyScreen < PM::Screen
title_image "image.png"
# ...
end
```
#### status_bar(style=nil, args={animation: UIStatusBarAnimationSlide})
Set the properties of the applications' status bar. Options for style are: `:none`, `:light` and `:default`. The animation argument should be a `UIStatusBarAnimation` (or `:none` / `:fade` / `:slide`) and is used to hide or show the status bar when appropriate and defaults to `:slide`.
```ruby
class MyScreen < PM::Screen
status_bar :none, {animation: :fade}
# ...
end
class MyScreenWithADarkColoredNavBar < PM::Screen
status_bar :light
# ...
end
```
---
### Accessors
#### parent_screen
References the screen immediately before this one in a navigation controller *or* the presenting
screen for modals. You should set this yourself if you're doing something funky like `addChildViewController`.
```ruby
def on_appear
self.parent_screen # => PM::Screen instance
end
```
#### view
The main view for this screen.
#### bounds
Alias for self.view.bounds
#### frame
Alias for self.view.frame

View File

@@ -0,0 +1,69 @@
### Contents
* [Usage](?#usage)
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
### Usage
```ruby
class AppDelegate < PM::Delegate
def on_load(app, options)
open_split_screen MenuScreen.new(nav_bar: true), DetailScreen.new
end
end
```
### Methods
#### open_split_screen(master, detail, args = {})
*iPad apps only*
Opens a UISplitScreenViewController with the specified screens. Usually opened in the AppDelegate as the root view controller.
```ruby
def on_load(app, options)
open_split_screen MasterScreen, DetailScreen, {
item: "split-icon", # tab bar item
title: "Split Screen Title",
button_title: "Some other title"
}
end
```
#### create_split_screen(master, detail, args={})
Creates a `PM::SplitViewController` (a `UIViewController` subclass) and returns it. Good for tabbed interfaces.
```ruby
def on_load(app, options)
@split = create_split_screen(MenuScreen.new(nav_bar: true), DetailScreen)
open_tab_screen @split, AboutScreen, ContactScreen
end
```
### Class Methods
*None for this module*
### Accessors
#### split_screen
References the containing split screen, if any.
```ruby
# in AppDelegate#on_load...
open_split_screen LeftScreen, RightScreen
# ...
class LeftScreen < PM::Screen
def on_appear
self.split_screen # => PM::SplitViewController instance
self.split_screen.master_screen # => LeftScreen
self.split_screen.detail_screen # => RightScreen
end
end
```

View File

@@ -0,0 +1,116 @@
PM::Styling is automatically included in many of the objects in ProMotion, such as `PM::Screen`, `PM::TableScreen`, and `PM::Delegate`. It gives you a simple way to apply a hash of attributes and values to a view (or any object that has setters, actually).
PM::Styling is *not* meant to be a full featured styling system. For that, you should use MotionKit or RMQ or some other styling system. This is just for simple applications.
### Contents
* [Usage](?#usage)
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
### Usage
```ruby
class MyScreen < PM::Screen
def on_load
set_attributes self.view, {
background_color: hex_color("#FB3259")
}
add UILabel.new, {
text: "My text",
frame: [[ 50, 150 ], [ 200, 50 ]],
background_color: rgba_color(32, 32, 32, 0.5)
}
add UIButton.new, {
frame: [[ 50, 250 ], [ 200, 50 ]],
"setTitle:forState:" => [ "My title", UIControlStateNormal ]
}
end
end
```
### Methods
#### add(view, attrs = {})
Adds the view to the screen after applying the attributes. Attributes are converted to camel case if necessary. `attrs` is usually either a hash, method call that returns a hash, or the name of a method call (in the form of a `:symbol`) that returns the hash.
```ruby
add UIInputView.new, {
background_color: UIColor.grayColor,
accessibility_label: "My input view",
frame: CGRectMake(10, 10, 300, 40)
}
# or use a symbol which calls a method
def my_input_style
{
background_color: UIColor.grayColor,
accessibility_label: "My input view",
frame: [[10, 10], [300, 40]],
}
end
add UIInputView.new, :my_input_style # will call my_input_style to get the hash
```
#### remove(view)
Removes the view from the superview.
```ruby
@input = UITextInput.new
add @input
remove @input
```
#### hex_color(str)
Creates a UIColor from a hex string. The # is optional.
```ruby
hex_color("#75D155") # => UIColor instance
```
#### rgb_color(r, g, b)
Creates a UIColor from red, green, and blue levels.
```ruby
rgb_color(23, 54, 21)
```
#### rgba_color(r, g, b, a)
Creates a UIColor with alpha setting from red, green, blue, and alpha levels.
```ruby
rgba_color(23, 54, 21, 0.25)
```
#### content_height(view)
Returns the height necessary to contain all of the visible subviews for `view`.
```ruby
add UILabel.new, { frame: [[ 0, 0 ], [ 150, 100 ]]
content_height(self.view) # => 100
```
#### content_width(view) - `edge`
Returns the width necessary to contain all of the visible subviews for `view`.
```ruby
add UILabel.new, { frame: [[ 0, 0 ], [ 150, 100 ]]
content_width(self.view) # => 150
```
### Class Methods
*None for this module*
### Accessors
*None for this module*

View File

@@ -0,0 +1,81 @@
<strong>Customizing:</strong> if you're getting crazy deep into styling your table cells,
you really should be subclassing them and specifying that new class in <code>:cell_class</code>. But, if you *really* want to know what ProMotion can do, here's an example format using nearly all available options:
```ruby
def table_data
[{
title: "Group Title",
title_view: MyCustomSection,
title_view_height: 50,
cells: [{
# Title
title: "Full featured cell",
subtitle: "This is my subtitle",
# Search: you can specify additional search terms
search_text: "Will match title and these words too!",
# Tap action, passed arguments
action: :tapped_cell_1,
long_press_action: :long_pressed_cell_1, # requires `longpressable`
arguments: { data: [ "lots", "of", "data" ] },
# The UITableViewCell
cell_style: UITableViewCellStyleSubtitle,
cell_identifier: "my-custom-cell-id", # ProMotion sets this for you intelligently
cell_class: PM::TableViewCell,
selection_style: UITableViewCellSelectionStyleGray, # or: :none, :blue, :gray, :default
# View attributes.
height: 50, # manually changes the cell's height
# Cell properties. You can add any writeable properties you want in here and they'll
# be applied to the cell instance with `set_attributes`.
# Alias is `style:` (but this is discouraged and could be deprecated at some point)
properties: { # (Edge change, use `style:` in ProMotion 2.0.x)
masks_to_bounds: true,
background_color: UIColor.whiteColor, # Creates a UIView for the backgroundView
},
# Accessory views (new in 1.0)
accessory: {
view: :switch, # UIView or :switch
value: true, # whether it's "checked" or not
action: :accessory_switched,
arguments: { some_arg: true } # :value is passed in if a hash
},
# Accessory Type
# Sets the UITableViewCell's accessoryType property
# Accepts UITableViewCellAccessory or any of the following symbols:
# :none, :disclosure_indicator, :disclosure_button, :checkmark, :default
accessory_type: :none,
# Swipe-to-delete
editing_style: :delete, # (can be :delete, :insert, or :none)
# Moveable Cell
moveable: true # can also be false or :section
# Selection
keep_selection: true, # specifies whether the cell automatically deselects after touch or not
# Images
image: {
image: "something", # PM will do `UIImage.imageNamed("something")` for you
radius: 15 # radius is optional
},
# You can also specify an image with just a UIImage or a String
# image: UIImage.imageNamed("something"),
# image: "something",
remote_image: { # remote image, requires JMImageCache CocoaPod
url: "http://placekitten.com/200/300",
placeholder: "some-local-image", # NOTE: this is required!
size: 50,
radius: 15,
content_mode: :scale_aspect_fill
}
}]
}]
end
```

View File

@@ -0,0 +1,417 @@
### Contents
* [Usage](?#usage)
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
### Usage
ProMotion::TableScreen allows you to easily create lists or "tables" as iOS calls them. It's a subclass of [UITableViewController](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewController_Class/Reference/Reference.html) and has all the goodness of [PM::Screen](https://github.com/clearsightstudio/ProMotion/wiki/API-Reference:-ProMotion::Screen) with some additional magic to make the tables work beautifully.
|Table Screens|Grouped Tables|Searchable|Refreshable|
|---|---|---|---|
|![ProMotion TableScreen](https://f.cloud.github.com/assets/1479215/1534137/ed71e864-4c90-11e3-98aa-ed96049f5407.png)|![Grouped Table Screen](https://f.cloud.github.com/assets/1479215/1589973/61a48610-5281-11e3-85ac-abee99bf73ad.png)|![Searchable](https://f.cloud.github.com/assets/1479215/1534299/20cc05c6-4c93-11e3-92ca-9ee39c044457.png)|![Refreshable](https://f.cloud.github.com/assets/1479215/1534317/5a14ef28-4c93-11e3-8e9e-f8c08d8464f8.png)|
```ruby
class TasksScreen < PM::TableScreen
title "Tasks"
refreshable
searchable placeholder: "Search tasks"
row_height :auto, estimated: 44
def on_load
@tasks = []
load_async
end
def table_data
[{
cells: @tasks.map do |task|
{
title: task.title,
subtitle: task.description,
action: :edit_task,
arguments: { task: task }
}
end
}]
end
def on_refresh
load_async
end
def load_async
# Assuming we're loading tasks from some cloud service
Task.async_load do |tasks|
@tasks = tasks
stop_refreshing
update_table_data
end
end
end
```
Example of a `PM::GroupedTableScreen`: https://gist.github.com/jamonholmgren/382a6cf9963c5f0b2248
### Methods
#### table_data
Method that is called to get the table's cell data and build the table.
It consists of an array of cell sections, each of which contain an array of cells.
```ruby
def table_data
[{
title: "Northwest States",
cells: [
{ title: "Oregon", action: :visit_state, arguments: { state: @oregon }},
{ title: "Washington", action: :visit_state, arguments: { state: @washington }}
]
}]
end
```
You'll often be iterating through a group of objects. You can use `.map` to easily build your table:
```ruby
def table_data
[{
title: "States",
cells:
State.all.map do |state|
{
title: state.name,
action: :visit_state,
arguments: { state: state }
}
end
}]
end
def visit_state(args={})
PM.logger.info args[:state] # => instance of State
end
```
View the [Reference: All available table_data options](https://github.com/clearsightstudio/ProMotion/wiki/Reference:-All-available-table_data-options) for an example with all available options.
#### Accessory Views
`TableScreen` supports the `:switch` accessory and custom accessory views.
![accessory](http://clrsight.co/jh/accessory.png)
Using Switches:
```ruby
{
title: "Switch With Action",
accessory: {
view: :switch,
value: true, # switched on
action: :foo
}
}, {
title: "Switch with Action and Parameters",
accessory: {
view: :switch,
action: :foo,
arguments: { bar: 12 }
}
}, {
title: "Switch with Cell Tap, Switch Action and Parameters",
accessory: {
view: :switch,
action: :foo,
arguments: { bar: 3 },
},
action: :fizz,
arguments: { buzz: 10 }
}
```
Using a custom `accessory` view:
```ruby
button1 = set_attributes UIButton.buttonWithType(UIButtonTypeRoundedRect), {
"setTitle:forState:" => [ "A", UIControlStateNormal ]
}
button2 = set_attributes UIButton.buttonWithType(UIButtonTypeRoundedRect), {
"setTitle:forState:" => [ "B", UIControlStateNormal ]
}
button1.frame = [[ 0, 0 ], [ 20, 20 ]]
button2.frame = [[ 0, 0 ], [ 20, 20 ]]
[{
title: "",
cells: [{
title: "My Cell with custom button",
accessory: { view: button1 }
}, {
title: "My Second Cell with another custom button",
accessory: { view: button2 }
}]
}]
```
*However*, adding custom accessory views like this is not recommended unless your use case is very simple. Instead, subclass `PM::TableViewCell` and provide setters that create the subviews or accessoryView that you want. You can find a blog post demonstrating how this is done here: http://jamonholmgren.com/creating-a-custom-uitableviewcell-with-promotion
#### update_table_data
Causes the table data to be refreshed, such as when a remote data source has
been downloaded and processed.
```ruby
class MyTableScreen < PM::TableScreen
def on_load
MyItem.pull_from_server do |items|
@table_data = [{
cells: items.map do |item|
{
title: item.name,
action: :tapped_item,
arguments: { item: item }
}
end
}]
update_table_data
end
end
def table_data
@table_data ||= []
end
def tapped_item(item)
open ItemDetailScreen.new(item: item)
end
end
```
#### table_data_index
This method allows you to create a "jumplist", the index on the right side of the table
A good way to do this is to grab the first letter of the title of each section:
```ruby
def table_data_index
# Returns an array of the first letter of the title of each section.
table_data.collect{ |section| (section[:title] || " ")[0] }
end
```
#### on_cell_deleted(cell)
If you specify `editing_style: :delete` in your cell, you can swipe to reveal a delete button on that cell. When you tap the button, the cell will be removed in an animated fashion and the cell will be removed from its respective `table_data` section.
If you need a callback for every cell that's deleted, you can implement the `on_cell_deleted(cell)` method, where `cell` is the attributes form the original cell data object. Returning `false` will cancel the delete action. Anything else will allow it to proceed.
Example:
```ruby
def on_cell_deleted(cell)
if cell[:arguments][:some_value] == "something"
App.alert "Sorry, can't delete that row." # BubbleWrap alert
false
else
RemoteObject.find(cell[:arguments][:id]).delete_remotely
true # return anything *but* false to allow deletion in the UI
end
end
```
#### delete_row(indexpath, animation=nil)
You can call `delete_row(indexpath, animation)` to delete. Both the UI and the internal
data hash are updated when you do this.
```ruby
def my_delete_method(section, row)
# the 2nd argument is optional. Defaults to :automatic
delete_row(NSIndexPath.indexPathForRow(row, inSection:section), :fade)
end
```
#### table_header_view
You can give the table a custom header view (this is different from a section header view) by defining:
```ruby
def table_header_view
# Return a UIView subclass here and it will be set at the top of the table.
end
```
This is useful for information that needs to only be at the very top of a table.
---
### Class Methods
#### searchable(placeholder: "placeholder text")
Class method to make the current table searchable.
```ruby
class MyTableScreen < PM::TableScreen
searchable placeholder: "Search This Table"
end
```
![Searchable Image](http://clrsight.co/jh/Screen_Shot_2014-06-21_at_9.01.09_PM.png)
You can prevent any table cell from being included in search results by setting the cell attribute `searchable` to `false` like this:
```ruby
[{
title: "This cell will appear in the search",
},{
title: "This cell will not",
searchable: false
}]
```
You can supply additional textual data that you want to be searchable but not display anywhere on the cell by setting the cell attribute `search_text` to a string. Cells with `search_text` will display in search results if the search term matches either the `title` *or* the `search_text` attributes.
```ruby
[{
title: "Searchable via Title"
},{
title: "Searchable via Title",
search_text: "and will match these words too!"
}]
```
If you need to know if the current table screen is being searched, `searching?` will return `true` if the user has entered into the search bar (even if there is no search results yet).
To get the text that a user has entered into the search bar, you can call `search_string` for what the data was actually searched against and `original_search_string` to get the actual text the user entered. These methods will return back a `String` or a falsey object (`nil` or `false`).
You can also implement methods in your `TableScreen` that are called when the search starts or ends:
```ruby
def will_begin_search
puts "the user tapped the search bar!"
end
def will_end_search
puts "the user tapped the 'cancel' button!"
end
```
#### row_height(height, options = {})
Class method to set the row height for each UITableViewCell. You can use iOS 8's 'automatic' row height feature by passing `:auto` as the first argument.
```ruby
class MyTableScreen < PM::TableScreen
row_height :auto, estimated: 44
end
```
#### refreshable(options = {})
Class method to make the current table have pull-to-refresh. All parameters are optional.
If you do not specify a callback, it will assume you've implemented an <code>on_refresh</code>
method in your tableview.
![](https://camo.githubusercontent.com/fa0ac0a77e6170cca72f03f9ad2273c5b165e83d/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313437393231352f313533343331372f35613134656632382d346339332d313165332d386539652d6638633038643834363466382e706e67)
```ruby
class MyTableScreen < PM::TableScreen
refreshable callback: :on_refresh,
pull_message: "Pull to refresh",
refreshing: "Refreshing data…",
updated_format: "Last updated at %s",
updated_time_format: "%l:%M %p"
def on_refresh
MyItems.pull_from_server do |items|
@my_items = items
end_refreshing
update_table_data
end
end
end
```
If you initiate a refresh event manually by calling `start_refreshing`, the table view will automatically scroll down to reveal the spinner at the top of the table.
#### indexable
This simply takes the first letter of each of your section titles and uses those for the "jumplist" on the right side of your table screen.
```ruby
class MyTable < PM::TableScreen
indexable
# ...
end
```
#### longpressable
This will allow you to specify an additional "long_press_action" on your table cells.
```ruby
class MyTable < PM::TableScreen
longpressable
def table_data
[{
cells: [{
title: "Long press cell",
action: :normal_action,
long_press_action: :long_press_action,
arguments: { foo: "Will be sent along with either action as arguments" }
}]
}]
end
end
```
---
### Accessors
You get all the normal accessors of `PM::Screen`, but no documented TableScreen accessors are available.
---
### Moveable cells
You can specify cells to be moveable in each individual cell hash. If you want the cells to only be moveable within their own section, define `moveable: :section` in each cell hash.
When you want the user to see the moveable drag handles, call `toggle_edit_mode` or `edit_mode(enabled:true)`.
Finally, define a method:
```ruby
def on_cell_moved(args)
# Do something here
end
```
The argument passed to `on_cell_moved` is a hash in the form of:
```ruby
{
:paths => {
:from => #<NSIndexPath:0xb777380>,
:to => #<NSIndexPath:0xb777390>
},
:cell => {
:title => "Whatever",
:moveable => true
# Your other cell attributes
}
}
```

View File

@@ -0,0 +1,78 @@
`ProMotion::Tabs` is a module that is automatically included in `PM::Delegate` and `PM::Screen`. It includes methods and functionality dealing with `UITabBarController` and `UITabBarItem`.
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
### Methods
#### set_tab_bar_item(args)
**NOTE: `icon` and `system_icon` have been deprecated and replaced by `item` and `system_item`.**
Creates the tab that is shown in a tab bar item.
Arguments: `{ item: "imagename", system_item: UITabBarSystemItemContacts, title: "tabtitle" }`
`item` can be a string, in which case it should exist in your resources folder. But `item` can also be a UIImage, if you prefer to create one yourself. Additionally, Apple adds a gradient to every `UITabBarItem`. In order to prevent this, or to control the state of the selected & unselected item, you can pass a hash into `item` like so (where variable `myUIImage` is an instance of `UIImage`):
```ruby
set_tab_bar_item { item: { selected: my_image, unselected: my_image }, title: "tabtitle" }
```
It's recommended to use this method in your `on_init` method OR set it using the class method `tab_bar_item` (below). `on_load` won't be called until you actually load the tab, which is too late.
```ruby
def on_init
set_tab_bar_item item: "custom_item_5", title: "Custom"
set_tab_bar_item system_item: :more
# :more, :favorites, :featured, :top_rated, :recents, :contacts,
# :history, :bookmarks, :search, :downloads, :most_recent, :most_viewed
end
```
#### open_tab_bar(*screens)
Opens a UITabBarController with the specified screens as the **root view controller** of the current app.
iOS doesn't allow opening a UITabBar as a sub-view. The current screen will be deallocated unless included
as one of the screens in the tab bar.
```ruby
def on_load(app, options)
open_tab_bar HomeScreen, AboutScreen.new(nav_bar: true), ThirdScreen, HelpScreen
end
```
#### open_tab(tab)
Opens the tab where the "string" title matches the passed in `tab` string. You can also
provide a number (starting at 0) and the tab with that index will be opened.
```ruby
open_tab "About"
open_tab 3 # fourth tab is opened
```
### Class Methods
#### tab_bar_item(args={})
Class method that sets the screen's default tab bar item.
```ruby
class TabScreen < PM::Screen
title "Tab"
tab_bar_item title: "Tab Item", item: "list"
end
```
### Accessors
#### tab_bar
Contains a reference to the current screen's tab bar controller.
#### tab_bar_item
Contains the settings hash used to set up the tab bar item. If you set this manually,
make sure to call `refresh_tab_bar_item` right afterward.

View File

@@ -0,0 +1,133 @@
### Contents
* [Usage](?#usage)
* [Methods](?#methods)
* [Class Methods](?#class-methods)
* [Accessors](?#accessors)
---
### Usage
*Has all the methods of PM::Screen*
Easily create a web-based view from an external URL, internal HTML file, or HTML string.
```ruby
open MyWebScreen.new(nav_bar: true, external_links: false)
```
```ruby
class MyWebScreen < PM::WebScreen
title "Title of Screen"
def content
# You can return:
# 1. A reference to a file placed in your resources directory
# 2. An instance of NSURL
# 3. An arbitrary HTML string
"AboutView.html"
end
def load_started
# Optional
# Called when the request starts to load
end
def load_finished
# Optional
# Called when the request is finished
end
def load_failed(error)
# Optional
# "error" is an instance of NSError
end
end
```
#### Initialization Options
```ruby
external_links: false
```
**Default:** false
**Behavior:** true causes all links clicked in the `WebScreen` to open in Safari (or Chrome).
```ruby
detector_types: [:none, :phone, :link, :address, :event, :all]
```
**Default:** :none
**Behavior:** An array of any of the above values to specify what sort of detectors you'd like the webview to auto-link for you. [You can read more about `UIDataDetector`s here](http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKitDataTypesReference/Reference/reference.html).
### Opening External Links in Chrome
If you want your users to have links open in the Google Chrome iOS app, simply add this to your `Rakefile`:
```ruby
app.pods do
pod 'OpenInChrome'
end
```
This will change the default behavior of your app to check and see if Chrome is installed and if so, open the link in Chrome. Otherwise, the links will open in Safari.
### Methods
#### set_content(content)
Causes the `WebScreen` to load new content (where `content` is a string reference to a local file in the `resources` directory or an `NSURL` or an arbitrary bit of HTML).
#### html
Returns the current HTML contained in the `WebScreen` as a string.
#### can_go_back
Returns a `boolean` if the user can navigate backwards (e.g., if there's anything in the history).
#### can_go_forward
Returns a `boolean` if the user can navigate forwards.
#### back
Navigates back one page.
#### forward
Navigates forward one page.
#### refresh
Refreshes the current URL. Alias: `reload`
#### stop
Cancels the current URL request and stops loading the page.
---
### Class Methods
None.
---
### Accessors
#### webview
Reference to the UIWebView that is automatically created.
#### external_links
TODO
#### detector_types
TODO

65
docs/Add-On-Gems.md Normal file
View File

@@ -0,0 +1,65 @@
## ProMotion Add-On Gems
ProMotion's simple philosophy and community make it attractive to those wanting to extend its capabilities. Rather than add to the core gem itself, consider making an add-on gem! We'll list it here if you do.
### ProMotion-form
ProMotion-form provides a PM::FormScreen, similar to Formotion, but much lighter and more compatible with ProMotion.
GitHub: [https://github.com/clearsightstudio/ProMotion-form](https://github.com/clearsightstudio/ProMotion-form)
```ruby
gem "ProMotion", "~> 2.0"
gem "ProMotion-form"
```
![form](http://clrsight.co/jh/Screen_Shot_2014-08-29_at_4.03.13_PM.png?+)
### ProMotion-map
ProMotion-map provides a PM::MapScreen, extracted from ProMotion core in 2.0+.
GitHub: [https://github.com/clearsightstudio/ProMotion-map](https://github.com/clearsightstudio/ProMotion-map)
```ruby
gem "ProMotion", "~> 2.0"
gem "ProMotion-map"
```
![ProMotion-map](https://camo.githubusercontent.com/c7c076b8a919b4bb44c82443f307a3143b82c939/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313437393231352f313533343632382f66376462663765382d346339372d313165332d383831372d3463326135383832343737312e706e67)
### ProMotion-push
ProMotion-push is push notification support, extracted from ProMotion core in 2.0+.
GitHub: [https://github.com/clearsightstudio/ProMotion-push](https://github.com/clearsightstudio/ProMotion-push)
```ruby
gem "ProMotion", "~> 2.0"
gem "ProMotion-push"
```
### ProMotion-menu
RubyMotion gem allowing you to easily setup a Facebook or Path style drawer menu easily with the ProMotion gem.
GitHub: [https://github.com/clearsightstudio/ProMotion-menu](https://github.com/clearsightstudio/ProMotion-menu)
```ruby
gem "ProMotion", "~> 2.0"
gem 'ProMotion-menu'
```
### ProMotion-formotion
Provides a ProMotion::FormotionScreen.
GitHub: [https://github.com/rheoli/ProMotion-formotion](https://github.com/rheoli/ProMotion-formotion)
```ruby
gem "ProMotion", "~> 2.0"
gem "ProMotion-formotion"
```

View File

@@ -0,0 +1,90 @@
ProMotion is designed to be as intuitive and Ruby-like as possible.
## Quick Setup (recommended)
Requirements:
* Licensed [RubyMotion](http://rubymotion.com) (2.29+ recommended)
* Xcode with command line tools installed
* Bundler (`gem install bundler`)
* CRuby 2.0.0+ (for executable)
```bash
gem install ProMotion #=> be sure to capitalize P and M here!
promotion new myapp
cd myapp
bundle
rake spec
rake
```
You should have a functioning ProMotion app!
## Manual Setup
Create a new RubyMotion project.
`motion create myapp`
Open the new folder in your favorite editor. Mine is Sublime, so I use `cd myapp; subl .` to open it.
Create a Gemfile and add the following lines:
```ruby
source "https://rubygems.org"
gem "rake"
gem "ProMotion", "~> 2.0.0"
```
Run `bundle` in Terminal to install ProMotion.
```
Fetching gem metadata from https://rubygems.org/....
Resolving dependencies...
Using bundler 1.6.2
Using rake 10.3.2
Using methadone 1.4.0
Using ProMotion 2.0.0
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
```
Go into your app/app_delegate.rb file and replace *everything* with the following:
```ruby
class AppDelegate < PM::Delegate
def on_load(app, options)
open HomeScreen.new(nav_bar: true)
end
end
```
Create a folder in `/app` named `screens`. Create a file in that folder named `home_screen.rb`.
Now drop in this code in that file:
```ruby
class HomeScreen < PM::Screen
title "Home"
def on_load
set_attributes self.view, {
background_color: hex_color("#FFFFFF")
}
end
end
```
Run `rake`. You should now see the simulator open with your home screen and a navigation bar. Congrats!
### Next steps
* Read through the rest of the API documentation on the right sidebar.
Here are a few tutorials to follow.
* [Getting Started with MotionKit and ProMotion](http://jamonholmgren.com/getting-started-with-motionkit-and-promotion)
* [Building an ESPN App Using RubyMotion, ProMotion, and TDD](http://jamonholmgren.com/building-an-espn-app-using-rubymotion-promotion-and-tdd)

View File

@@ -0,0 +1,66 @@
You can make your own `PM::Screen` from a custom view controller easily.
### Custom UIViewController
Due to a RubyMotion limitation, we can't override built-in methods with a module. Here are the main methods you'll want to override. You should be able to just copy & paste most of the code below (customize the `self.new` method).
```ruby
class EventsScreen < JHAwesomeViewController
include ProMotion::ScreenModule
# Customize this method for your preferred initializer
def self.new(args = {})
s = self.alloc.initWithAwesomeName(args[:name])
s.screen_init(args) # Important for ProMotion stuff!
s
end
# Highly recommended that you include these methods below
def loadView
self.respond_to?(:load_view) ? self.load_view : super
end
def viewDidLoad
super
self.view_did_load if self.respond_to?(:view_did_load)
end
def viewWillAppear(animated)
super
self.view_will_appear(animated) if self.respond_to?("view_will_appear:")
end
def viewDidAppear(animated)
super
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
end
def viewWillDisappear(animated)
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
super
end
def viewDidDisappear(animated)
self.view_did_disappear(animated) if self.respond_to?("view_did_disappear:")
super
end
def shouldAutorotateToInterfaceOrientation(orientation)
self.should_rotate(orientation)
end
def shouldAutorotate
self.should_autorotate
end
def willRotateToInterfaceOrientation(orientation, duration:duration)
self.will_rotate(orientation, duration)
end
def didRotateFromInterfaceOrientation(orientation)
self.on_rotate
end
end
```

View File

@@ -0,0 +1 @@
[View the PM::PushNotification](https://github.com/clearsightstudio/ProMotion/wiki/API-Reference:-ProMotion::PushNotification) documentation.

View File

@@ -0,0 +1,7 @@
By [Jamon Holmgren](http://twitter.com/jamonholmgren), ProMotion creator and owner of [ClearSight Studio](http://www.clearsightstudio.com/)
**NOTE: This guide has been deprecated. We recommend using a styling/layout library like [MotionKit](https://github.com/rubymotion/motion-kit) or [RMQ](https://github.com/infinitered/rmq).**
Here's a better guide: [http://jamonholmgren.com/getting-started-with-motionkit-and-promotion](http://jamonholmgren.com/getting-started-with-motionkit-and-promotion)
Old article, for reference, is in the deprecated repo: [https://github.com/jamonholmgren/promotion-styling](https://github.com/jamonholmgren/promotion-styling)

48
docs/Home.md Normal file
View File

@@ -0,0 +1,48 @@
## Welcome to the ProMotion wiki!
Documentation is targeting ProMotion 2.2.0. Any exceptions will be noted.
If you have a problem with *any* of the documentation, *please* [open an issue](https://github.com/clearsightstudio/ProMotion/issues) so we can resolve it quickly.
### Getting Started
#### [Getting Started with ProMotion](https://github.com/clearsightstudio/ProMotion/wiki/Guide:-Getting-Started)
Everything you need to know to install ProMotion and create your first iPhone app.
### Goal/Philosophy/Roadmap
ProMotion's goal is to create a **memorable**, **simple**, **intuitive**, and **enjoyable** API for
rapidly developing screen-based iPhone and iPad apps.
* **Memorable:** The API should be easy to memorize. Developers shouldn't have to be digging through documentation all the time to build out iOS apps.
* **Simple:** The API should utilize simple language, such as `open`, `close`, `add`, `remove`. Cocoa Touch is far too verbose.
* **Intuitive:** The API should make sense, even to developers unfamiliar with ProMotion.
* **Enjoyable:** The API should make developers feel like they're programming with purpose rather than implementing boilerplate. It should make iPhone and iPad development fun.
The philosophy behind ProMotion is to be a **friendly and welcoming community** to new iOS/RubyMotion developers. Many new ProMotion developers come from the web development world (Ruby on Rails, PHP) and have a lot of questions. Others come from non-English-speaking countries and may have difficulty understanding the documentation. **The more experienced ProMotion developers are encouraged to answer new developers' questions in good humor and with encouragement and patience.**
The current roadmap is to continue evolving the code's quality, performance, and maintainability. No major new features are currently planned. Most new features will be implemented in the form of [add-on gems](./Add-On-Gems), of which there are several already.
I don't want ProMotion to become bloated with little-used features. The features we've implemented so far have been commonly used ones that aren't easily available in other compatible and popular RubyMotion libraries. We will carefully consider pull requests, but the measure of whether something is accepted or not depends not only on its code quality but also its relevance and future maintainability.
*Visit the links in the sidebar to learn more about ProMotion's API.*
## Primary Contributors
|Contributor|Twitter|
|---|---|
|Jamon Holmgren|[@jamonholmgren](https://twitter.com/jamonholmgren)|
|Mark Rickert|[@markrickert](https://twitter.com/markrickert)|
|Silas J. Matson|[@silasjmatson](https://twitter.com/silasjmatson)|
|Ryan Linton|[@ryanlntn](https://twitter.com/ryanlntn)|
## Alumni
Matt Brewer [@macfanatic](https://twitter.com/macfanatic)
Many others contribute every day!

View File

@@ -0,0 +1,165 @@
ProMotion 2.0 is mostly backwards-compatible to ProMotion 1.2, but there are a few things to look for in your app when you upgrade. Follow this guide and you shouldn't have any issues.
First, update your Gemfile:
```ruby
gem "ProMotion", "~> 2.0"
```
### PM::MapScreen and PM::PushNotification
If you're using a MapScreen or push notifications in your app, add either or both of these gems to your Gemfile right after ProMotion:
```ruby
gem "ProMotion-map"
gem "ProMotion-push"
```
If you were using PM::FormotionScreen, you can try using the ProMotion-formotion gem. Some people have had trouble with this third party gem, so if you have difficulty, feel free to open an issue there (I watch that repo). Another option is to convert over to the new [ProMotion-form](https://github.com/clearsightstudio/ProMotion-form) gem which is much more compatible with ProMotion.
## PM::Screen changes
### Check to make sure your `title`s are only strings
* `title` now only accepts a string. If you want to set an image or view, use `title_image` and `title_view`.
```ruby
class MyScreen < PM::Screen
title UILabel.new # don't do this
title UIImage.imageNamed("my-title") # don't do this
title "String" # good
title_view UILabel.new # good
title_image UIImage.imageNamed("my-title") # good
end
```
### Look for `on_create` and change to `on_init`
* Don't use `on_create` anymore. `on_init` is called about the same time that `on_create` used to be.
* Remove any calls to `super` in the new `on_init`.
```ruby
class MyScreen < PM::Screen
# bad
def on_create
# other stuff
super
end
# good
def on_init
# other stuff
end
end
```
### Look for `set_nav_bar_right_button` and `set_nav_bar_left_button`
* Use `set_nav_bar_button :left` and `set_nav_bar_button :right` instead.
```ruby
# Bad
set_nav_bar_right_button "Help", action: :help
# Good
set_nav_bar_button :right, title: "Help", action: :help
```
### Look for any `present_modal_view_controller` calls
* You really shouldn't have been using this undocumented method, and its API has changed. Instead, use `open_modal`.
### Look for any `on_load` methods that set the view
* We've moved `on_load` to fire after the view is created
* If you need to set the root view, do so in the new `load_view` method instead
```ruby
def on_load
self.view = UIView.new # bad
end
def load_view
self.view = UIView.new # good
end
def on_load
self.view.backgroundColor = UIColor.redColor # good
end
```
## PM::TableScreen changes
### In table cells, move arbitrary styling attributes into a `style:` hash
* We now only apply attributes in the `style:` hash to the cell.
* `background_color` is still applied due to some weirdness in UIKit's handling of cell background colors.
```ruby
def table_data
[{
cells: [{
# stays the same
title: "My title",
background_color: UIColor.blackColor,
# bad -- these won't be applied to the cell
accessibility_label: "My label",
background_view: MyBGView.new,
# good -- these will be applied to the cell
style: {
accessibility_label: "My label",
background_view: MyBGView.new,
}
}]
}]
end
```
### Look for any `subviews:` in your table hashes
* We no longer support this feature
* Instead, subclass `PM::TableViewCell` and make your own subviews there
### Look for cell tap actions that rely on the `[:cell]` data being auto-passed in
* We no longer include the `[:cell]` data in the argument hash passed through on tap.
* If you need this info, replicate it in the `arguments:` hash yourself.
```ruby
def table_data
[{
cells: [{
title: "My title",
action: :some_action,
arguments: { my_title: "My title" }
}]
}]
end
def some_action(args={})
puts args[:cell][:title] # Bad -- won't work
puts args[:my_title] # Good
end
```
## PM::Styling changes
### Look for add_element, add_view, remove_element, remove_view
* These aliases have been removed. Use `add` and `remove` instead.
### Removed easy attributes
* Not too many people knew about these, but there were some `margin:` helpers and whatnot in PM::Styling (`add` and `set_attributes`). These have been removed.
* If your views are not visible or screwed up, you were probably relying on one of these. File an issue and I'll help you migrate.
## Problems?
Get in touch by filing an issue. We'll be there to help you out!
Jamon Holmgren
August 2, 2014

125
docs/ProMotion Apps.md Normal file
View File

@@ -0,0 +1,125 @@
### RubyMotion Yelp
[View Source on GitHub](https://github.com/faizaanshamsi/rubymotion_yelp)
[![rm yelp](http://media.clearsightstudio.com/jamon/iOS_Simulator__iPhone_Retina_4inch__iOS_7.0.3_11B508_20140114_091423.jpg)](https://github.com/faizaanshamsi/rubymotion_yelp)
> Simple Yelp search using Rubymotion. My First Rubymotion app!
>
> Uses Yelp API v1.0 so search by location. Allows you to filter results in a table view. Clicking on a results will redirect you to the mobile yelp page.
By [@faizaanshamsi](https://twitter.com/faizaanshamsi).
### Brewers Association Styles
[![Brewers Association Styles](http://a3.mzstatic.com/us/r30/Purple6/v4/65/83/4e/65834e58-9872-a839-98db-bdbeda61de45/mzl.yaxkfpsv.175x175-75.jpg)](http://www.mohawkapps.com/app/brewers-association-styles/)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/brewers-association-styles/id670470983?mt=8&uo=4&at=10l4yY&ct=promotionwiki)
Brewers Association Styles (by [Mohawk Apps](http://www.mohawkapps.com/)) is the _UNOFFICIAL_ go-to guide for all your beer style guide needs! The complete Brewers Association 2013 style guidelines in your pocket! The app is free (as in beer) and [open source](https://github.com/MohawkApps/BAStyleGuide).
### RainCloud
[![RainCloud](http://a1.mzstatic.com/us/r30/Purple4/v4/a1/83/60/a183608c-1bf4-172c-a17d-b71c1bc213d7/mzl.gdviwmld.175x175-75.jpg)](http://www.raincloudalerts.com/)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/raincloud/id632130365?mt=8)
RainCloud (by [@forrestgrant](https://twitter.com/forrestgrant)) is a free iPhone app that notifies you when critical cloud infrastructure services and APIs have downtime, performance issues, and other similar failures.
### Coowl
[![Coowl](http://a4.mzstatic.com/us/r1000/044/Purple/v4/eb/6f/5a/eb6f5ad5-e6b9-d76d-9165-4f568bc87bc3/mzl.exefkfxt.175x175-75.jpg)](https://itunes.apple.com/us/app/coowl/id657397623)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/coowl/id657397623)
Coowl (by [@puelocesar](https://twitter.com/puelocesar)) is a photo editing/effects app with a really well done menu system and sharing mechanism.
### BigDay! Reminder App
[![BigDay! Reminder app](http://a1.mzstatic.com/us/r1000/066/Purple2/v4/59/26/c7/5926c7fb-0a28-c770-ce10-5d3509edb06a/mzl.xauslwqp.175x175-75.jpg)](https://itunes.apple.com/us/app/bigday!/id571756685?ls=1&mt=8)
This was the genesis of ProMotion. [ClearSight Studio](http://www.clearsightstudio.com/) ([Jamon Holmgren](http://twitter.com/jamonholmgren)'s company) built the app for Kijome Software, a small app investment company. We extracted ProMotion from that code.
### TipCounter App
[![TipCounter](http://a1.mzstatic.com/us/r30/Purple/v4/49/f5/b4/49f5b434-07ac-7292-8437-556b3dc025d5/mzl.pitrhwco.175x175-75.jpg)](https://itunes.apple.com/us/app/tip-counter/id418749608?mt=8&ls=1)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/tip-counter/id418749608?mt=8&ls=1)
[TipCounter](http://www.tipcounterapp.com) was built by [Matt Brewer](https://github.com/macfanatic/) for bartenders and servers to easily track their tips and analyze income. Used ProMotion and the development was a lot of fun!
### BraillED
[![BraillED](http://a1.mzstatic.com/us/r30/Purple/v4/c7/79/6a/c7796a36-ef17-c056-073d-6ebea335ebff/mzl.frehfqca.175x175-75.jpg)](https://itunes.apple.com/us/app/brailled/id839690467?mt=8)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/brailled/id839690467?mt=8)
Explore the braille alphabet in a high contrast app designed specifically for the visually impaired. Audio cues and device vibrations aid in learning.
[BraillED](http://www.brailledapp.com) was created by [Matt Brewer](https://github.com/macfanatic/) and uses ProMotion, [motion-speech](https://github.com/macfanatic/motion-speech), [motion-launchpad](https://github.com/macfanatic/motion-launchpad), and more.
### Winston-Salem Crime Map
[![WSCrime](http://a2.mzstatic.com/us/r1000/086/Purple/v4/f4/8d/82/f48d82c7-68bb-933d-5db3-7f93357ddf7b/mzl.dndttxht.175x175-75.jpg)](http://www.mohawkapps.com/app/winston-salem-crime-map/)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/winston-salem-crime-map/id472546582?mt=8&uo=4&at=10l4yY&ct=promotionwiki)
Have an interest in crime statistics and locations? Live in Winston-Salem, NC? This hyper-local and [open source](https://github.com/MohawkApps/WSCrime) RubyMotion app uses a mixture of custom UIViewControllers and ProMotion for ease of setting attributes and adding views. Check it out [on the App Store](https://itunes.apple.com/us/app/winston-salem-crime-map/id472546582?mt=8&uo=4&at=10l4yY&ct=promotionwiki) or [fork it and contribute](https://github.com/MohawkApps/WSCrime)!
### BJCP Styles (OFFICIAL)
[![BJCPStyles](http://a5.mzstatic.com/us/r1000/004/Purple6/v4/d1/a9/66/d1a966cc-0b36-e528-d5cd-7bb3dd4df978/mzl.rfzwzkkg.175x175-75.jpg)](http://www.mohawkapps.com/app/bjcp-styles/)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/bjcp-styles/id293788663?mt=8&uo=4&at=10l4yY&ct=promotionwiki)
Now you have a full copy of the BJCP Style Guidelines at your finger tips! Whether you're a beer judge, a homebrewer, or an enthusiast, this free app will come in handy whenever you want a quick lookup of a style description.
Features include:
* Quick jump to a specific category using the index on the right.
* Full-text search of all guidelines!
* SRM spectrum graphic for each style!
* Swipe left and right for access to the next and previous style. (iPad only)
This application is open source! [Check out the source code](https://github.com/MohawkApps/BJCPStyleGuide)!
### Beer Judge
[![Beer Judge](http://a3.mzstatic.com/us/r1000/013/Purple4/v4/c0/4b/ff/c04bffc5-523f-bbe0-c22e-93283ee989db/mzl.ctvoovnz.175x175-75.jpg)](http://www.mohawkapps.com/app/beerjudge/)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/beer-judge/id666120064?mt=8&uo=4&at=10l4yY&ct=promotionwiki)
This app is the perfect companion for you at beer competitions!
* Use the Flavor Wheel to explore and help identify different off flavors and aromas in a beer.
* Tap and drag around the SRM Spectrum to identify the closest SRM to the beer you're judging.
* Use your device's camera to help you estimate a beer's SRM using the SRM Analysis tool! (SRM Analysis tool requires a device with camera capability.)
This application is open source! [Check out the source code](https://github.com/MohawkApps/BeerJudge)!
### Odorik
[![Odorik](http://a2.mzstatic.com/us/r1000/032/Purple4/v4/6d/0f/81/6d0f81bb-30eb-c37d-2d1e-83a3787abe1d/mzl.kzpndpmw.175x175-75.jpg)](https://itunes.apple.com/us/app/odorik/id682721789?mt=8)
[![App Store Link](https://a248.e.akamai.net/camo.github.com/9cbd2153e42bdb92ce53083d2a614989408ea054/687474703a2f2f722e6d7a7374617469632e636f6d2f696d616765732f7765622f6c696e6b6d616b65722f62616467655f61707073746f72652d6c72672e676966
)](https://itunes.apple.com/us/app/odorik/id682721789?ls=1&mt=8)
Odorik is an iOS application that allows you comfortably set up callbacks through your account with Czech VOIP provider of the same name, [Odorik.cz](http://Odorik.cz) (run by miniTEL s.r.o.).
It's open source!
[https://github.com/wejn/Odorik](https://github.com/wejn/Odorik)
More information: [http://wejn.com/ios/odorik/](http://wejn.com/ios/odorik/)
### Your app here
Tweet [@jamonholmgren](https://twitter.com/jamonholmgren) if you built an app in ProMotion and want it included here!

View File

@@ -0,0 +1,22 @@
## Tutorials
* [Getting Started with MotionKit and ProMotion](http://jamonholmgren.com/getting-started-with-motionkit-and-promotion)
* [Building an ESPN app with ProMotion and TDD](http://jamonholmgren.com/building-an-espn-app-using-rubymotion-promotion-and-tdd)
## Screencasts
*MotionInMotion requires a paid subscription, but is well worth the money)*
* MotionInMotion episode 8: [ProMotion](https://motioninmotion.tv/screencasts/8)
* MotionInMotion episode 9: [ProMotion + Formotion](https://motioninmotion.tv/screencasts/9)
## Articles
* [ClearSight blog: ProMotion for non-geeks](http://clearsightstudio.com/blog/2014/05/15/promotion-for-non-geeks/)
## Presentations
* Jamon Holmgren's talk at RubyMotion #inspect2014: [http://confreaks.com/videos/3813-inspect-going-pro-with-promotion-from-prototype-to-production](http://confreaks.com/videos/3813-inspect-going-pro-with-promotion-from-prototype-to-production) (video)
* Jamon Holmgren's appearance on MotionMeetup: [https://www.youtube.com/watch?v=rf7h-3AiMRQ](https://www.youtube.com/watch?v=rf7h-3AiMRQ) (video)
* Wouter de Vos: "RubyMotion and ProMotion" [http://www.slideshare.net/wrdevos/20140121-ruby-motionamsrb](http://www.slideshare.net/wrdevos/20140121-ruby-motionamsrb) (slides)
* mediatainment: [https://speakerdeck.com/mediatainment/rubymotion-with-promotion-and-teacup](https://speakerdeck.com/mediatainment/rubymotion-with-promotion-and-teacup) (slides)