Git Product home page Git Product logo

kvocontroller's Introduction

Build Status Coverage Status Version Platform

Key-value observing is a particularly useful technique for communicating between layers in a Model-View-Controller application. KVOController builds on Cocoa's time-tested key-value observing implementation. It offers a simple, modern API, that is also thread safe. Benefits include:

  • Notification using blocks, custom actions, or NSKeyValueObserving callback.
  • No exceptions on observer removal.
  • Implicit observer removal on controller dealloc.
  • Thread-safety with special guards against observer resurrection – rdar://15985376.

For more information on KVO, see Apple's Introduction to Key-Value Observing.

Usage

Example apps for iOS and OS X are included with the project. Here is one simple usage pattern:

// create KVO controller with observer
FBKVOController *KVOController = [FBKVOController controllerWithObserver:self];
self.KVOController = KVOController;

// observe clock date property
[self.KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(ClockView *clockView, Clock *clock, NSDictionary *change) {

  // update clock view with new value
  clockView.date = change[NSKeyValueChangeNewKey];
}];

While simple, the above example is complete. A clock view creates a KVO controller to observe the clock date property. A block callback is used to handle initial and change notification. Unobservation happens implicitly on controller deallocation, since a strong reference to the KVOController is kept.

Note: the observer specified must support weak references. The zeroing weak reference guards against notification of a deallocated observer instance.

NSObject Category

For an even easier usage, just #import <KVOController/NSObject+FBKVOController.h> for an automatic KVOController property on all objects.

[self.KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew action:@selector(updateClockWithDateChange:)];

Swift

KVOController works great in Swift but there are few requirements:

  • Your observer should subclass NSObject.
  • Properties that you observe must be marked as dynamic.

Check the following example:

class TasksListViewModel: NSObject {

  dynamic var tasksList: [TaskList] = []
}

/// In ViewController.swift

import KVOController

kvoController.observe(viewModel,
                      keyPath: "listsDidChange",
                      options: [.new, .initial]) { (viewController, viewModel, change) in
    
  self.taskListsTableView.reloadData()
}

Prerequisites

KVOController takes advantage of recent Objective-C runtime advances, including ARC and weak collections. It requires:

  • iOS 6 or later.
  • OS X 10.7 or later.

Installation

To install using CocoaPods, add the following to your project Podfile:

pod 'KVOController'

To install using Carthage, add the following to your project Cartfile:

github "facebook/KVOController"

Alternatively, drag and drop FBKVOController.h and FBKVOController.m into your Xcode project, agreeing to copy files if needed. For iOS applications, you can choose to link against the static library target of the KVOController project.

Having installed using CocoaPods or Carthage, add the following to import in Objective-C:

#import <KVOController/KVOController.h>

Testing

The unit tests included use CocoaPods for managing dependencies. Install CocoaPods if you haven't already done so. Then, at the command line, navigate to the root KVOController directory and type:

pod install

This will install and add test dependencies on OCHamcrest and OCMockito. Re-open the Xcode KVOController workspace and Test, ⌘U.

License

KVOController is released under a BSD License. See LICENSE file for details.

kvocontroller's People

Contributors

acerbetti avatar ashton-w avatar christianroman avatar coeur avatar cxa avatar danielvy avatar fredemmott avatar grp avatar ha-nyung avatar hossamghareeb avatar jcavar avatar jeffreyjackson avatar lexrus avatar lxcid avatar mazyod avatar modocache avatar mohamede1945 avatar mrh-is avatar nlutsenko avatar ruiaaperes avatar seivan avatar siyusong avatar tettoffensive avatar torinkwok avatar zzz6519003 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kvocontroller's Issues

KVO self with self observer

A bit of context first: I am using MVVM and I have a VC with a VM. The VC is observing one property of the VM. Now is the thing: I want the VM to observe himself for two keyPaths and once there is a change, if it's passes a validation, I will update the property the VC is observing. On the VM I would have something like:

[self.KVOController observe: self keyPaths:@[keyPath1,keyPath2] options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew block:^(ViewModel *observer, ViewModel *observed, NSDictionary *change) {

}];

So my two problems:

  1. The VM get's retained and it's never released (dealloc is not called). I would like it to behave as expected: lifetime tied with its VC.
  2. Is this pattern fundamentally wrong?

The goal here is to avoid exposing the two inner properties to VC (I don't think he should be exposed to those)

New Tag?

Hello,

I am wondering if it is possible to create a new tag / release (also on cocoapods) to make some new features available for cocoapods users, for example observation of multiple keypaths with only one block.

That would be awesome =)

Thanks
Steffen

Will KVOController support arm64 ?

you know, apple will reject any app that doesn't support arm64 before next Feb. That means all third-party frameworks in my project need support arm64. KVOController is a good framework, so will it support arm64 proccessor? and when ?

Road to v1.0.4

There have been some minor changes since v1.0.3 that aren't released on CocoaPods - or in a tagged release. Is there a roadmap for what has to be done before the next release, or did someone just have to ask ;)

We could perhaps use the 'Milestones' feature in GitHub.

❤️ KVOController

What's the point of the "observer"?

To instantiate a controller, I use [FBKVOController controllerWithObserver:self].

What's the point of passing in self? In traditional KVO, I pass in selfto clarify which object's observe method should get called. But with FBKVOController, I pass in blocks to handle KVO notifications; it's the block that'll get called, not self.

Why separate alloc and init ?

In your init() method for SharedController,

There is
NSHashTable *infos = [NSHashTable alloc];
then
[infos initWithOptions:NSPointerFunctionsZeroingWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];

Apple document recommends against this. See Issues with Initializers
Can you explain, thanks

NSObject Category not included in pod

I just installed the latest pod and xcode cannot find #import <KVOController/NSObject+FBKVOController.h>

When investigating i saw that the file doesn't appear to be included

Edit just realized it's probably related to #50

Performance hotspot on iOS 9.

I'm using KVOController to observe ~12 attributes on 35 objects (so about 420 things being observed in total) and seeing significant performance degradation on iOS 9.

I fired up the time profiler instrument and noticed that inside -[_FBKVOSharedController observe:info:] I'm seeing 100% CPU utilization on [object addObserver:self forKeyPath:info->_keyPath options:info->_options context:(void *)info];. I'm wondering if anyone else has seen similar behavior on iOS 9. iOS 7 and iOS 8 seem to be around 8x faster.

Crashing bevore unobserve all in dealloc

Incident Identifier: AC065E21-025D-4D28-94A0-34DE72FAB50F
CrashReporter Key:   BE4698B2-CBA3-4F8C-A667-2AA3D45C1DF4
Hardware Model:      iPhone4,1
Process:         My Application [704]
Path:            /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/My Application
Version:         590
Code Type:       ARM
Parent Process:  launchd [1]

Date/Time:       2014-11-28T13:22:16Z
OS Version:      iPhone OS 8.1 (12B411)
Report Version:  104

Exception Type:  SIGTRAP
Exception Codes: #0 at 0x328028a4
Crashed Thread:  0

Thread 0 Crashed:
0   libobjc.A.dylib                      0x328028a4 _objc_trap() + 0
1   libobjc.A.dylib                      0x32802909 _objc_fatal + 70
2   libobjc.A.dylib                      0x3281c44b weak_register_no_lock + 208
3   libobjc.A.dylib                      0x3281c7c3 objc_storeWeak + 152
4   My Application                       0x003558c5 -[FBKVOController initWithObserver:retainObserved:] (FBKVOController.m:367)
5   My Application                       0x00355861 +[FBKVOController controllerWithObserver:] (FBKVOController.m:360)
6   My Application                       0x003567d1 -[NSObject(FBKVOController) KVOController] (FBKVOController.m:639)
7   My Application                       0x000e402f -[BSCArtikeldetailansichtPageViewController dealloc] (BSCArtikeldetailansichtPageViewController.m:335)
8   My Application                       0x0009da9d -[BSCArtikelUebersichtTableViewController checkForLoginAfterSelect] (BSCArtikelUebersichtTableViewController.m:121)
9   My Application                       0x0009d57b -[BSCArtikelUebersichtTableViewController viewDidAppear:] (BSCArtikelUebersichtTableViewController.m:80)
10  UIKit                                0x2845df2b -[UIViewController _setViewAppearState:isAnimating:] + 500
11  UIKit                                0x2845e3e7 -[UIViewController _endAppearanceTransition:] + 288
12  UIKit                                0x289cad13 -[UIPageViewController queuingScrollView:didEndManualScroll:toRevealView:direction:animated:didFinish:didComplete:] + 292
13  UIKit                                0x28a4179f -[_UIQueuingScrollView _notifyDelegateDidEndManualScroll:toRevealView:direction:animated:didFinish:didComplete:] + 88
14  UIKit                                0x28a41a55 -[_UIQueuingScrollView setView:direction:animated:completion:] + 574
15  UIKit                                0x289c8f0b -[UIPageViewController _setViewControllers:withScrollInDirection:animated:completion:] + 476
16  UIKit                                0x289c9029 -[UIPageViewController setViewControllers:direction:animated:completion:] + 154
17  My Application                       0x000accbd __66-[BSCArtikelUebersichtPageViewController setupFirstViewController]_block_invoke (BSCArtikelUebersichtPageViewController.m:237)
18  libdispatch.dylib                    0x32d63423 _dispatch_call_block_and_release + 8
19  libdispatch.dylib                    0x32d6340f _dispatch_client_callout + 20
20  libdispatch.dylib                    0x32d6e1b5 _dispatch_main_queue_callback_4CF$VARIANT$mp + 710
21  CoreFoundation                       0x24f69c41 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 6
22  CoreFoundation                       0x24f68361 __CFRunLoopRun + 1510
23  CoreFoundation                       0x24eb5981 CFRunLoopRunSpecific + 474
24  CoreFoundation                       0x24eb5793 CFRunLoopRunInMode + 104
25  GraphicsServices                     0x2c28e051 GSEventRunModal + 134
26  UIKit                                0x284a7981 UIApplicationMain + 1438
27  My Application                       0x0006af93 main (main.m:16)
28  libdyld.dylib                        0x32d9eaaf start + 0

Thread 1:
0   libsystem_kernel.dylib               0x32e502c8 kevent64 + 24
1   libdispatch.dylib                    0x32d72b7b _dispatch_mgr_thread$VARIANT$mp + 36

Thread 2:
0   libsystem_kernel.dylib               0x32e649cc __workq_kernreturn + 8
1   libsystem_pthread.dylib              0x32ee0b78 start_wqthread + 6

