• Stars
    star
    543
  • Rank 81,848 (Top 2 %)
  • Language
    Objective-C
  • License
    Other
  • Created about 10 years ago
  • Updated about 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Lightweight KVO-based data binding options.

RZDataBinding

Version CircleCI License Platform

RZDataBinding

Overview

RZDataBinding is a framework designed to help maintain data integrity in your iOS or OS X app. It is built using the standard Key-Value Observation (KVO) framework, but is safer and provides additional functionality. Like KVO, RZDataBinding helps to avoid endless delegate chains by establishing direct callbacks for when an object changes state.

Installation

Install using CocoaPods (recommended) by adding the following line to your Podfile:

pod "RZDataBinding"

Alternatively, download the repository and add the contents of the RZDataBinding directory to your project.

Demo Project

An example project is available in the Example directory. You can quickly check it out with

pod try RZDataBinding

Or download the zip from github and run it manually.

RZDataBinding

The demo shows a basic usage of RZDataBinding, but is by no means the canonical or most advanced use case.

Usage

Register a callback for when the keypath of an object changes:

// Register a selector to be called on a given target whenever keyPath changes on the receiver.
// Action must take either zero or exactly one parameter, an NSDictionary. 
// If the method has a parameter, the dictionary will contain values for the appropriate 
// RZDBChangeKeys. If keys are absent, they can be assumed to be nil. Values will not be NSNull.
- (void)rz_addTarget:(id)target
              action:(SEL)action
    forKeyPathChange:(NSString *)keyPath;

Bind values of two objects together either directly or with a function:

// Binds the value of a given key of the receiver to the value of a key path of another object. 
// When the key path of the object changes, the bound key of the receiver is also changed.
- (void)rz_bindKey:(NSString *)key
         toKeyPath:(NSString *)foreignKeyPath
          ofObject:(id)object;

// Same as the above method, but the binding function is first applied 
// to the changed value before setting the value of the bound key.
// If nil, the identity function is assumed, making it identical to regular rz_bindKey.
- (void)rz_bindKey:(NSString *)key 
         toKeyPath:(NSString *)foreignKeyPath 
          ofObject:(id)object
      withFunction:(RZDBKeyBindingFunction)bindingFunction;

Targets can be removed and keys unbound with corresponding removal methods, but unlike with standard KVO, you are not obligated to do so. RZDataBinding will automatically cleanup observers before objects are deallocated.

Why not use plain KVO?

Consider the following code, which calls nameChanged: when a user object's name changes, and reload a collection view when the user's preferences change:

Using KVO:

static void* const MyKVOContext = (void *)&MyKVOContext;

