mutech / aka-ios-beacon Goto Github PK
View Code? Open in Web Editor NEWThe missing binding framework for iOS
License: BSD 2-Clause "Simplified" License
The missing binding framework for iOS
License: BSD 2-Clause "Simplified" License
Controls are a left over from a previous incarnation of the binding library and do not really fit in well with the new architecture. While this is a rather big change, it should not affect the outer interface of the framework (except for naming of delegate that probably nobody uses yet).
Until now I did not yet encounter any noticeable performance problems due to bindings.
However, many implementations are far from optimal and performance issues will almost certainly pop up. For example:
Similar to UITableView data source binding
If we keep it:
Extract the binding expression parser and related classes to a separate target/project.
Create an external tool that validates binding expressions at compile time (scan through XIB/Storyboard files, extract binding expressions, validate them and integrate the whole thing in Xcode.
Introduce a new syntax for conditional bindings:
$when(<TypeA>)
"CellForAs"
$when(<TypeB>)
<CustomUITableViewCellType> { cellIdentifier: "CellForB" }
$when("SELF someCondition:argument == YES" { argument: 1.2 })
"CellForSomeConditionSatisfied"
$else
"DefaultCell"
Currently, cell mappings look like this:
[ { predicate: <TypeA>,
cellIdentifier: "CellForAs" },
{ predicate: <TypeB>,
cellIdentifier: "CellForBs", type: <CustomUITableViewCellType> },
{ predicate: "SELF someCondition:argument == YES" { argument: 1.2 },
cellIdentifier: "CellForSomeConditionSatisfied" },
{ cellIdentifier: "DefaultCell" }
]
<conditional> ::= <whenClause> + <elseClause> ?
<whenClause> ::= ('$when' | '$whenNot') '(' <predicateBindingExpression> ')' <bindingExpression>
<elseClause> ::= '$else' <bindingExpression>
Optionally, the key words '$inspect' (or '$switch', '$case', ...) and '$end' could be added. $inspect could be used to change the data context for the when clause and $end would make it possible to nest conditionals (not sure if that should be supported though). Both could be optional.
<conditional> ::= <inspectClause> ? <whenClause> + <elseClause> ? '$end' ?
<whenClause> ::= '$when' '(' <predicateBindingExpression> ')' <bindingExpression>
<elseClause> ::= '$else' <bindingExpression>
<inspectClause> ::= '$inspect' '(' <keyPathBindingExpression> ')'
Conditional bindings observe changes that can lead to predicates changing the value (due to predicate configuration or data context changes).
They however only have to observe leading predicates up until the first one that evaluates to true. Succeeding predicates can be ignored unless the active (satisfied) predicate changes its value to false.
When the conditional binding starts observing changes, it iterates over when clauses and evaluates their predicates until one is satisfied. The first predicate that is satisfied (by the data context) is selected and the result binding expression is used to create a binding.
If the data context used in when clauses changes or non constant predicates change (f.e. an NSPredicate parameter bound to a key path), the conditional binding re-evaluated invalidated predicates.
When relevant predicates change, a previously used result binding will stopObservingChanges (thus be released) and the new result binding will be created and startObservingChanges.
Dynamic layout constraints are one of the last domains where you currently need you write quite a lot of code to change or update presentation aspects from view models (or controllers).
One of the main goals of Beacon is to support the notion of abstract (not presentation specific) view models, that correspond to a user interaction and not so much to a concrete UI design or layout.
For example, a user interaction state could be "define filter criteria" that results in a possible change to properties searchPattern
and searchPatternOptions
. The editing state could be represented by a property isFilterEditorActive
or an enumeration presentationMode
having states like Default, FilterEditorActive, ...
.
The UI designer wants to represent that using a toolbar with a loupe icon that, when tapped, should present a search bar. This can be implemented using a set of constraints that hide the search bar while the the user is not editing the filter criteria.
Currently, the view model or controller would have to track the editing state and update the set of constraints to implement this functionality. In the future, this should be expressible in terms of constraint bindings.
This part is not thought out, just dumping the idea:
This is the easy part. Modifiable constraint properties could simply be updated using property bindings. The only catch here is that the binding would probably have to keep a strong reference to the constraint to ensure that if any party (including the binding itself) removes the constraint from its owner, it will not be released until the binding stops observing changes.
The following constraint properties are candidates for this binding types:
Such bindings would allow to:
All of these actions would be active as long as a binding is observing changes and the original state would be restored thereafter.
Constraint collection bindings are defined for the view that owns the constraints (the root of a sub hierarchy that is directly affected by constraint (?)).
Constraints to be added could look like:
addConstraints [
"H:|-(margin)-[viewA]-(margin)-|" {
metrics: { margin: 20.0 },
views: { viewA: { tag: 4 { optional }, role: "label" } }
]
One of the big challenges is that new constraints have to reference views. This will be supported using a query specification expressed in terms of binding attributes such as:
viewA: {
tag: 1, role: "label", type: <UILabel>,
searchOrder: [.Siblings, .SubViews, .SuperView, .SuperViews...],
}
Such a query would look for UILabels having a role "label" and otherwise a view tag 1 starting with siblings, then looking for matching sub view and finally testing the super view (transitively if .SuperViews is specified).
The role
would be a textual tag provided as extension property to UIViews (currently a mostly obsolete property aka_controlTags and aka_controlRole is implemented which could be replaced).
In the example above, a constraint binding could be defined on the UISearchBar (or some layout container view):
{ addConstraints: $whenNot(isFilterEditorActive) [ "V:[self(0)]" ] }
A lot of this functionality is already implemented in the scope of view theming (see AKAEditorControl & friends). These would be made obsolete.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.