Thread 3:
0   libsystem_kernel.dylib               0x32e649cc __workq_kernreturn + 8
1   libsystem_pthread.dylib              0x32ee0b78 start_wqthread + 6

Thread 4:
0   libsystem_kernel.dylib               0x32e50518 mach_msg_trap + 20
1   CoreFoundation                       0x24f69bab __CFRunLoopServiceMachPort + 144
2   CoreFoundation                       0x24f68171 __CFRunLoopRun + 1014
3   CoreFoundation                       0x24eb5981 CFRunLoopRunSpecific + 474
4   CoreFoundation                       0x24eb5793 CFRunLoopRunInMode + 104
5   CFNetwork                            0x24a6a9df +[NSURLConnection(Loader) _resourceLoadLoop:] + 484
6   Foundation                           0x25cb599b __NSThread__main__ + 1116
7   libsystem_pthread.dylib              0x32ee2e67 _pthread_body + 136
8   libsystem_pthread.dylib              0x32ee2ddb _pthread_start + 116
9   libsystem_pthread.dylib              0x32ee0b84 thread_start + 6

Thread 5:
0   libsystem_kernel.dylib               0x32e50518 mach_msg_trap + 20
1   CoreFoundation                       0x24f69bab __CFRunLoopServiceMachPort + 144
2   CoreFoundation                       0x24f68171 __CFRunLoopRun + 1014
3   CoreFoundation                       0x24eb5981 CFRunLoopRunSpecific + 474
4   CoreFoundation                       0x24eb5793 CFRunLoopRunInMode + 104
5   Foundation                           0x25bf0951 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 262
6   Foundation                           0x25c3edc5 -[NSRunLoop(NSRunLoop) run] + 78
7   My Application                       0x001cc609 +[GAI threadMain:] + 62
8   Foundation                           0x25cb599b __NSThread__main__ + 1116
9   libsystem_pthread.dylib              0x32ee2e67 _pthread_body + 136
10  libsystem_pthread.dylib              0x32ee2ddb _pthread_start + 116
11  libsystem_pthread.dylib              0x32ee0b84 thread_start + 6

Thread 6:
0   libsystem_kernel.dylib               0x32e649cc __workq_kernreturn + 8
1   libsystem_pthread.dylib              0x32ee0b78 start_wqthread + 6

Thread 7:
0   libsystem_kernel.dylib               0x32e6408c __select + 20
1   libsystem_pthread.dylib              0x32ee2e67 _pthread_body + 136
2   libsystem_pthread.dylib              0x32ee2ddb _pthread_start + 116
3   libsystem_pthread.dylib              0x32ee0b84 thread_start + 6

Thread 8:
0   libsystem_kernel.dylib               0x32e649cc __workq_kernreturn + 8
1   libsystem_pthread.dylib              0x32ee0b78 start_wqthread + 6

Thread 9:
0   libsystem_kernel.dylib               0x32e649cc __workq_kernreturn + 8
1   libsystem_pthread.dylib              0x32ee0b78 start_wqthread + 6

Thread 10:
0   libsystem_kernel.dylib               0x32e649cc __workq_kernreturn + 8
1   libsystem_pthread.dylib              0x32ee0b78 start_wqthread + 6

Thread 11:
0   ???                                  0x00000000 0x0 + 0

Thread 0 crashed with ARM Thread State:
    pc: 0x328028a4     r7: 0x006f09bc     sp: 0x006f09b0     r0: 0x00000000 
    r1: 0x00000028     r2: 0x00000100     r3: 0x00000100     r4: 0x163ff000 
    r5: 0x3551d618     r6: 0x168ee90c     r8: 0x35515130     r9: 0x35515440 
   r10: 0x3551d600    r11: 0x3551d600     ip: 0x00000000     lr: 0x32802909 
  cpsr: 0x60000030 

Link Register Analysis:
  Symbol: _objc_fatal + 70
  Description: We have determined that the link register (lr) is very likely to contain the return address of frame #0's calling function, and have inserted it into the crashing thread's backtrace as frame #1 to aid in analysis. This determination was made by applying a heuristic to determine whether the crashing function was likely to have created a new stack frame at the time of the crash.
  Type: 1

Binary Images:
   0x3f000 -   0x4dafff +My Application armv7  <1ed82560cf8d3053add4442c6981d525> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/My Application
  0x6f2000 -   0x891fff  libswiftCore.dylib armv7  <ca81d18b7890334694e9c2426a2293e2> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftCore.dylib
  0x9d2000 -   0x9e9fff  libswiftCoreGraphics.dylib armv7  <dbb52d8303a438bb9b793a1bc4ff7c8b> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftCoreGraphics.dylib
  0x9fe000 -   0xa01fff  libswiftCoreImage.dylib armv7  <5a934d4aee463c46bc2bce0e447243bf> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftCoreImage.dylib
  0xa0a000 -   0xa11fff  libswiftDarwin.dylib armv7  <686e70965b003f318234b4a3886ec028> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftDarwin.dylib
  0xa1f000 -   0xa22fff  libswiftDispatch.dylib armv7  <b7b470f4a25b3bdb83150f9114ea014c> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftDispatch.dylib
  0xa2c000 -   0xa7ffff  libswiftFoundation.dylib armv7  <718f87fd373c3865a481b11c6b606d95> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftFoundation.dylib
  0xab0000 -   0xab7fff  libswiftObjectiveC.dylib armv7  <917d7ce312763e1cbef11ec59a5e0b19> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftObjectiveC.dylib
  0xac3000 -   0xac6fff  libswiftSecurity.dylib armv7  <58019e87237d3869911c80614c4fe57f> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftSecurity.dylib
  0xacf000 -   0xad2fff  libswiftUIKit.dylib armv7  <17308e4d8c933178833f74c0707cfe10> /private/var/mobile/Containers/Bundle/Application/1089ACB5-0A1F-4BB9-8116-A1C4AB4C1906/My Application.app/Frameworks/libswiftUIKit.dylib
