README.md in rm-extensions-0.2.0 vs README.md in rm-extensions-0.3.0
- old
+ new
@@ -1,290 +1,14 @@
RMExtensions
-----------------
#### Extensions and helpers for dealing with various areas of rubymotion and iOS.
-## Equation-style AutoLayout Constraints
+#### [Documentation](https://github.com/joenoon/rm-extensions/wiki/RMExtensions-Documentation)
-AutoLayout is a great way to lay out views, but writing constraints manually is
-confusing and verbose.
+#### [CHANGELOG](https://github.com/joenoon/rm-extensions/wiki/CHANGELOG)
-Using Apple's "Visual Format Language" ASCII-inspired
-strings can improve things, but it has drawbacks: **1)** It returns an array
-of constraints. This means if you plan on altering one of them later, or removing
-one in particular, you would have to loop through all of the constraints, testing
-each one to see if its the one you want. **2)** The `options` argument adds additional
-constraints. For example, if you specify NSLayoutAttributeCenterY to a horizontal string,
-an additional constraint will be added for each view to set their centerY's equal to each
-other. This compounds problem #1. The chances you will get an error that the layout system
-cannot satisfy your constraints is probably because of these "extra" constraints. **3)**
-It can't handle complex constraints, so you end up needing to supplement it with
-verbose low-level constraint creation anyway.
-
-Apple makes note of how constraints can be thought of like a linear equation:
-
-http://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/NSLayoutConstraint/NSLayoutConstraint.html
-
-**Remember the formula:**
-
-```ruby
-view1.attr1 == view2.attr2 * multiplier + constant @ priority
-```
-
-**We can actually use this super-simple formula to write ALL of our constraints, simple OR complex!**
-
-Once you get the hang of the formula and visualization of how the geometry works, it becomes easy to create complex layouts with little
-effort. And, in my opinion, its only slightly more verbose than the visual format language, but much clearer, and you only end up
-with the exact constraints you want.
-
-Available values for `attr1` and `attr2` are:
-
-- left
-- right
-- top
-- bottom
-- leading
-- trailing
-- width
-- height
-- centerX
-- centerY
-- baseline
-
-Available `relation` values are:
-
-- ==
-- <=
-- >=
-
-Available `priority` values are:
-
-- required (1000 is the default)
-- high (750)
-- low (250)
-- fit (50)
-- or, you can use your own value between 1-1000
-
-
-### Examples
-
-Here is a real example. The Layout instance is created just like the motion-layout gem. `layout.view` sets the view
-that will act as the 'superview' to the views set in `layout.subviews`. Thats where the similarities end with
-motion-layout. With RMExtensions::Layout, there are two methods: `eq` and `eqs`, short for equation and equations.
-
-- `layout.eq` takes one string, and returns *one constraint*
-- `layout.eqs` takes one string, assumes multiple constraints are separated by newlines, and returns an *array of constraints*
-
-```ruby
-RMExtensions::Layout.new do |layout|
- layout.view view
- layout.subviews({
- "calendar" => calendarView,
- "table" => tableView,
- "shadow" => line
- })
-
- layout.eqs %Q{
- calendar.left == 0
- calendar.right == 0
- table.left == 7
- table.right == -7
- shadow.left == 0
- shadow.right == 0
-
- calendar.top == 0
- table.top == calendar.bottom
- table.bottom == 0
- shadow.top == table.top
- }
-
- @calendar_height_constraint = layout.eq "calendar.height == 0"
-end
-```
-
-Above, **calendar.left == 0** is short for **calendar.left == view.left * 1.0 + 0 @ 1000**. If no view2 is given, the superview ('view') is assumed.
-If no multiplier is given, 1.0 is assumed. If no constant is given, 0 is assumed. If no priority is given, "required" (1000) is assumed.
-The last constraint is created separately and stored in @calendar_height_constraint, because I want to be able to change the calendar's height
-any time I want.
-
-Here is another example:
-
-```ruby
-RMExtensions::Layout.new do |layout|
- layout.view self
- layout.subviews({
- "timeLabel" => @timeLabel,
- "titleLabel" => @titleLabel,
- "trackingImage" => @trackingImage,
- "inOutStatusInImage" => @inOutStatusInImage,
- "inOutStatusOutImage" => @inOutStatusOutImage,
- "plannerImage" => @plannerImage,
- "shareButton" => @shareButton,
- "cancelledLabel" => @cancelledLabel,
- "unreadImage" => @unreadImage
- })
-
- layout.eqs %Q{
- unreadImage.left == 6
- unreadImage.top == 6
- plannerImage.left == 14
- plannerImage.centerY == 0
- plannerImage.width == 30
- plannerImage.height == 30
- trackingImage.left == timeLabel.right + 5
- inOutStatusOutImage.left == trackingImage.right + 5
- inOutStatusInImage.left == inOutStatusOutImage.right + 5
- timeLabel.left == plannerImage.right + 5
- timeLabel.baseline == plannerImage.bottom + 1
- trackingImage.centerY == timeLabel.centerY
- inOutStatusOutImage.centerY == timeLabel.centerY
- inOutStatusInImage.centerY == timeLabel.centerY
- titleLabel.left == cancelledLabel.right
- cancelledLabel.left == plannerImage.right + 5
- titleLabel.top == plannerImage.top - 4
- cancelledLabel.centerY == titleLabel.centerY
- shareButton.right == -10
- shareButton.centerY == 0
- titleLabel.resistH == low
- shareButton.left >= titleLabel.right + 5
- timeLabel.resistH == low
- shareButton.left >= inOutStatusInImage.right + 5
- }
-
-end
-```
-
-Keep in mind none of these lines are using the multiplier, and thats OK. I've only needed it on one constraint in my entire app so far,
-so don't think its odd if you can't find a use for it.
-
-There are two special cases at the moment. **titleLabel.resistH == low** is not a "real" constraint. Its a shortcut to
-`setContentCompressionResistancePriority`, and since its common when dealing with autolayout, its nice to include it
-in our layout code. The same is done for `setContentHuggingPriority`. The full list of "special cases" at the moment:
-
-- view1.resistH == priority
-- view1.resistV == priority
-- view1.hugH == priority
-- view1.hugV == priority
-
-"priority" can be one of the values listed earlier, or your own number between 1-1000.
-
-### Debugging constraints
-
-- You can include a **?** on any line, and debug output will be printed when that constraint is built:
-
-```ruby
-layout.eqs %Q{
- label.left == photo.right + 5 ?
-}
-```
-
-- Since layout.eqs allows you to write many constraints in one string, and sometimes its nice to
-keep comments next to constraints, **comments are allowed**:
-
-```ruby
-layout.eqs %Q{
- commentsCount.width == likesCount.width @ low # the widths of the labels prefer to be the same
-}
-```
-
-### Things to remember
-
-- Remember you usually want negative constants for right and bottom. For example: label.right == -10 means "label's right should be 10 away from the right side of the superview". But if you accidentally said label.right == 10, you would have created "label's right should be 10 PAST the right side of the superview". It may require you to adjust your thinking.
-
-- The formula is just shorthand for `constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:`. You should **really** read up on constraints and
-understand this method, to fully understand the power and simplicity the shorthand formula gives you.
-
-
-
-
-
-
-
-
-## Observation/KVO, Events
-
-#### Make observations without needing to clean up/unobserve
-
-Call from anywhere on anything:
-
-```ruby
-class MyViewController < UIViewController
- def viewDidLoad
- super.tap do
- rmext_observe(@model, "name") do |val|
- p "name is #{val}"
- end
- foo.rmext_on(:some_event) do |val|
- p "some_event called with #{val.inspect}"
- end
- end
- end
- def test_trigger
- foo.rmext_trigger(:some_event, "hello!")
- end
-end
-```
-
-Differences from BW::KVO and BW::Reactor::Eventable:
-
-- No need to include a module in the class you wish to use it on
-- the observation happens on a proxy object
-- KVO: The default is to observe and immediately fire the supplied callback
-- KVO: The callback only takes one argument, the new value
-- KVO: the object observing is not retained, and when it is deallocated, the observation
- will be removed automatically for you. there is typically no need to clean up manually
-
-
-## Accessors
-
-#### weak attr_accessors:
-
-```ruby
-
-class MyView < UIView
- rmext_weak_attr_accessor :delegate
-end
-
-class MyViewController < UIViewController
- def viewDidLoad
- super.tap do
- v = MyView.alloc.initWithFrame(CGRectZero)
- view.addSubview(v)
- v.delegate = self
- end
- end
-end
-
-```
-
-## Queues
-
-#### Wraps GCD:
-
-```ruby
-# note +i+ will appear in order, and the thread will never change (main)
-100.times do |i|
- rmext_on_main_q do
- p "i: #{i} thread: #{NSThread.currentThread}"
- end
-end
-
-# note +i+ will appear in order, and the thread will change
-100.times do |i|
- rmext_on_serial_q("testing") do
- p "i: #{i} thread: #{NSThread.currentThread}"
- end
-end
-
-# note +i+ will sometimes appear out of order, and the thread will change
-100.times do |i|
- rmext_on_concurrent_q("testing") do
- p "i: #{i} thread: #{NSThread.currentThread}"
- end
-end
-```
-
Installation
-----------------
Add this line to your application's Gemfile:
@@ -292,12 +16,10 @@
And then execute:
$ bundle
-* Currently depends on bubblewrap (for BW::KVO).
-
Contributing
-----------------
If you have a better way to accomplish anything this library is doing, please share!
@@ -310,10 +32,9 @@
License
-----------------
Please see [LICENSE](https://github.com/joenoon/rm-extensions/blob/master/LICENSE.txt) for licensing details.
-
Author
-----------------
-Joe Noon, [joenoon](https://github.com/joenoon)
+[Joe Noon](https://github.com/joenoon)