- (void)setupKVO
{
    [self.user addObserver:self
                forKeyPath:@"name"
                   options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
                   context:MyKVOContext]; 
                  
    [self.user addObserver:self
                forKeyPath:@"preferences"
                   options:kNilOptions
                   context:MyKVOContext];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object change:(NSDictionary *)change
                       context:(void *)context
{
  if ( context == MyKVOContext ) {
        if ( [object isEqual:self.user] ) {
            if ( [keyPath isEqualToString:@"name"] ) {
                [self nameChanged:change];
            }
            else if ( [keyPath isEqualToString:@"preferences"] ) {
                [self.collectionView reloadData];
            }
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)dealloc
{
    [self.user removeObserver:self forKeyPath:@"name" context:MyKVOContext];
    [self.user removeObserver:self forKeyPath:@"preferences" context:MyKVOContext];
}

Using RZDataBinding:

- (void)setupKVO
{
    [self.user rz_addTarget:self 
                     action:@selector(nameChanged:) 
           forKeyPathChange:@"name"];
    
    [self.user rz_addTarget:self.collectionView 
                     action:@selector(reloadData) 
           forKeyPathChange:@"preferences"];
}

Aside from the obvious reduction in code, the RZDataBinding implementation demonstrates several other wins:

  1. No need to manage different KVO contexts and check which object/keypath changed
  2. No need to implement an instance method, meaning any object can be added as a target
  3. No need to teardown before deallocation (standard KVO crashes if you fail to do this)

Safe Keypaths

RZDataBinding also provides several convenience macros to create type-safe keypaths. When running in DEBUG mode, invalid keypaths will generate a compiler error:

// Creates the keypath @"text", ensuring it exists on objects of type UILabel
RZDB_KP(UILabel, text);

// Creates @"layer.cornerRadius", ensuring the keypath exists on myView
RZDB_KP_OBJ(myView, layer.cornerRadius);

// Creates @"session.user.name", ensuring the keypath exists on self
RZDB_KP_SELF(session.user.name);

You should always use these macros instead of literal strings, because of the additional type checks they provide. Note that in production these macros simplify to literal string generation to avoid any additional overhead.

Callback Coalescing (Advanced)

RZDataBinding also provides a coalescing mechanism for fine-tuning areas of your application that receive or send a high number of KVO notifications, which may incur a performance cost. For example, a complex view might trigger an expensive layout operation whenever one of several properties changes. Or, some work may require changing properties several times before they settle to final values. In these cases, it may be beneficial to have RZDataBinding treat a block of work as an "atomic" event. That is, supported callbacks should be coalesced and sent once, when the work completes.

RZDBCoalesce provides a block interface:

[RZDBCoalesce coalesceBlock:^{
        // Callbacks within this block are coalesced,
        // and sent only once, after the block completes
}];

Callbacks are not coalesced by default, even within an RZDBCoalesce event. The rz_addTarget:action: methods can opt in to support coalescing by specifying a coalesce proxy as the callback target:

[object rz_addTarget:[self rz_coalesceProxy] 
              action:@selector(expensiveCallback) 
    forKeyPathChange:RZDB_KP_OBJ(object, key.path)];

In this example, the intended target is self, but if a coalesce event is in progress these messages will be coalesced and deferred until the event completes. Note that only rz_addTarget:action: callbacks may support coalescing; bindings established with the rz_bindKey: methods will never be coalesced.

Author

Rob Visentin, [email protected]

License

RZDataBinding is available under the MIT license. See the LICENSE file for more info.

More Repositories

1

BonMot

Beautiful, easy attributed strings in Swift
Swift
3,538
star
2

RZTransitions

A library of custom iOS View Controller Animations and Interactions.
Objective-C
1,877
star
3

Anchorage

A collection of operators and utilities that simplify iOS layout code.
Swift
628
star
4

Eject

An eject button for Interface Builder to generate swift code
Swift
523
star
5

RZCellSizeManager

Dynamic size computation and caching for cells.
Objective-C
242
star
6

Swiftilities

A collection of useful Swift utilities.
Swift
184
star
7

BentoMap

Map Clustering for Swift.
Swift
182
star
8

AndroidDatabaseLibraryComparison

Java
148
star
9

RZBluetooth

Core Bluetooth helper library
Objective-C
136
star
10

Singleton

135
star
11

RZUtils

Rightpoint Commonly Used Tools
Objective-C
122
star
12

Parser

112
star
13

RZViewActions

A category on UIView that provides animation structure similar to SKAction from SpriteKit.
Objective-C
103
star
14

ios-template

A `cookiecutter` template for iOS projects
Swift
94
star
15

RaisinToast

A UIWindow subclass used to message information to the users of your app.
Objective-C
83
star
16

FRY

UIKit Integration Library
Objective-C
77
star
17

rust-universal-template

Template for creating Rust libraries with bindings to iOS, Android, WebAssembly and more
Shell
58
star
18

UniversalAdapter

A single adapter implementation for any scrolling view or ViewGroup.
Java
53
star
19

ARKit-CoreML

Utilities and examples for using CoreML in conjunction with ARKit
Swift
47
star
20

RZCollectionList

A framework for dealing with displaying data from Core Data and other sources in UITableViews.
Objective-C
44
star
21

FreshAir-Android

Java
41
star
22

RIGImageGallery

An image gallery view controller designed to work with the Raizlabs Interface Guidelines for iOS
Swift
40
star
23

CardParser

Credit Card Type Parsing for Swift
Swift
40
star
24

Raizlabs-Android-Style

The Raizlabs Android Style Guide
38
star
25

RZAndroidBaseUtils

Base Utility set for Android applications
Java
36
star
26

RZTouchID

Basic TouchID implementation
Objective-C
34
star
27

Griddle

Groovy
34
star
28

Raizlabs-Cocoa-Style

The Raizlabs iOS Style Guide
Objective-C
32
star
29

ViewHolderInflater

31
star
30

android-template

A `cookiecutter` template for Android projects
Kotlin
28
star
31

RZTweenSpirit

Piecewise tweening/animation library for iOS
Objective-C
25
star
32

DebugModule

Java
22
star
33

Shift

A library of custom iOS View Controller Animations and Interactions written in Swift.
Swift
22
star
34

RZVinyl

Stack management, ActiveRecord utilities, and seamless importing for Core Data
Objective-C
21
star
35

Broker

21
star
36

RZDebugMenu

Configurable debug menu for iOS apps
Objective-C
20
star
37

Raze

A supplemental graphics engine for apps
Objective-C
20
star
38

RZImport

Automatic importing of data from NSDictionary to Cocoa objects
Objective-C
18
star
39

Stackable

Supercharged UIStackViews for Swift
Swift
18
star
40

AndroidWebServiceManager

Java
17
star
41

RZIntrinsicContentSizeTextView

Objective-C
17
star
42

RZSafariKeychain

A simple implementation of Safari Keychain
Objective-C
17
star
43

RZSplitViewController

A custom iOS SplitViewController.
16
star
44

FrictionLess

A collection of UX-focused swift components for reducing friction in "user work".
Swift
15
star
45

BoardingPass

A navigation controller interactive pan to push and pop.
Swift
14
star
46

WebServiceManager

13
star
47

ViewState

Small library for lightweight UIView and UIViewController state management on iOS
Swift
12
star
48

Pourcast

JavaScript
12
star
49

SketchyCode

An experimental tool to generate Swift code from Sketch files
Swift
12
star
50

CoreUtils

Java
12
star
51

UniversalFontComponents

A library that allows you to set a custom font in xml for all your TextViews
Java
11
star
52

opencv-swift

OpenCV / Swift Package Manager / XCFramework / Podspec
Ruby
10
star
53

RZNumberPad

Never write a custom number pad from scratch again.
Objective-C
9
star
54

conference-room

Conference room management system
C#
9
star
55

CompoundComponents

Android sample project that shows how to use Compound Components to make reusable UI. Also shows examples for creating reusable UI with the <include> tag and with Fragments.
Java
9
star
56

Geode

Location management made easy.
Swift
8
star
57

RZPoseurWebView

RZPoseurWebView
7
star
58

RZAssert

Useful assertion macros from the fine folks at Raizlabs.
Objective-C
7
star
59

RZEffects

Apply shader effects to UIKit elements.
7
star
60

RZBuildScripts

Xcode command line build script for building/signing/packaging iOS builds
Ruby
7
star
61

ai-discipline-ollama-rag

Python
7
star
62

Actionable

A cleaner delegation pattern for iOS.
Swift
6
star
63

RZOpenGL

Raizlabs OpenGL Library
6
star
64

localizable

Swift command line utility to take a CSV input of strings and output localizable string formats for iOS/macOS and Android.
Swift
5
star
65

RZKeychain

Easy keychain manipulation in iOS
4
star
66

FreshAir

Objective-C
4
star
67

RZLogin

A Reusable Login View Controller.
4
star
68

sample-scrolling-controls-ios

Sample code for a blog post about controls in scroll views on iOS
Swift
4
star
69

RZArrayCandy

Some functional sugar for your NSArrays
4
star
70

RZCollectionTableView

A UICollectionView that behaves like a UITableView
4
star
71

RZMapView

Simple custom mapping for iOS
Objective-C
4
star
72

sample-smart-animated-deselection-ios

Sample code for a blog post on smarter animated deselection on iOS
Swift
4
star
73

sample-float-remapping-ios

Sample code for a blog post on float remapping on iOS
Swift
3
star
74

RZDataManager

An iOS framework for Importing and Managing Data in your App.
3
star
75

slog

A simple logging utility for Swift
Shell
3
star
76

Drafter

Drafter - A nice way to draft up some constraints programmatically
3
star
77

DialogFactory

3
star
78

ios-template-output

For running CircleCI on output of ios-template
Swift
3
star
79

example-xcframework-build

Shell
3
star
80

CtrlZ

3
star
81

RZRadioKit

2
star
82

jss-react-template

Sample JSS React project using the OpenWeather API
JavaScript
2
star
83

RZSpriteTools

A library for creating and managing SpriteKit objects.
2
star
84

viewmodel-inject

Utilizes Dagger to generate a ViewModelProvider.Factory
Kotlin
2
star
85

RZAffirm

Raizlabs Swift Assertion Library
Swift
2
star
86

DataHub

Java
2
star
87

RZSegmentViewController

A customizable View Controller Container that lets you switch between view controllers using a segment control.
2
star
88

RZRevealViewController

RZRevealViewController is a Basement Menu style Containment View Controller.
1
star
89

FlowStacks-iOS-15-Bug

Demonstrating SwiftUI navigation bug in FlowStacks on iOS 15
Swift
1
star
90

maven-releases

1
star
91

PeopleCards

Flashcard game to learn new hire names/faces
JavaScript
1
star
92

AirQualityDashboard-iOS

Air quality dashboard for our BLE AQI device
Swift
1
star
93

RZSequenceController

A view controller container that arranges child view controller in either a horizontal or vertical scrolling flow.
1
star
94

air_quality_bluetooth_le

Bluetooth Low Energy interface for SDS011 APM2.5 air quality sensor
Python
1
star
95

react-native-touch-sensor

Java
1
star
96

RPLogging

Log level settings for iOS, macOS, tvOS, & watchOS
Swift
1
star
97

CustomVisionTools

Useful utilities for training object detection models with Custom Vision.
Python
1
star
98

Azure-Search-Query-Builder

This is a library that uses expression tree parsing to build a parameters object for performing search, suggest, and autocomplete actions with the Azure Search .NET SDK.
C#
1
star