0x23a53000 - 0x23bbffff  AVFoundation armv7  <3e13d2b9a2d13ce6a5e8b30652ccdd2a> /System/Library/Frameworks/AVFoundation.framework/AVFoundation
0x23bc0000 - 0x23c1efff  libAVFAudio.dylib armv7  <ca82083ada963023985d0530ff53776d> /System/Library/Frameworks/AVFoundation.framework/libAVFAudio.dylib
0x23c59000 - 0x23c59fff  Accelerate armv7  <79b84eb74f0234e4ac81d7c906641804> /System/Library/Frameworks/Accelerate.framework/Accelerate
0x23c6a000 - 0x23e83fff  vImage armv7  <5ec259488c033a4f98b0f28ee14ecfc1> /System/Library/Frameworks/Accelerate.framework/Frameworks/vImage.framework/vImage
0x23e84000 - 0x23f61fff  libBLAS.dylib armv7  <e5395e7ee45e353498dcb4e956bcf272> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/libBLAS.dylib
0x23f62000 - 0x24225fff  libLAPACK.dylib armv7  <689f4395215e3cef8bafa5f21e288cfe> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/libLAPACK.dylib
0x24226000 - 0x24238fff  libLinearAlgebra.dylib armv7  <b86c17150d2133b8baea239d17df5e28> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/libLinearAlgebra.dylib
0x24239000 - 0x242adfff  libvDSP.dylib armv7  <bc358a699c2132a09e9150cfc2db34bb> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/libvDSP.dylib
0x242ae000 - 0x242bffff  libvMisc.dylib armv7  <565f1fdc35f436219a758de47022e34c> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/libvMisc.dylib
0x242c0000 - 0x242c0fff  vecLib armv7  <f4dbfd05244f30b2905a5dbf06f15fc8> /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/vecLib
0x242c1000 - 0x242e7fff  Accounts armv7  <134b9fe391fc3ee49d1ba11a022a416d> /System/Library/Frameworks/Accounts.framework/Accounts
0x242e8000 - 0x242e8fff  AdSupport armv7  <6a9e6e524165303bb74dd97863258ff0> /System/Library/Frameworks/AdSupport.framework/AdSupport
0x242e9000 - 0x24359fff  AddressBook armv7  <c1cc3f1f1bf13875aa0199b60829048c> /System/Library/Frameworks/AddressBook.framework/AddressBook
0x2435a000 - 0x2447efff  AddressBookUI armv7  <b196db085d073e0c855f798bcb9c3820> /System/Library/Frameworks/AddressBookUI.framework/AddressBookUI
0x2447f000 - 0x24491fff  AssetsLibrary armv7  <4b99b898c23838b18067861bf1632f91> /System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary
0x24615000 - 0x24886fff  AudioToolbox armv7  <a9cf66a97d1636ed8ed3eb4fb2b0fd69> /System/Library/Frameworks/AudioToolbox.framework/AudioToolbox
0x249ee000 - 0x24b76fff  CFNetwork armv7  <3bedb71907f23fed9fa2ece15da815e1> /System/Library/Frameworks/CFNetwork.framework/CFNetwork
0x24b77000 - 0x24bf8fff  CloudKit armv7  <5408225e99ad322ea51ede79fefe2f8b> /System/Library/Frameworks/CloudKit.framework/CloudKit
0x24bf9000 - 0x24c57fff  CoreAudio armv7  <77c81b98ce5f30bfbc15fe04871f334c> /System/Library/Frameworks/CoreAudio.framework/CoreAudio
0x24c72000 - 0x24c8ffff  CoreBluetooth armv7  <38ef2bf52cfe3f148b09e6554d5ca87c> /System/Library/Frameworks/CoreBluetooth.framework/CoreBluetooth
0x24c90000 - 0x24e9bfff  CoreData armv7  <cb6a3ecb19ef348c8cdd778f18ed5cbe> /System/Library/Frameworks/CoreData.framework/CoreData
0x24e9c000 - 0x251cbfff  CoreFoundation armv7  <874d5e6eaf8f386588748eea1bf23e79> /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
0x251cc000 - 0x252f5fff  CoreGraphics armv7  <f3d81a675d71319da92854b9bf022b7e> /System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
0x25335000 - 0x25337fff  libCGXType.A.dylib armv7  <4c604b9853523134ae5bd1cc2723d40b> /System/Library/Frameworks/CoreGraphics.framework/Resources/libCGXType.A.dylib
0x25338000 - 0x25342fff  libCMSBuiltin.A.dylib armv7  <21b189f1221a35a293851586208f3a55> /System/Library/Frameworks/CoreGraphics.framework/Resources/libCMSBuiltin.A.dylib
0x2552a000 - 0x25545fff  libRIP.A.dylib armv7  <408b014e9d3c358b887cf673643ba913> /System/Library/Frameworks/CoreGraphics.framework/Resources/libRIP.A.dylib
0x25546000 - 0x25657fff  CoreImage armv7  <997b9cd9c612337db658372eab3ab6fd> /System/Library/Frameworks/CoreImage.framework/CoreImage
0x25658000 - 0x256affff  CoreLocation armv7  <7493a33b9d983ff19b7b72b5807cf25f> /System/Library/Frameworks/CoreLocation.framework/CoreLocation
0x256e1000 - 0x2577bfff  CoreMedia armv7  <dd4491324c28376a82f7caefc326484e> /System/Library/Frameworks/CoreMedia.framework/CoreMedia
0x2577c000 - 0x2583bfff  CoreMotion armv7  <69fc9c0a1ed7366d9bbeb2581a5ede6b> /System/Library/Frameworks/CoreMotion.framework/CoreMotion
0x2583c000 - 0x2589afff  CoreTelephony armv7  <c9e10c8b8d443e929b4f02fcdbd46dbb> /System/Library/Frameworks/CoreTelephony.framework/CoreTelephony
0x2589b000 - 0x25962fff  CoreText armv7  <17dc20b2359d31b4bbcee9a01596c680> /System/Library/Frameworks/CoreText.framework/CoreText
0x25963000 - 0x25978fff  CoreVideo armv7  <1d59c14bdead37ab975da3b21f010ebb> /System/Library/Frameworks/CoreVideo.framework/CoreVideo
0x25979000 - 0x25a6efff  EventKit armv7  <f7b1aae5a27038bfa8eb2089b143a4a0> /System/Library/Frameworks/EventKit.framework/EventKit
0x25a6f000 - 0x25bd0fff  EventKitUI armv7  <22c7fc5b2c9e3841b8824d8ed647acf1> /System/Library/Frameworks/EventKitUI.framework/EventKitUI
0x25be5000 - 0x25de7fff  Foundation armv7  <56ef2e09ae9b316f9ed82344f3471b2e> /System/Library/Frameworks/Foundation.framework/Foundation
0x25e14000 - 0x25e33fff  GSS armv7  <d533358bb257318b9f507c72d52118a8> /System/Library/Frameworks/GSS.framework/GSS
0x25ec8000 - 0x25f1efff  IOKit armv7  <128d9396fe493ab9a22f245264d5327b> /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
0x25f1f000 - 0x26161fff  ImageIO armv7  <e3564eafb6463d04bd165eaab4a818e4> /System/Library/Frameworks/ImageIO.framework/ImageIO
0x26162000 - 0x264abfff  JavaScriptCore armv7  <fa3211d4594135649426d3b99ae53f74> /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
0x26784000 - 0x2678cfff  MediaAccessibility armv7  <4d99470cce0f3a2fa93ada24c5125ff1> /System/Library/Frameworks/MediaAccessibility.framework/MediaAccessibility
0x2678d000 - 0x26966fff  MediaPlayer armv7  <b92131828e64387b942db61e033912fd> /System/Library/Frameworks/MediaPlayer.framework/MediaPlayer
0x26967000 - 0x26ce1fff  MediaToolbox armv7  <e3a432bc8d8b34be933fcd04380b8c02> /System/Library/Frameworks/MediaToolbox.framework/MediaToolbox
0x26ce2000 - 0x26da0fff  MessageUI armv7  <59024b6478f53a13a1b7c16682f3b0ee> /System/Library/Frameworks/MessageUI.framework/MessageUI
0x26da1000 - 0x26e0dfff  Metal armv7  <8b3ea94103ec31bdbfe2a537d068dffb> /System/Library/Frameworks/Metal.framework/Metal
0x26e0e000 - 0x26e9efff  MobileCoreServices armv7  <94f9a4e5ae0f3fcfb627db2b96dc7134> /System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices
0x27969000 - 0x27971fff  OpenGLES armv7  <5fd5717d524735c489b33aef0162c82f> /System/Library/Frameworks/OpenGLES.framework/OpenGLES
0x27973000 - 0x27973fff  libCVMSPluginSupport.dylib armv7  <4aeddc62331d30adb955af134ec16a97> /System/Library/Frameworks/OpenGLES.framework/libCVMSPluginSupport.dylib
0x27974000 - 0x27976fff  libCoreFSCache.dylib armv7  <387bf7c1911a3e749f83037d6655a0e9> /System/Library/Frameworks/OpenGLES.framework/libCoreFSCache.dylib
0x27977000 - 0x2797afff  libCoreVMClient.dylib armv7  <9ac8ebec447238cab588905e8173abec> /System/Library/Frameworks/OpenGLES.framework/libCoreVMClient.dylib
0x2797b000 - 0x27983fff  libGFXShared.dylib armv7  <8f22b5c2469036ca896d9dd6fa090e1f> /System/Library/Frameworks/OpenGLES.framework/libGFXShared.dylib
0x27984000 - 0x279c3fff  libGLImage.dylib armv7  <f1249f0605623095b35b95f048d6b00f> /System/Library/Frameworks/OpenGLES.framework/libGLImage.dylib
0x27e64000 - 0x27fb5fff  QuartzCore armv7  <d13e0f6b71c23eb19871b68e3a3d32e4> /System/Library/Frameworks/QuartzCore.framework/QuartzCore
0x27fb6000 - 0x28009fff  QuickLook armv7  <f4912227e3d53999a7620956aa794781> /System/Library/Frameworks/QuickLook.framework/QuickLook
0x281f6000 - 0x28236fff  Security armv7  <47d7d32da10435c88bda1ab679f2b756> /System/Library/Frameworks/Security.framework/Security
0x28237000 - 0x282affff  Social armv7  <6d1557478edd30e59ab4d1726172fcc8> /System/Library/Frameworks/Social.framework/Social
0x283c4000 - 0x283d9fff  StoreKit armv7  <6b14ff8a82a73f88b4381e3fdd37b342> /System/Library/Frameworks/StoreKit.framework/StoreKit
0x283da000 - 0x28436fff  SystemConfiguration armv7  <ffe3e804e7bf3af1886c180949b71dc2> /System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration
0x28439000 - 0x28cdbfff  UIKit armv7  <bd715708301933568875568870c35906> /System/Library/Frameworks/UIKit.framework/UIKit
0x28cdc000 - 0x28d43fff  VideoToolbox armv7  <85acd014b766351d84815417397fe67f> /System/Library/Frameworks/VideoToolbox.framework/VideoToolbox
0x28d44000 - 0x28f28fff  WebKit armv7  <9236bb2a21863a5e860ee9a394b7f8c1> /System/Library/Frameworks/WebKit.framework/WebKit
0x2924d000 - 0x29258fff  AOSNotification armv7  <0058b3278d033878b1a6c75af3f587d1> /System/Library/PrivateFrameworks/AOSNotification.framework/AOSNotification
0x293ad000 - 0x293f9fff  AccountsDaemon armv7  <48ae1d7e18bf32809018ed52bbf8d738> /System/Library/PrivateFrameworks/AccountsDaemon.framework/AccountsDaemon
0x293fa000 - 0x2941bfff  AccountsUI armv7  <6874dc925cd13bdf9246b9a1ab5933b3> /System/Library/PrivateFrameworks/AccountsUI.framework/AccountsUI
0x2941c000 - 0x29420fff  AggregateDictionary armv7  <f4d6a9cda6553fc597fb89116907b817> /System/Library/PrivateFrameworks/AggregateDictionary.framework/AggregateDictionary
0x295e6000 - 0x29610fff  AirPlaySupport armv7  <3bfee7bc51303e37b5ff1141f61e135f> /System/Library/PrivateFrameworks/AirPlaySupport.framework/AirPlaySupport
0x29809000 - 0x2984bfff  AppSupport armv7  <d14af435548f3ee79635523145e3a035> /System/Library/PrivateFrameworks/AppSupport.framework/AppSupport
0x2984c000 - 0x29893fff  AppleAccount armv7  <b4ad4f621515315da3e913f310e663ef> /System/Library/PrivateFrameworks/AppleAccount.framework/AppleAccount
0x2997b000 - 0x299b8fff  AppleJPEG armv7  <2e7ce29b9d7e338aaf58ec054abe1ef7> /System/Library/PrivateFrameworks/AppleJPEG.framework/AppleJPEG
0x299c3000 - 0x299d5fff  ApplePushService armv7  <d87e982603a9391fab3742915456e539> /System/Library/PrivateFrameworks/ApplePushService.framework/ApplePushService
0x299d6000 - 0x299dcfff  AppleSRP armv7  <c320a73d635938c4998bcf2ec77997e4> /System/Library/PrivateFrameworks/AppleSRP.framework/AppleSRP
0x29a11000 - 0x29a1afff  AssertionServices armv7  <a49b2bbace4239109cee223d1bdc87c9> /System/Library/PrivateFrameworks/AssertionServices.framework/AssertionServices
0x29a1b000 - 0x29a33fff  AssetsLibraryServices armv7  <0b5fc76b94103173bf4118143cbf879f> /System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices
0x29a34000 - 0x29a58fff  AssistantServices armv7  <7fb1917be0423872b7af8419fbd5971b> /System/Library/PrivateFrameworks/AssistantServices.framework/AssistantServices
0x29a88000 - 0x29a8cfff  BTLEAudioController armv7  <5348e569a1863cd2acb458ef3c238df6> /System/Library/PrivateFrameworks/BTLEAudioController.framework/BTLEAudioController
0x29a8d000 - 0x29aa4fff  BackBoardServices armv7  <3952119c87ba3c8581779811f16569d9> /System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices
0x29aa7000 - 0x29adcfff  BaseBoard armv7  <33e55e2e61bd392d83e990f2db062c92> /System/Library/PrivateFrameworks/BaseBoard.framework/BaseBoard
0x29add000 - 0x29ae3fff  BluetoothManager armv7  <14d3ed516b9c385d9327b97503de0967> /System/Library/PrivateFrameworks/BluetoothManager.framework/BluetoothManager
0x29ae4000 - 0x29b0afff  Bom armv7  <7f17c88103a037c484afb3405787db58> /System/Library/PrivateFrameworks/Bom.framework/Bom
0x29b89000 - 0x29b90fff  CacheDelete armv7  <16c959d761d63a6b9faef60faf2f4434> /System/Library/PrivateFrameworks/CacheDelete.framework/CacheDelete
0x29bd5000 - 0x29bfefff  CalendarFoundation armv7  <f7ec9adede723df39fe46cd94d1dfa16> /System/Library/PrivateFrameworks/CalendarFoundation.framework/CalendarFoundation
0x29bff000 - 0x29c18fff  CalendarUIKit armv7  <12f6afa8f12b3ef8a6e88444089a8475> /System/Library/PrivateFrameworks/CalendarUIKit.framework/CalendarUIKit
0x29d0c000 - 0x29d14fff  CaptiveNetwork armv7  <60b0278123383390a4b1adf28561d887> /System/Library/PrivateFrameworks/CaptiveNetwork.framework/CaptiveNetwork
0x29d15000 - 0x29e37fff  Celestial armv7  <e9c754cb3e333c11b212b8b997bcdeae> /System/Library/PrivateFrameworks/Celestial.framework/Celestial
0x29e45000 - 0x29e5dfff  CertInfo armv7  <557f4b7831743819bfb28afae51992c3> /System/Library/PrivateFrameworks/CertInfo.framework/CertInfo
0x29e5e000 - 0x29e63fff  CertUI armv7  <cda24a7e63023084b1ab8bec476b3d57> /System/Library/PrivateFrameworks/CertUI.framework/CertUI
0x29f8e000 - 0x29faffff  ChunkingLibrary armv7  <9e947c5103b6365c9795dee24263cec1> /System/Library/PrivateFrameworks/ChunkingLibrary.framework/ChunkingLibrary
0x2a35d000 - 0x2a408fff  CloudPhotoLibrary armv7  <543dd7ee012c3bd5881d044438cb36df> /System/Library/PrivateFrameworks/CloudPhotoLibrary.framework/CloudPhotoLibrary
0x2a459000 - 0x2a45bfff  CommonAuth armv7  <b84b2b2966a83bfe95779cda3fbde0b5> /System/Library/PrivateFrameworks/CommonAuth.framework/CommonAuth
0x2a45c000 - 0x2a46cfff  CommonUtilities armv7  <32770dfa1acd380da2687854518aa141> /System/Library/PrivateFrameworks/CommonUtilities.framework/CommonUtilities
0x2a46d000 - 0x2a471fff  CommunicationsFilter armv7  <48cd97a90fe235809677403a1fadb47b> /System/Library/PrivateFrameworks/CommunicationsFilter.framework/CommunicationsFilter
0x2a4e2000 - 0x2a4e6fff  ConstantClasses armv7  <8ecd06c7839c3e538b5b20bdc52da65f> /System/Library/PrivateFrameworks/ConstantClasses.framework/ConstantClasses
0x2a4e7000 - 0x2a51ffff  ContentIndex armv7  <212f96cfdf5d3c6680f33a7754aabaff> /System/Library/PrivateFrameworks/ContentIndex.framework/ContentIndex
0x2a520000 - 0x2a523fff  CoreAUC armv7  <33d2af2dbb6b3708ae007bcb8d072a73> /System/Library/PrivateFrameworks/CoreAUC.framework/CoreAUC
0x2a548000 - 0x2a59cfff  CoreDAV armv7  <7e7b04dada943f5ba23550236b38cfa7> /System/Library/PrivateFrameworks/CoreDAV.framework/CoreDAV
0x2a59d000 - 0x2a5b6fff  CoreDuet armv7  <1f8ef623dbbc3b9081e17138af60fea1> /System/Library/PrivateFrameworks/CoreDuet.framework/CoreDuet
0x2a5bb000 - 0x2a5cafff  CoreDuetDaemonProtocol armv7  <9d71debf6b6b3904a228b2c0f4f24247> /System/Library/PrivateFrameworks/CoreDuetDaemonProtocol.framework/CoreDuetDaemonProtocol
0x2a5d1000 - 0x2a5d3fff  CoreDuetDebugLogging armv7  <f883285c891b33e0af97bb661cd655c3> /System/Library/PrivateFrameworks/CoreDuetDebugLogging.framework/CoreDuetDebugLogging
0x2a721000 - 0x2a821fff  CoreMediaStream armv7  <9bb20dd8c6873794a508d660cde4e6cf> /System/Library/PrivateFrameworks/CoreMediaStream.framework/CoreMediaStream
0x2a822000 - 0x2a8bdfff  CorePDF armv7  <518382e78bb235018d1dd8a2ce8185f0> /System/Library/PrivateFrameworks/CorePDF.framework/CorePDF
0x2a91e000 - 0x2a928fff  CoreRecents armv7  <fb0db517ef2c3df5a4401cfea8a0171c> /System/Library/PrivateFrameworks/CoreRecents.framework/CoreRecents
0x2a9a0000 - 0x2a9befff  CoreServicesInternal armv7  <460c9c860e7c3b57babb8f72c019ed4e> /System/Library/PrivateFrameworks/CoreServicesInternal.framework/CoreServicesInternal
0x2abbc000 - 0x2ac3cfff  CoreUI armv7  <49dabd90f5fc3829a2b38cb740574ccf> /System/Library/PrivateFrameworks/CoreUI.framework/CoreUI
0x2ac3d000 - 0x2aca6fff  CoreUtils armv7  <5c6b6c1e7e1330a887d84ec789a819e0> /System/Library/PrivateFrameworks/CoreUtils.framework/CoreUtils
0x2aca7000 - 0x2acacfff  CrashReporterSupport armv7  <db76db0b27993dd6a350f4b9906da07b> /System/Library/PrivateFrameworks/CrashReporterSupport.framework/CrashReporterSupport
0x2acad000 - 0x2acb3fff  DAAPKit armv7  <024d0ed467ca3f35b05e31e35c81e4a1> /System/Library/PrivateFrameworks/DAAPKit.framework/DAAPKit
0x2acb4000 - 0x2acbefff  DCIMServices armv7  <8f18cb74edb131678e64d1ac14cdfe46> /System/Library/PrivateFrameworks/DCIMServices.framework/DCIMServices
0x2acbf000 - 0x2ad04fff  DataAccess armv7  <6ade4b898da034e79943063edd83ad65> /System/Library/PrivateFrameworks/DataAccess.framework/DataAccess
0x2aef6000 - 0x2af17fff  DataAccessExpress armv7  <8cbe266570923e8d9f8497104311ca76> /System/Library/PrivateFrameworks/DataAccessExpress.framework/DataAccessExpress
0x2af56000 - 0x2af5cfff  DataMigration armv7  <8b69f877dac03e8887a8f5ad729204da> /System/Library/PrivateFrameworks/DataMigration.framework/DataMigration
0x2af66000 - 0x2af67fff  DiagnosticLogCollection armv7  <6cf05dfb8bc03f3ab10331833e57fa5b> /System/Library/PrivateFrameworks/DiagnosticLogCollection.framework/DiagnosticLogCollection
0x2af68000 - 0x2af82fff  DictionaryServices armv7  <5bc83c2a05a13a32a34c1bf78c4e2cde> /System/Library/PrivateFrameworks/DictionaryServices.framework/DictionaryServices
0x2afa1000 - 0x2afc0fff  EAP8021X armv7  <08c6ce5ecb4d31e892c4e94590b32aa9> /System/Library/PrivateFrameworks/EAP8021X.framework/EAP8021X
0x2b0bf000 - 0x2b0c1fff  FTClientServices armv7  <5fa3891f80773f08b8f79ad985eb3b49> /System/Library/PrivateFrameworks/FTClientServices.framework/FTClientServices
0x2b0c2000 - 0x2b0f2fff  FTServices armv7  <d17281a56f8d3575913152deae8d8e7a> /System/Library/PrivateFrameworks/FTServices.framework/FTServices
0x2b0f3000 - 0x2b516fff  FaceCore armv7  <4cb3244c9c313638b75c3e035a47df5d> /System/Library/PrivateFrameworks/FaceCore.framework/FaceCore
0x2b53b000 - 0x2b53bfff  FontServices armv7  <4e2379ef6f81337c8e1d2c4ec8c588df> /System/Library/PrivateFrameworks/FontServices.framework/FontServices
0x2b53c000 - 0x2b610fff  libFontParser.dylib armv7  <fddf6712351d3bb9b5d4d1bc34bf57e2> /System/Library/PrivateFrameworks/FontServices.framework/libFontParser.dylib
0x2b611000 - 0x2b61dfff  libGSFontCache.dylib armv7  <662288173dfb30e1bbe1fff6b0dc5cff> /System/Library/PrivateFrameworks/FontServices.framework/libGSFontCache.dylib
0x2b700000 - 0x2b71bfff  FrontBoardServices armv7  <cbac6a6d32a83a9c816f85a01161a2f8> /System/Library/PrivateFrameworks/FrontBoardServices.framework/FrontBoardServices
0x2c000000 - 0x2c016fff  GenerationalStorage armv7  <3f77bd8594fe3e2d891c725b1fdb2bac> /System/Library/PrivateFrameworks/GenerationalStorage.framework/GenerationalStorage
0x2c017000 - 0x2c284fff  GeoServices armv7  <e1c161192088392abf2cf032a5b33f36> /System/Library/PrivateFrameworks/GeoServices.framework/GeoServices
0x2c285000 - 0x2c295fff  GraphicsServices armv7  <224964ed8efa3333b0054cf79e716a2b> /System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices
0x2c337000 - 0x2c386fff  Heimdal armv7  <081f0416b1c5389b8e0b255429e46c1d> /System/Library/PrivateFrameworks/Heimdal.framework/Heimdal
0x2c41c000 - 0x2c49bfff  HomeSharing armv7  <0cf72b1a521d33aa844b5077338dfb7d> /System/Library/PrivateFrameworks/HomeSharing.framework/HomeSharing
0x2c4fa000 - 0x2c550fff  IDS armv7  <d680abcc1e953b21aae6500bafc651d7> /System/Library/PrivateFrameworks/IDS.framework/IDS
0x2c551000 - 0x2c573fff  IDSFoundation armv7  <cd6f6024256930e9a0ad6439453b452c> /System/Library/PrivateFrameworks/IDSFoundation.framework/IDSFoundation
0x2c5db000 - 0x2c68afff  IMCore armv7  <90ddf2086d29355d804c95ebc3ac8d02> /System/Library/PrivateFrameworks/IMCore.framework/IMCore
0x2c724000 - 0x2c788fff  IMFoundation armv7  <64ac97291a233018832a817ef38ba656> /System/Library/PrivateFrameworks/IMFoundation.framework/IMFoundation
0x2c790000 - 0x2c793fff  IOAccelerator armv7  <f00aa309007d322397e526b85dcee9f6> /System/Library/PrivateFrameworks/IOAccelerator.framework/IOAccelerator
0x2c796000 - 0x2c79cfff  IOMobileFramebuffer armv7  <45bd6cd1bd0f301c8d0a7067363271c5> /System/Library/PrivateFrameworks/IOMobileFramebuffer.framework/IOMobileFramebuffer
0x2c79d000 - 0x2c7a2fff  IOSurface armv7  <574736e1aa7535ab84270c7c858e5188> /System/Library/PrivateFrameworks/IOSurface.framework/IOSurface
0x2c7a3000 - 0x2c7a4fff  IOSurfaceAccelerator armv7  <c2f81e1c21df341d8f3114bf07ddd7b9> /System/Library/PrivateFrameworks/IOSurfaceAccelerator.framework/IOSurfaceAccelerator
0x2c840000 - 0x2c846fff  IntlPreferences armv7  <d3b4b32b2ffe36df8edf25b60c6dfb40> /System/Library/PrivateFrameworks/IntlPreferences.framework/IntlPreferences
0x2c847000 - 0x2c87dfff  LanguageModeling armv7  <f65ffb925c3b3d66bd52a73bb06bf950> /System/Library/PrivateFrameworks/LanguageModeling.framework/LanguageModeling
0x2c8b9000 - 0x2c8f5fff  MIME armv7  <6034dae451c43110ab394629dbd552e0> /System/Library/PrivateFrameworks/MIME.framework/MIME
0x2c8f6000 - 0x2c950fff  MMCS armv7  <d786d9c1425a38d6b45e680c6ab80e04> /System/Library/PrivateFrameworks/MMCS.framework/MMCS
0x2c999000 - 0x2c9a5fff  MailServices armv7  <8e0d72f2510e38f689371d3dcf5ed0d2> /System/Library/PrivateFrameworks/MailServices.framework/MailServices
0x2c9d9000 - 0x2ca79fff  ManagedConfiguration armv7  <93334cccaa793e408e1627d948d3889b> /System/Library/PrivateFrameworks/ManagedConfiguration.framework/ManagedConfiguration
0x2ca83000 - 0x2ca84fff  Marco armv7  <53094cd88ce0335fbb7785bd105324fe> /System/Library/PrivateFrameworks/Marco.framework/Marco
0x2ca85000 - 0x2cafcfff  MediaControlSender armv7  <f7e078094413382f85024e50caefd010> /System/Library/PrivateFrameworks/MediaControlSender.framework/MediaControlSender
0x2cb9b000 - 0x2cbadfff  MediaRemote armv7  <e8ade53696193d198cb55e33876b2bed> /System/Library/PrivateFrameworks/MediaRemote.framework/MediaRemote
0x2cbae000 - 0x2cbbdfff  MediaServices armv7  <4123257e5b893d0f8079656d7c063b10> /System/Library/PrivateFrameworks/MediaServices.framework/MediaServices
0x2cbbe000 - 0x2cbd6fff  MediaStream armv7  <eaf74c11a14a3dedb8df6bfc5c30bb4a> /System/Library/PrivateFrameworks/MediaStream.framework/MediaStream
0x2cc3b000 - 0x2cd19fff  Message armv7  <ba131644ebe531c197e7633c7931a1ab> /System/Library/PrivateFrameworks/Message.framework/Message
0x2cd1f000 - 0x2cd21fff  MessageSupport armv7  <56bbf6d2fc7d330f854dab1f6aa80efe> /System/Library/PrivateFrameworks/MessageSupport.framework/MessageSupport
0x2cd33000 - 0x2cd40fff  MobileAsset armv7  <1481506887163a6fb0def2fe3a063148> /System/Library/PrivateFrameworks/MobileAsset.framework/MobileAsset
0x2cd67000 - 0x2cd70fff  MobileBluetooth armv7  <b8c23903eb513eb7946e16a9d9652801> /System/Library/PrivateFrameworks/MobileBluetooth.framework/MobileBluetooth
0x2cd8c000 - 0x2cd93fff  MobileIcons armv7  <9ae48b9500b4330b8756df324494da2f> /System/Library/PrivateFrameworks/MobileIcons.framework/MobileIcons
0x2cd94000 - 0x2cd9bfff  MobileInstallation armv7  <13f848d7495e3ac19e1329b20aaf521a> /System/Library/PrivateFrameworks/MobileInstallation.framework/MobileInstallation
0x2cd9c000 - 0x2cda8fff  MobileKeyBag armv7  <b2c05dc6ee7b3ee59e3ff5da6ef2a183> /System/Library/PrivateFrameworks/MobileKeyBag.framework/MobileKeyBag
0x2cdd5000 - 0x2cdd8fff  MobileSystemServices armv7  <3c1f89fa7e613528bf9489a7a3a1457b> /System/Library/PrivateFrameworks/MobileSystemServices.framework/MobileSystemServices
0x2cdfa000 - 0x2ce07fff  MobileWiFi armv7  <4e731464a31d3c2a9aa94c0b45d52045> /System/Library/PrivateFrameworks/MobileWiFi.framework/MobileWiFi
0x2ce46000 - 0x2cfe5fff  MusicLibrary armv7  <6076ca550a49380392806971c8bb6dcc> /System/Library/PrivateFrameworks/MusicLibrary.framework/MusicLibrary
0x2d07f000 - 0x2d084fff  Netrb armv7  <074590436e5b35cd97b9993ead095d22> /System/Library/PrivateFrameworks/Netrb.framework/Netrb
0x2d085000 - 0x2d08bfff  NetworkStatistics armv7  <a7f9668047363799949464bff9fa2f09> /System/Library/PrivateFrameworks/NetworkStatistics.framework/NetworkStatistics
0x2d08c000 - 0x2d0a9fff  Notes armv7  <45274e58778c3b1c94f556830e51b4a3> /System/Library/PrivateFrameworks/Notes.framework/Notes
0x2d0af000 - 0x2d0b1fff  OAuth armv7  <949fdcebc2cb37938b6a6726763c3918> /System/Library/PrivateFrameworks/OAuth.framework/OAuth
0x2d809000 - 0x2d845fff  OpenCL armv7  <2476013a84073dd396cf58daa40ed766> /System/Library/PrivateFrameworks/OpenCL.framework/OpenCL
0x2d936000 - 0x2d95dfff  PersistentConnection armv7  <7849f2df76ac309ab8ceef2898cb2a11> /System/Library/PrivateFrameworks/PersistentConnection.framework/PersistentConnection
0x2dac7000 - 0x2dd32fff  PhotoLibraryServices armv7  <4ecb52a2744f3562877f59cad30203ce> /System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices
0x2dd33000 - 0x2dd3cfff  PhotosFormats armv7  <5daec8e2716439d5be3ada908eeffa60> /System/Library/PrivateFrameworks/PhotosFormats.framework/PhotosFormats
0x2dd3d000 - 0x2dd87fff  PhysicsKit armv7  <4cfad2d9c9df3a26bd804f4521543a75> /System/Library/PrivateFrameworks/PhysicsKit.framework/PhysicsKit
0x2dd88000 - 0x2dd9efff  PlugInKit armv7  <1df308c780c13f1eae89f6826ec17fdb> /System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit
0x2dd9f000 - 0x2dda6fff  PowerLog armv7  <fb42d57df96130b8ae790ff99e2551a9> /System/Library/PrivateFrameworks/PowerLog.framework/PowerLog
0x2dfa4000 - 0x2e04cfff  Preferences armv7  <cfd757f6082f31908dfd886f6b384ac0> /System/Library/PrivateFrameworks/Preferences.framework/Preferences
0x2e04d000 - 0x2e08afff  PrintKit armv7  <9a83e4e4ddb1323eb762e220424f56c3> /System/Library/PrivateFrameworks/PrintKit.framework/PrintKit
0x2e08f000 - 0x2e123fff  ProofReader armv7  <290ed02d482e3acaa5443ac0811ed415> /System/Library/PrivateFrameworks/ProofReader.framework/ProofReader
0x2e124000 - 0x2e133fff  ProtectedCloudStorage armv7  <34af50670d0933cd9d5d70809fbe589e> /System/Library/PrivateFrameworks/ProtectedCloudStorage.framework/ProtectedCloudStorage
0x2e134000 - 0x2e140fff  ProtocolBuffer armv7  <c6b7a055e72a3f79b3ee1824b8f0460a> /System/Library/PrivateFrameworks/ProtocolBuffer.framework/ProtocolBuffer
0x2e173000 - 0x2e1e1fff  Quagga armv7  <26e44b0355bd324eb346080d10ea6150> /System/Library/PrivateFrameworks/Quagga.framework/Quagga
0x2e3f4000 - 0x2e480fff  SAObjects armv7  <047fba39f0443d1281f43a597b9685ff> /System/Library/PrivateFrameworks/SAObjects.framework/SAObjects
0x2e61e000 - 0x2e638fff  SpringBoardServices armv7  <178517c3a9413f0c80a2eba476273d3d> /System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices
0x2e9a4000 - 0x2eabcfff  StoreServices armv7  <6f3c1a6314d03956a6221993c044f0ec> /System/Library/PrivateFrameworks/StoreServices.framework/StoreServices
0x2eb86000 - 0x2eb8dfff  SyncedDefaults armv7  <f177db17138e362985b84661f3a96177> /System/Library/PrivateFrameworks/SyncedDefaults.framework/SyncedDefaults
0x2eb8e000 - 0x2eb90fff  TCC armv7  <4dee497812173f638d8a930e2fc38e81> /System/Library/PrivateFrameworks/TCC.framework/TCC
0x2ebd7000 - 0x2ec14fff  TelephonyUtilities armv7  <7a990b1d16663f928aef7a1641ab0f31> /System/Library/PrivateFrameworks/TelephonyUtilities.framework/TelephonyUtilities
0x2f7d8000 - 0x2f800fff  TextInput armv7  <57eecb2b33da3510a22701adae4fdf43> /System/Library/PrivateFrameworks/TextInput.framework/TextInput
0x2f8b3000 - 0x2f973fff  UIFoundation armv7  <5492d9b56862324e8f4648ba374d99be> /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
0x2f990000 - 0x2f993fff  UserFS armv7  <22f60007f8813d31b7321159810d967a> /System/Library/PrivateFrameworks/UserFS.framework/UserFS
0x3010c000 - 0x3012afff  VoiceServices armv7  <90babff89f8c3632bf50b85d21e35007> /System/Library/PrivateFrameworks/VoiceServices.framework/VoiceServices
0x301b3000 - 0x301d9fff  WebBookmarks armv7  <a617030bf2db3eb4ab929972c6e9a461> /System/Library/PrivateFrameworks/WebBookmarks.framework/WebBookmarks
0x301ef000 - 0x30d5efff  WebCore armv7  <c75fdc8d04563b48a29218f89784d174> /System/Library/PrivateFrameworks/WebCore.framework/WebCore
0x30d5f000 - 0x30e1dfff  WebKitLegacy armv7  <9e4b1589e8013c05b679ccf8243aec86> /System/Library/PrivateFrameworks/WebKitLegacy.framework/WebKitLegacy
0x30fb8000 - 0x30fbefff  XPCKit armv7  <01ee4eb523f63ff6b1e357c1932126c3> /System/Library/PrivateFrameworks/XPCKit.framework/XPCKit
0x30fbf000 - 0x30fc7fff  XPCObjects armv7  <60522ad6a74c36829531b82c3d89d602> /System/Library/PrivateFrameworks/XPCObjects.framework/XPCObjects
0x311b1000 - 0x311d5fff  iCalendar armv7  <20a13df98b1234b7a2582883ce42e6c9> /System/Library/PrivateFrameworks/iCalendar.framework/iCalendar
0x311f5000 - 0x31230fff  iTunesStore armv7  <534865915ff1324c9bee2076679c4686> /System/Library/PrivateFrameworks/iTunesStore.framework/iTunesStore
0x31997000 - 0x3199ffff  libAccessibility.dylib armv7  <e05dedfb004c31568d1c47fe007309b6> /usr/lib/libAccessibility.dylib
0x31bf3000 - 0x31c09fff  libCRFSuite.dylib armv7  <d93386704a0b3b078db8e345a929ab01> /usr/lib/libCRFSuite.dylib
0x31c3b000 - 0x31d3efff  libFosl_dynamic.dylib armv7  <5c61b56d9a8037d3b7c3615d42e33891> /usr/lib/libFosl_dynamic.dylib
0x31d56000 - 0x31d57fff  libMobileCheckpoint.dylib armv7  <c805ec9af96037118971f9a4eefd091a> /usr/lib/libMobileCheckpoint.dylib
0x31d58000 - 0x31d6ffff  libMobileGestalt.dylib armv7  <5b3743ededbd388b9ef26e4665290f95> /usr/lib/libMobileGestalt.dylib
0x31d95000 - 0x31d96fff  libSystem.B.dylib armv7  <108ce41624233e74aef626d0617be497> /usr/lib/libSystem.B.dylib
0x31e07000 - 0x31e4bfff  libTelephonyUtilDynamic.dylib armv7  <022a0a1fd7493074a07c9757f35f509a> /usr/lib/libTelephonyUtilDynamic.dylib
0x31f5b000 - 0x31f7dfff  libarchive.2.dylib armv7  <9c5747f3bde23eb9904f25f4d2a48482> /usr/lib/libarchive.2.dylib
0x31f7e000 - 0x31f7efff  libassertion_extension.dylib armv7  <05566cf162f035b5aa89991ca46c26e5> /usr/lib/libassertion_extension.dylib
0x31fad000 - 0x31fb9fff  libbsm.0.dylib armv7  <b9c322e115d93e709860199baba0df40> /usr/lib/libbsm.0.dylib
0x31fba000 - 0x31fc3fff  libbz2.1.0.dylib armv7  <43c20d2a3ae630b2b00af23b29c1cf4a> /usr/lib/libbz2.1.0.dylib
0x31fc4000 - 0x3200efff  libc++.1.dylib armv7  <04463e09c37b388fb4f0d9b578ff27af> /usr/lib/libc++.1.dylib
0x3200f000 - 0x3202afff  libc++abi.dylib armv7  <201e1c5ea8a53c70aa976d54f4518c2e> /usr/lib/libc++abi.dylib
0x3202c000 - 0x32039fff  libcmph.dylib armv7  <bc6842a838a13b8e9837a3ddfba2edc9> /usr/lib/libcmph.dylib
0x3203a000 - 0x32042fff  libcupolicy.dylib armv7  <f93e0bf0d250368b94c690b1832c755f> /usr/lib/libcupolicy.dylib
0x32069000 - 0x32081fff  libextension.dylib armv7  <ec10cac678b030619f4450bf476981ac> /usr/lib/libextension.dylib
0x321b2000 - 0x321b5fff  libheimdal-asn1.dylib armv7  <0dd1fe3b2362376a9af33b267a6219d0> /usr/lib/libheimdal-asn1.dylib
0x321b6000 - 0x322a3fff  libiconv.2.dylib armv7  <a0d4cae016673389ad357ea1033c1f4d> /usr/lib/libiconv.2.dylib
0x322a4000 - 0x32412fff  libicucore.A.dylib armv7  <dbef6f558ea13739869f1cc43f13794a> /usr/lib/libicucore.A.dylib
0x3241f000 - 0x3241ffff  liblangid.dylib armv7  <3399f30bf7ea3551b32b052dc3a87aad> /usr/lib/liblangid.dylib
0x32420000 - 0x3242afff  liblockdown.dylib armv7  <03badc4e7a0d3e63b898ab085bc71543> /usr/lib/liblockdown.dylib
0x3242b000 - 0x32440fff  liblzma.5.dylib armv7  <0ede283640b036dbbcbbf042f3771b24> /usr/lib/liblzma.5.dylib
0x327bc000 - 0x327d0fff  libmis.dylib armv7  <bc591102300e3ad286a5e6e3fdfec1bd> /usr/lib/libmis.dylib
0x327d1000 - 0x327f8fff  libncurses.5.4.dylib armv7  <48bb79245a883d669ad5b1e0a86c2d04> /usr/lib/libncurses.5.4.dylib
0x327fc000 - 0x329f6fff  libobjc.A.dylib armv7  <fcccdef901003a469d4b5263d611846a> /usr/lib/libobjc.A.dylib
0x32aab000 - 0x32ac1fff  libresolv.9.dylib armv7  <f99e0bc1c4ba33ad99a3389faf59ba72> /usr/lib/libresolv.9.dylib
0x32aec000 - 0x32b91fff  libsqlite3.dylib armv7  <a81902eff78c39308cc8040889887d2e> /usr/lib/libsqlite3.dylib
0x32bdf000 - 0x32c06fff  libtidy.A.dylib armv7  <abe9491c2435315fab7fa38577d67d15> /usr/lib/libtidy.A.dylib
0x32c07000 - 0x32c0ffff  libtzupdate.dylib armv7  <34d81ea5ef0c3d6ebdd926fe96296931> /usr/lib/libtzupdate.dylib
0x32c13000 - 0x32cc9fff  libxml2.2.dylib armv7  <5445357fce2e397597851a6960538d9e> /usr/lib/libxml2.2.dylib
0x32cca000 - 0x32cebfff  libxslt.1.dylib armv7  <3373d602995e38a3b6a224205b0d1f1c> /usr/lib/libxslt.1.dylib
0x32cec000 - 0x32cf8fff  libz.1.dylib armv7  <5a3030aa2bd43c3db1b41e49b65d8852> /usr/lib/libz.1.dylib
0x32cf9000 - 0x32cfdfff  libcache.dylib armv7  <6019d220fb3e3fa69a198f520232debe> /usr/lib/system/libcache.dylib
0x32cfe000 - 0x32d07fff  libcommonCrypto.dylib armv7  <836d57a0d3f13f908568559f073df665> /usr/lib/system/libcommonCrypto.dylib
0x32d08000 - 0x32d0cfff  libcompiler_rt.dylib armv7  <23acad79bc2536cba04a16bf273d5a26> /usr/lib/system/libcompiler_rt.dylib
0x32d0d000 - 0x32d13fff  libcopyfile.dylib armv7  <96eb24b114683ec59859ad2e29558169> /usr/lib/system/libcopyfile.dylib
0x32d14000 - 0x32d60fff  libcorecrypto.dylib armv7  <159e0de6a3ee3122b0dc502d4509a2b7> /usr/lib/system/libcorecrypto.dylib
0x32d61000 - 0x32d9cfff  libdispatch.dylib armv7  <b1962ee937ec366dba9fed066d8b52c2> /usr/lib/system/libdispatch.dylib
0x32d9d000 - 0x32d9efff  libdyld.dylib armv7  <87d39df2c2aa3d899796c8c505fd95d6> /usr/lib/system/libdyld.dylib
0x32d9f000 - 0x32d9ffff  libkeymgr.dylib armv7  <5912943c373d39a999d731ba50249006> /usr/lib/system/libkeymgr.dylib
0x32da0000 - 0x32da0fff  liblaunch.dylib armv7  <5456bea7a1063c2da6cbe4038a71ed04> /usr/lib/system/liblaunch.dylib
0x32da1000 - 0x32da4fff  libmacho.dylib armv7  <524ef59bfc1e36daa4587d909bfc22eb> /usr/lib/system/libmacho.dylib
0x32da5000 - 0x32da6fff  libremovefile.dylib armv7  <45423b639f9634d8b46d4d31d0e05a50> /usr/lib/system/libremovefile.dylib
0x32da7000 - 0x32db8fff  libsystem_asl.dylib armv7  <236f31e0c18b31e59ceefdbe782e448e> /usr/lib/system/libsystem_asl.dylib
0x32db9000 - 0x32db9fff  libsystem_blocks.dylib armv7  <783efecc85a832ac962bea5bc4d365d5> /usr/lib/system/libsystem_blocks.dylib
0x32dba000 - 0x32e1cfff  libsystem_c.dylib armv7  <8d35a18fb3c73ccfb651b5b81becfa21> /usr/lib/system/libsystem_c.dylib
0x32e1d000 - 0x32e1ffff  libsystem_configuration.dylib armv7  <18a352390a1f3ce0aca8ca3fe3aa5450> /usr/lib/system/libsystem_configuration.dylib
0x32e20000 - 0x32e21fff  libsystem_coreservices.dylib armv7  <81748046d9ce39388c4c052055e41f05> /usr/lib/system/libsystem_coreservices.dylib
0x32e22000 - 0x32e2efff  libsystem_coretls.dylib armv7  <91adb1c9d7373930aa75275394bc5ab5> /usr/lib/system/libsystem_coretls.dylib
0x32e2f000 - 0x32e35fff  libsystem_dnssd.dylib armv7  <6fcb3ca6e25c317f9e8115cac1a7b94b> /usr/lib/system/libsystem_dnssd.dylib
0x32e36000 - 0x32e4efff  libsystem_info.dylib armv7  <31d0e6d3934d341b97eeb3486c13b75d> /usr/lib/system/libsystem_info.dylib
0x32e4f000 - 0x32e69fff  libsystem_kernel.dylib armv7  <86b6c92082743f5ebc303bf1046ce1b8> /usr/lib/system/libsystem_kernel.dylib
0x32e6a000 - 0x32e8afff  libsystem_m.dylib armv7  <967fd2a24c6b30b7bebb215d724cb0dd> /usr/lib/system/libsystem_m.dylib
0x32e8b000 - 0x32e9dfff  libsystem_malloc.dylib armv7  <559e2b4eb8da3a50812eb97875e75ed8> /usr/lib/system/libsystem_malloc.dylib
0x32e9e000 - 0x32ecbfff  libsystem_network.dylib armv7  <40460818237f3f6f8f37914f524fbb41> /usr/lib/system/libsystem_network.dylib
0x32ecc000 - 0x32ed1fff  libsystem_networkextension.dylib armv7  <93ecd3781a4b3b2aa063ba4d9d785554> /usr/lib/system/libsystem_networkextension.dylib
0x32ed2000 - 0x32ed9fff  libsystem_notify.dylib armv7  <551e8f86eb503925a6aef3b3b43a5b92> /usr/lib/system/libsystem_notify.dylib
0x32eda000 - 0x32edffff  libsystem_platform.dylib armv7  <dec5d5f721603b65b9baf61249e9d747> /usr/lib/system/libsystem_platform.dylib
0x32ee0000 - 0x32ee6fff  libsystem_pthread.dylib armv7  <6685c82b6d2d387aa04afd123a402bd0> /usr/lib/system/libsystem_pthread.dylib
0x32ee7000 - 0x32ee9fff  libsystem_sandbox.dylib armv7  <bcf1ac34e63438d8812b21cd7f94721b> /usr/lib/system/libsystem_sandbox.dylib
0x32eea000 - 0x32eedfff  libsystem_stats.dylib armv7  <bf7e18865b22330d9c494bb5afad64f6> /usr/lib/system/libsystem_stats.dylib
0x32eee000 - 0x32ef3fff  libsystem_trace.dylib armv7  <ec975093d6ef3440a760eb0b2bda59f2> /usr/lib/system/libsystem_trace.dylib
0x32ef4000 - 0x32ef4fff  libunwind.dylib armv7  <057b81c42ccf3d9dbfa7fd9a35ee0dab> /usr/lib/system/libunwind.dylib
0x32ef5000 - 0x32f10fff  libxpc.dylib armv7  <04694beb256f3132a00f0c82b79bc689> /usr/lib/system/libxpc.dylib

Subspecs for different patterns

I had some thoughts about separating each 'pattern' with subspec. So you'd have a subspec for block based, one for selectors and one for the old fashioned delegate.

Just a thought. I prefer the block based ones.

Cannot remove observer from inside the observing block

When i want to remove observation outside the observation block:

self.simpleObject = [SimpleObject new];
[self.KVOController observe:self.simpleObject
                    keyPath:NSStringFromSelector(@selector(simpleProperty))
                    options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew
                      block:^(AppDelegate *observer, id object, NSDictionary *change) {

}];

[self.KVOController unobserve:self.simpleObject];

then everything is fine, but when i want to remove observer from inside the block

self.simpleObject = [SimpleObject new];
[self.KVOController observe:self.simpleObject
                    keyPath:NSStringFromSelector(@selector(simpleProperty))
                    options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew
                      block:^(AppDelegate *observer, id object, NSDictionary *change) {
                            [observer.KVOController unobserve:observer.simpleObject];
}];

then i got crash, is it done by design or is it a bug?

Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <_FBKVOSharedController 0x7fa62a62d350> for the key path "simpleProperty" from <SimpleObject 0x7fa62a62b890> because it is not registered as an observer.

Unable to use action and block observers at the same time

I can reproduce it with the following code:

[self.KVOController observe:self
                    keyPath:@"textLabel.text"
                    options:NSKeyValueObservingOptionNew
                     action:@selector(sizeToFit)];

[self.KVOController observe:self
                    keyPath:@"textLabel.text"
                    options:NSKeyValueObservingOptionNew
                      block:^(id observer, id object, NSDictionary *change) {
                          NSLog(@"change = %@", change);
                          [self sizeToFit];
                      }];

The first registered observer is called, the second one is not.

Make NSObject category optional

I prefer not to use NSObject categories in my projects. KVOController includes one in it's header file now, can we move it into another header file so it is opt-in? Maybe even a subspec in the podfile?

I build the project failed. error as follows.

Undefined symbols for architecture armv7s:
"_llvm_gcov_init", referenced from:
___llvm_gcov_init in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_end_file", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_emit_function", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_emit_arcs", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_start_file", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_summary_info", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)

then I try to set the option OTHER LDFLAGS with the value of -fprofile-arcs -ftest-coverage ,and build success.
I want to konw if has other method to sovle this error all right?

Is this supposed to work in Swift?

I think I am following all the steps, but I don't get any calls except the initial call. Just once when I call the observer, whether I use the block or the selector.
Any comments very much appreciated.

Version 1.1.0 requires Xcode 7.?+

I'm not sure what the new minimum Xcode version required, but with the new changes in 1.1.0 Xcode 6.4 is no longer supported due to #91.

I'm not sure if there is a good way to call attention to it, but just in case it breaks anyone else's projects, they need to lock down the version

Bi-Directional KVO?

Is there a way to setup a bi-direction KVO in one method call? I know I can just create two observers, but since setting up observers in both directions is so common, it would be cool to be able to do it in one step.

Documentation ambiguity.

From the documentation:

While simple, the above example is complete. A clock view creates a KVO controller to observe the clock date property. A block callback is used to handle initial and change notification. Unobservation happens implicitly on controller deallocation.

I think this is not clear enough. For me the idea of something being complete, in this context, and maybe I am bit biased because I am coming from RAC, is the that the block is kept alive until self is deallocated. But, on the other hand

Unobservation happens implicitly on controller deallocation.

So in this case, is it at the end of the scope? Further:

To automatically remove observers on observer dealloc, add a strong reference between observer and KVO controller.

Is it then correct to say " While simple, the above example is complete. Although the KVOController should be kept alive by the observer"? Sorry for being pedantic, but this should be crystal clear.

Discussion: Switch filename to KVOController.h

I've started looking at using KVOController in a framework. Given that the Pod name is KVOController apple's framework expects either an umbrella header of the same name or the class having the same name.

Both are options, but renaming to KVOController feels more like the intent of the library than adding an umbrella header.

Does this version support registering Dependent Keys?

Like in Apple Document says.
There is another example in my project, When users ended up editing his address information which contains many properties(eg: city, country, state, zip code ...), we need to know if any property has been changed and give user a alert about saving these changes. I want to add a "isModified" property to "address" model, and this property depends on other properties.
Thank a lot!

Selector only executed for .Initial but never again.

Hi, I am testing to use this project in Swift. In the code below I have an UITextField hooked up as an outlet. I marked the outlet as "dynamic", as suggested here: http://stackoverflow.com/a/25219216, at least that what I think I am suppose to do.

Anyway, when I run the code it prints "New email: [email protected]" since I am setting the text to that (before setting up the KVO), this works since the option .Initial is chosen.

But when I change the text in the UITextField nothing happens. What am I doing wrong?

Is it possible to use this with UITextFields in Swift?

Thanks for any help!

   @IBOutlet weak dynamic var emailField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        emailField.text = "[email protected]"
        setupKVO()
    }

    func setupKVO() {
        let options : NSKeyValueObservingOptions = .New | .Old | .Initial | .Prior
        self.KVOController.observe(self.emailField, keyPath:"text", options: options, action:"newEmail:")
    }

    func newEmail(change: NSDictionary) {
        if let newEmail: String = change["new"] as? String {
            println("New email: \(newEmail)")
        }
    }

Even with weakSelf block still has the retain cycles problem (v1.0.3)

Even with weakSelf block still has the retain cycles problem (v1.0.3)!

__weak __typeof(self)weakSelf = self;
[self.KVOController observe:someobject
keyPath:someProperty
options:NSKeyValueObservingOptionNew
block:^(id observer, id object, NSDictionary *change) {
[weakSelf someMethod];
}

Then self never dealloc. It is easy to verify that.

If I calls [self.KVOController unobserve:someobject]; inside the block self will dealloc then. But I think it defeats the purpose of using it!

Thread safety issue of rdar://15985376 seems unfixed

I'm trying to figure out how KVOController fixes rdar://15985376. The code migrated from radar project still crashes with the latest version of KVOController.

- (void)testThreadCrash {
    FBKVOTestCircle * circle = [FBKVOTestCircle circle];

    FBKVOTestObserver * __block circleObserver = nil;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        while (YES) {
            circle.radius = CACurrentMediaTime(); //EXC_BAD_ACCESS on CFDictionaryGetValue
        }
    });

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        while (YES) {
            @autoreleasepool {
                circleObserver = [FBKVOTestObserver observer];
                [circleObserver.KVOController observe:circle keyPath:@"radius" options:optionsBasic block:^(id observer, id object, NSDictionary *change) {

                }];
            }
        }
    });

    [NSThread sleepForTimeInterval:3];
}

Dispatch notifications on a given queue?

Would it be possible to dispatch the notification block on a given queue? One of my most frequent use cases is propagating changes from model code running in background threads back to the UI. That means the notifications fire on the background thread and I have to dispatch_async onto the main queue manually all the time. It would be nice to have a feature in KVOController to set the “target” notification queue.

Passing in `self` as the observed object creates a retain cycle

I notice that if I pass self in as the observed object, like so:

[self.kvo observe:self keyPath:@"widgets" options:NSKeyValueObservingOptionInitial block:^(id observer, id object, NSDictionary* change)
{
    // Some code here.
}

...a retain cycle is created. Checking in the FBKVOController source, I notice the NSMapTable you store observed objects in retains them. Is this required? Can it be set to use weak references?

Why need SharedController ?

I see that FBSharedController has a HashTable that weakly holds FBKVOInfo, while FBKVOController strongly holds FBKVOInfo?

Why do we need FBSharedController? We can have KVOController handle "addObserver" and "observeValueForKeyPath"

Project connot build, how to fix that?

Error info like this:

Undefined symbols for architecture arm64:
"_llvm_gcov_init", referenced from:
___llvm_gcov_init in libFBKVOController.a(NSObject+FBKVOController.o)
___llvm_gcov_init in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_end_file", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(NSObject+FBKVOController.o)
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_emit_function", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(NSObject+FBKVOController.o)
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_emit_arcs", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(NSObject+FBKVOController.o)
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_start_file", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(NSObject+FBKVOController.o)
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)
"_llvm_gcda_summary_info", referenced from:
___llvm_gcov_writeout in libFBKVOController.a(NSObject+FBKVOController.o)
___llvm_gcov_writeout in libFBKVOController.a(FBKVOController.o)

Xcode fails with "Code Sign Error"

Hello there,

I compiled and installed the FBKVOController.framework, and I linked it in my own app, everything is OK when I didn't code sign my app:

no-problem

When I didn't code sign my app, everything works.

BUT when I code sign this app with my Mac Developer ID, the Xcode fails with "Code Sign Error":
error1

For details:
error2

I have tried to solve this problem through asking the Google and StackOverflow, look here and here. Not surprisingly: lot of people encountered such error. But most of them encountered this error after upgrading to Yosemite or other situations (for example, certificates expired). My certificates is up-to-date and everything is OK except coding sign this app.

Has anyone encountered the same issue? Any ideas as to what I could be missing here?

Why not allow duplication observation?

Hi, your API does not allow duplication

"Observing nil or observing an already observed object's key path results in no operation"

Why is that? What if people want to observer that same object, same keypath 2 times ?

Submit a podspec for KVOController

Using CocoaPods to fetch and link against KVOController is generally convenient and makes versioning easier. It's reasonable at the moment to have CocoaPods fetch this repo's HEAD but I think it would be even better to have a podspec.

Automatic removal of observation for not retained observed objects.

This is a follow-up issue for #48 for discussions and actual implementation of automatic removal of any observation registered via KVOController when the observed objects are not retained in any way.
The story here is that unless you let KVOController retain the objects - all of the observation becomes as fragile as it is with vanilla Cocoa KVO APIs.

Taking into account that we all would love to observe things in a "weak" way - there are 2 ways one could implement such a thing:

  • Swizzle dealloc and unregister registered observers or KVOControllers there. Sounds like less than ideal solution, but this will work just as fine. It feels very very fragile, but is a supported use case for ObjC runtime.
  • Use a separate instance of a custom class to box the original object into a property and store all of the observation info inside of it instead of a custom map table inside KVOController. As well as add all of the KVO observation with extra prefix path component whenever KVOController is registering an observer. Then store this instance via associated objects on the observed object.
    This will allow both weak reference to the original object, as well as to know the moment where we need to unregister KVO, as associated objects are cleaned up automatically on dealloc.

Do you have an idea/suggestion/comment? Great! Please post it here!
Do you want to take a chance on implementing this? Amazing! Pull requests are very very welcome, and I'll do my best to review/guide/help/drive any implementation of this.

support observing values within to-many relationships

support observing values within to-many relationships

From NSKeyValueObserving.h

/* Register or deregister as an observer of the values at a key path relative to each indexed element of the array. The options determine what is included in observer notifications and when they're sent, as described above, and the context is passed in observer notifications as described above. These are not merely convenience methods; invoking them is potentially much faster than repeatedly invoking NSObject(NSKeyValueObserverRegistration) methods. You should use -removeObserver:fromObjectsAtIndexes:forKeyPath:context: instead of -removeObserver:fromObjectsAtIndexes:forKeyPath: whenever possible for the same reason described in the NSObject(NSKeyValueObserverRegistration) comment.
*/
- (void)addObserver:(NSObject *)observer toObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
- (void)removeObserver:(NSObject *)observer fromObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath context:(void *)context NS_AVAILABLE(10_7, 5_0);
- (void)removeObserver:(NSObject *)observer fromObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath;

should NSMapTable‘s keyOption be NSMapTableWeakMemory?

in the implementation of FBKVOController

_objectInfosMap = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPointerPersonality valueOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPersonality capacity:0];

should keyOptions memory option be NSMapTableWeakMemory? like below:

_objectInfosMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableWeakMemory|NSPointerFunctionsObjectPointerPersonality valueOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPersonality capacity:0];

I guess that strong memory type will retain the observee which can postpone the relinquish of the observee.

Passing wrong context when removing observer ?

[object removeObserver:self forKeyPath:info->_keyPath context:(void *)info];

Should the context param be info->_context instead of (void *)info ?

[object removeObserver:self forKeyPath:info->_keyPath context:info->_context];

Crashing when running Unit Tests

When the Unit Tests suit starts, it will setup an observer on a singleton I got, as part of the application starting:

self.loginStateManagerKVOController = [FBKVOController controllerWithObserver:self];
[self.loginStateManagerKVOController observe:[WHLoginStateManager sharedManager] keyPath:@"userLoggedIn" options:NSKeyValueObservingOptionNew block:^(id *mainViewController, id *loginStateManager, NSDictionary *change) {

    // ....
    }];

Then I add another observer (this time as part of the Unit Test itself):

self.stateManagerKVOController = [FBKVOController controllerWithObserver:self];

[self.stateManagerKVOController observe:[WHLoginStateManager sharedManager] keyPath:@"accountDetails.firstName" options:NSKeyValueObservingOptionNew block:^(id *loginViewModel,id *stateManager, NSDictionary *change) {
   // ...
    }];

And the stack trace:

Thread 1Queue : com.apple.main-thread (serial)
#0  0x0000000112db0159 in objc_registerClassPair ()
#1  0x00000001111b76ec in _NSKVONotifyingCreateInfoWithOriginalClass ()
#2  0x00000001111b7654 in _NSKeyValueContainerClassGetNotifyingInfo ()
#3  0x0000000111195ba6 in -[NSKeyValueUnnestedProperty _isaForAutonotifying] ()
#4  0x0000000111195a26 in -[NSKeyValueUnnestedProperty isaForAutonotifying] ()
#5  0x00000001111b70c8 in -[NSObject(NSKeyValueObserverRegistration) _addObserver:forProperty:options:context:] ()
#6  0x00000001111b6d0d in -[NSObject(NSKeyValueObserverRegistration) addObserver:forKeyPath:options:context:] ()
#7  0x0000000120d75ff8 in -[_FBKVOSharedController observe:info:] 
#8  0x0000000120d776ff in -[FBKVOController _observe:info:] 
#9  0x0000000120d780ac in -[FBKVOController observe:keyPath:options:block:] 
#10 0x0000000120bf05d0 in -[WHLoginViewModel setupObservers]
#11 0x0000000120bf04a6 in -[WHLoginViewModel init] 
#12 0x0000000120bf352d in -[WHLoginTesting testShouldReturnErrorForNoInternet] 
#13 0x000000011378422c in __invoking___ ()
#14 0x0000000113784082 in -[NSInvocation invoke] ()
#15 0x000000012147e1df in -[XCTestCase invokeTest] ()
#16 0x000000012147e3e0 in -[XCTestCase performTest:] ()
#17 0x0000000121487ce5 in -[XCTest run] ()
#18 0x000000012147d14b in -[XCTestSuite performTest:] ()
#19 0x0000000121487ce5 in -[XCTest run] ()
#20 0x000000012147d14b in -[XCTestSuite performTest:] ()
#21 0x0000000121487ce5 in -[XCTest run] ()
#22 0x000000012147d14b in -[XCTestSuite performTest:] ()
#23 0x0000000121487ce5 in -[XCTest run] ()
#24 0x000000012147a20c in __25-[XCTestDriver _runSuite]_block_invoke ()
#25 0x0000000121484f9d in -[XCTestObservationCenter _observeTestExecutionForBlock:] ()
#26 0x000000012147a140 in -[XCTestDriver _runSuite] ()
#27 0x000000012147ab6d in -[XCTestDriver _checkForTestManager] ()
#28 0x000000012148abd0 in +[XCTestProbe runTests:] ()
#29 0x00000001111eea75 in __NSFireDelayedPerform ()
#30 0x00000001137f44e4 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#31 0x00000001137f40a5 in __CFRunLoopDoTimer ()
#32 0x00000001137b73dd in __CFRunLoopRun ()
#33 0x00000001137b6a06 in CFRunLoopRunSpecific ()
#34 0x0000000114d349f0 in GSEventRunModal ()
#35 0x00000001118cf550 in UIApplicationMain ()
#36 0x000000010ff0bd73 in main 
#37 0x00000001146e8145 in start ()

And the crash is here:

[object addObserver:self forKeyPath:info->_keyPath options:info->_options context:(void *)info];

With:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)

If I stop the initial app setup (like commenting the observing part [WHLoginStateManager sharedManager]), or overriding the bootstrap since it's starting because of the Unit Tests, there is no crash.

README Example of KVO with and without KVOController

It would be great to include an example in the README (or a link to a wiki page) that shows the benefits of KVOController by example.
Show code using KVOController, then the equivalent correct and safe usage of plain KVO.

The example code could be a UIViewController subclass, I think that is a common usage.

Error on Readme page?

Is this a typo on the ReadMe page or am I missing something?

Currently:
// create KVO controller with observer
FBKVOController *KVOController = [FBKVOController controllerWithObserver:self];
// add strong reference from observer to KVO controller
_KVOController = [FBKVOController controllerWithObserver:self];

Shouldn't it be:
_KVOController = KVOController;

Otherwise KVOController is unused.

Crash in arm64 due to incompatible usage of objc_msgSend.

I'm facing intermittent crashes when observing with - (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action while debugging on a 64-bit device.

It seems that we need to do a cast from objc_msgSend to the calling function prototype for it to work properly, as describe in the following document, under the section, Dispatch Objective-C Messages Using the Method Function’s Prototype.

My resulting solution is as follow:

https://github.com/facebook/KVOController/blob/master/FBKVOController/FBKVOController.m#L354

//objc_msgSend(observer, info->_action, change, object);
int (*action)(id, SEL, NSDictionary *, id) = (int (*)(id, SEL, NSDictionary *, id)) objc_msgSend;
action(observer, info->_action, change, object);

Although the above solution works, I gave a bit more thoughts to it and wonder if we really need to go down to the objective-c runtime to send a message. It feels a bit unsafe.

I understand that we can't use performSelector as it will throw warning under ARC but we could use NSInvocation to achieve a safer albeit more expensive solution.

NSMethodSignature *methodSignature = [observer methodSignatureForSelector:info->_action];
if (methodSignature) {
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    invocation.target = observer;
    invocation.selector = info->_action;
    [invocation setArgument:&change atIndex:2];
    [invocation setArgument:&object atIndex:3];
    [invocation invoke];
}

Thanks!

When will dealloc be called?

Hi, you stated that

Unobservation happens implicitly on controller deallocation.

To automatically remove observers on observer dealloc, add a strong reference > between observer and KVO controller

What if controller can't be deallocated? Because inside of the block, I use self

[KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(ClockView *clockView, Clock *clock, NSDictionary *change) {

  // do something with self
  [self doSomething];
}];

So SharedController holds KVOInfo, which holds block, which holds self, which holds KVOController

So dealloc on KVOController will never called

Please correct me if I'm wrong

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.