master 1ee564830a46 cached
59 files
239.9 KB
64.1k tokens
1 symbols
1 requests
Download .txt
Showing preview only (257K chars total). Download the full file or copy to clipboard to get everything.
Repository: facebookarchive/KVOController
Branch: master
Commit: 1ee564830a46
Files: 59
Total size: 239.9 KB

Directory structure:
gitextract_aqb3k6nd/

├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── Examples/
│   ├── Clock-OSX/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Base.lproj/
│   │   │   └── MainMenu.xib
│   │   ├── Clock-OSX-Info.plist
│   │   ├── Clock-OSX-Prefix.pch
│   │   ├── ClockView.h
│   │   ├── ClockView.m
│   │   ├── Images.xcassets/
│   │   │   └── AppIcon.appiconset/
│   │   │       └── Contents.json
│   │   ├── en.lproj/
│   │   │   ├── Credits.rtf
│   │   │   └── InfoPlist.strings
│   │   └── main.m
│   ├── Clock-iOS/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Base.lproj/
│   │   │   ├── Main_iPad.storyboard
│   │   │   └── Main_iPhone.storyboard
│   │   ├── Clock-iOS-Info.plist
│   │   ├── Clock-iOS-Prefix.pch
│   │   ├── Clock.h
│   │   ├── Clock.m
│   │   ├── ClockLayer.h
│   │   ├── ClockLayer.m
│   │   ├── ClockView.h
│   │   ├── ClockView.m
│   │   ├── Images.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.launchimage/
│   │   │       └── Contents.json
│   │   ├── ViewController.h
│   │   ├── ViewController.m
│   │   ├── en.lproj/
│   │   │   └── InfoPlist.strings
│   │   └── main.m
│   └── Examples.xcodeproj/
│       └── project.pbxproj
├── FBKVOController/
│   ├── FBKVOController.h
│   ├── FBKVOController.m
│   ├── Info.plist
│   ├── KVOController.h
│   ├── NSObject+FBKVOController.h
│   └── NSObject+FBKVOController.m
├── FBKVOController.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   └── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           ├── FBKVOController-OSX-Dynamic.xcscheme
│           ├── FBKVOController-iOS-Dynamic.xcscheme
│           ├── FBKVOController-tvOS-Dynamic.xcscheme
│           ├── FBKVOController-watchOS-Dynamic.xcscheme
│           └── FBKVOController.xcscheme
├── FBKVOController.xcworkspace/
│   └── contents.xcworkspacedata
├── FBKVOControllerTests/
│   ├── FBKVOControllerTests-Info.plist
│   ├── FBKVOControllerTests.m
│   ├── FBKVOTesting.h
│   ├── FBKVOTesting.m
│   └── en.lproj/
│       └── InfoPlist.strings
├── KVOController.podspec
├── LICENSE
├── PATENTS
├── Podfile
├── README.md
├── Rakefile
└── codecov.yml

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
## OS X
.DS_Store

## Build generated
build/
DerivedData

## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata

## Other
*.xccheckout
*.moved-aside
*.xcuserstate
*.xcscmblueprint

## Obj-C/Swift specific
*.hmap
*.ipa

## Dependency Managers
Pods/
Carthage/Build

## AppCode
.idea/


================================================
FILE: .travis.yml
================================================
branches:
  only:
    - master
language: objective-c
os: osx
osx_image: xcode8.2
env:
  matrix:
    - TEST_TYPE=iOS
    - TEST_TYPE=CocoaPods
    - TEST_TYPE=Carthage
install:
- |
  if [ "$TEST_TYPE" = "iOS" ]; then
    gem install xcpretty -N --no-ri --no-rdoc
    gem update cocoapods
    pod install
  elif [ "$TEST_TYPE" = Carthage ]; then    
    brew install carthage || brew upgrade carthage
  fi
script:
- |
  if [ "$TEST_TYPE" = "iOS" ]; then
    set -o pipefail
    xcodebuild test -workspace FBKVOController.xcworkspace -scheme FBKVOController -sdk iphonesimulator -destination "platform=iOS Simulator,OS=latest,name=iPhone 4s" -destination "platform=iOS Simulator,OS=latest,name=iPad Air 2" GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | xcpretty -c
  elif [ "$TEST_TYPE" = CocoaPods ]; then
    pod lib lint KVOController.podspec
    pod lib lint --use-libraries KVOController.podspec
  elif [ "$TEST_TYPE" = Carthage ]; then
    carthage build --no-skip-current
  fi
after_success:
- |
  if [ "$TEST_TYPE" = "iOS" ]; then
    bash <(curl -s https://codecov.io/bash)
  fi


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
We want to make contributing to KVOController as easy and transparent as
possible. If you run into problems, please open an issue. We also actively welcome pull requests.

## Pull Requests
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests
3. If you've changed APIs, update the documentation. 
4. Ensure the test suite passes. 
5. Make sure your code lints. 
6. If you haven't already, complete the Contributor License Agreement ("CLA").

## Contributor License Agreement ("CLA")
In order to accept your pull request, we need you to submit a CLA. You only need
to do this once to work on any of Facebook's open source projects.

Complete your CLA here: <https://developers.facebook.com/opensource/cla>

## Issues  
We use GitHub issues to track public bugs. Please ensure your description is
clear and has sufficient instructions to be able to reproduce the issue.

## Coding Style  
* 2 spaces for indentation rather than tabs

## License
By contributing to KVOController, you agree that your contributions will be licensed
under its BSD license.


================================================
FILE: Examples/Clock-OSX/AppDelegate.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;

@end


================================================
FILE: Examples/Clock-OSX/AppDelegate.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import "AppDelegate.h"
#import "Clock.h"
#import "ClockView.h"

@interface AppDelegate()
@end

#define CLOCK_VIEW_MAX_COUNT 10
#define CLOCK_VIEW_TIME_DELAY 3.0

@implementation AppDelegate
{
  NSMutableArray *_clockViews;
  dispatch_source_t _timer;
}

- (void)dealloc
{
  if (NULL != _timer) {
    dispatch_source_cancel(_timer);
  }
}

- (void)_addClockView
{
  if (!_clockViews) {
    _clockViews = [NSMutableArray array];
  }

  ClockView *clockView = [[ClockView alloc] initWithClock:[Clock clock]];
  [_clockViews addObject:clockView];
  [_window.contentView addSubview:clockView];

  NSSize clockSize = clockView.bounds.size;
  NSRect contentBounds = [_window.contentView bounds];

  [clockView setFrameOrigin:NSMakePoint(arc4random_uniform(contentBounds.size.width) - (clockSize.width / 2.), arc4random_uniform(contentBounds.size.height) - (clockSize.height / 2.))];
}

- (void)_removeClockView
{
  if (0 == _clockViews.count) {
    return;
  }

  [_clockViews[0] removeFromSuperview];
  [_clockViews removeObjectAtIndex:0];
}

- (void)_removeAddClockView
{
  [self _removeClockView];
  [self _addClockView];
}

- (void)_scheduleTimer
{
  dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
  dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, CLOCK_VIEW_TIME_DELAY * NSEC_PER_SEC), CLOCK_VIEW_TIME_DELAY * NSEC_PER_SEC, 1.0);
  
  __weak id weakSelf = self;
  dispatch_source_set_event_handler(timer, ^{
    [weakSelf _removeAddClockView];
  });

  _timer = timer;
  dispatch_resume(timer);
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
  while (_clockViews.count < CLOCK_VIEW_MAX_COUNT) {
    [self _addClockView];
  }
  
  [self _scheduleTimer];
}

@end


================================================
FILE: Examples/Clock-OSX/Base.lproj/MainMenu.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B3116" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
            <connections>
                <outlet property="delegate" destination="494" id="495"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application"/>
        <menu title="AMainMenu" systemMenu="main" id="29">
            <items>
                <menuItem title="Clock-OSX" id="56">
                    <menu key="submenu" title="Clock-OSX" systemMenu="apple" id="57">
                        <items>
                            <menuItem title="About Clock-OSX" id="58">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="236">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Preferences…" keyEquivalent="," id="129"/>
                            <menuItem isSeparatorItem="YES" id="143">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Services" id="131">
                                <menu key="submenu" title="Services" systemMenu="services" id="130"/>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="144">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Hide Clock-OSX" keyEquivalent="h" id="134">
                                <connections>
                                    <action selector="hide:" target="-1" id="367"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Hide Others" keyEquivalent="h" id="145">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="hideOtherApplications:" target="-1" id="368"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Show All" id="150">
                                <connections>
                                    <action selector="unhideAllApplications:" target="-1" id="370"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="149">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Quit Clock-OSX" keyEquivalent="q" id="136">
                                <connections>
                                    <action selector="terminate:" target="-3" id="449"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="File" id="83">
                    <menu key="submenu" title="File" id="81">
                        <items>
                            <menuItem title="New" keyEquivalent="n" id="82">
                                <connections>
                                    <action selector="newDocument:" target="-1" id="373"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Open…" keyEquivalent="o" id="72">
                                <connections>
                                    <action selector="openDocument:" target="-1" id="374"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Open Recent" id="124">
                                <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="125">
                                    <items>
                                        <menuItem title="Clear Menu" id="126">
                                            <connections>
                                                <action selector="clearRecentDocuments:" target="-1" id="127"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="79">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Close" keyEquivalent="w" id="73">
                                <connections>
                                    <action selector="performClose:" target="-1" id="193"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Save…" keyEquivalent="s" id="75">
                                <connections>
                                    <action selector="saveDocument:" target="-1" id="362"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Revert to Saved" id="112">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="revertDocumentToSaved:" target="-1" id="364"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="74">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Page Setup..." keyEquivalent="P" id="77">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                <connections>
                                    <action selector="runPageLayout:" target="-1" id="87"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Print…" keyEquivalent="p" id="78">
                                <connections>
                                    <action selector="print:" target="-1" id="86"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Edit" id="217">
                    <menu key="submenu" title="Edit" id="205">
                        <items>
                            <menuItem title="Undo" keyEquivalent="z" id="207">
                                <connections>
                                    <action selector="undo:" target="-1" id="223"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Redo" keyEquivalent="Z" id="215">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                <connections>
                                    <action selector="redo:" target="-1" id="231"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="206">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Cut" keyEquivalent="x" id="199">
                                <connections>
                                    <action selector="cut:" target="-1" id="228"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Copy" keyEquivalent="c" id="197">
                                <connections>
                                    <action selector="copy:" target="-1" id="224"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Paste" keyEquivalent="v" id="203">
                                <connections>
                                    <action selector="paste:" target="-1" id="226"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="pasteAsPlainText:" target="-1" id="486"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Delete" id="202">
                                <connections>
                                    <action selector="delete:" target="-1" id="235"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Select All" keyEquivalent="a" id="198">
                                <connections>
                                    <action selector="selectAll:" target="-1" id="232"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="214">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Find" id="218">
                                <menu key="submenu" title="Find" id="220">
                                    <items>
                                        <menuItem title="Find…" tag="1" keyEquivalent="f" id="209">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="241"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="534">
                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="535"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find Next" tag="2" keyEquivalent="g" id="208">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="487"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="213">
                                            <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="488"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="221">
                                            <connections>
                                                <action selector="performFindPanelAction:" target="-1" id="489"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Jump to Selection" keyEquivalent="j" id="210">
                                            <connections>
                                                <action selector="centerSelectionInVisibleArea:" target="-1" id="245"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Spelling and Grammar" id="216">
                                <menu key="submenu" title="Spelling and Grammar" id="200">
                                    <items>
                                        <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="204">
                                            <connections>
                                                <action selector="showGuessPanel:" target="-1" id="230"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Check Document Now" keyEquivalent=";" id="201">
                                            <connections>
                                                <action selector="checkSpelling:" target="-1" id="225"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="453"/>
                                        <menuItem title="Check Spelling While Typing" id="219">
                                            <connections>
                                                <action selector="toggleContinuousSpellChecking:" target="-1" id="222"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Check Grammar With Spelling" id="346">
                                            <connections>
                                                <action selector="toggleGrammarChecking:" target="-1" id="347"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Correct Spelling Automatically" id="454">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="456"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Substitutions" id="348">
                                <menu key="submenu" title="Substitutions" id="349">
                                    <items>
                                        <menuItem title="Show Substitutions" id="457">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="orderFrontSubstitutionsPanel:" target="-1" id="458"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="459"/>
                                        <menuItem title="Smart Copy/Paste" tag="1" keyEquivalent="f" id="350">
                                            <connections>
                                                <action selector="toggleSmartInsertDelete:" target="-1" id="355"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Quotes" tag="2" keyEquivalent="g" id="351">
                                            <connections>
                                                <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="356"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Dashes" id="460">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticDashSubstitution:" target="-1" id="461"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smart Links" tag="3" keyEquivalent="G" id="354">
                                            <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                            <connections>
                                                <action selector="toggleAutomaticLinkDetection:" target="-1" id="357"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Text Replacement" id="462">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleAutomaticTextReplacement:" target="-1" id="463"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Transformations" id="450">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Transformations" id="451">
                                    <items>
                                        <menuItem title="Make Upper Case" id="452">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="uppercaseWord:" target="-1" id="464"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Make Lower Case" id="465">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="lowercaseWord:" target="-1" id="468"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Capitalize" id="466">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="capitalizeWord:" target="-1" id="467"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Speech" id="211">
                                <menu key="submenu" title="Speech" id="212">
                                    <items>
                                        <menuItem title="Start Speaking" id="196">
                                            <connections>
                                                <action selector="startSpeaking:" target="-1" id="233"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Stop Speaking" id="195">
                                            <connections>
                                                <action selector="stopSpeaking:" target="-1" id="227"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Format" id="375">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Format" id="376">
                        <items>
                            <menuItem title="Font" id="377">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Font" systemMenu="font" id="388">
                                    <items>
                                        <menuItem title="Show Fonts" keyEquivalent="t" id="389">
                                            <connections>
                                                <action selector="orderFrontFontPanel:" target="420" id="424"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Bold" tag="2" keyEquivalent="b" id="390">
                                            <connections>
                                                <action selector="addFontTrait:" target="420" id="421"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Italic" tag="1" keyEquivalent="i" id="391">
                                            <connections>
                                                <action selector="addFontTrait:" target="420" id="422"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Underline" keyEquivalent="u" id="392">
                                            <connections>
                                                <action selector="underline:" target="-1" id="432"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="393"/>
                                        <menuItem title="Bigger" tag="3" keyEquivalent="+" id="394">
                                            <connections>
                                                <action selector="modifyFont:" target="420" id="425"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Smaller" tag="4" keyEquivalent="-" id="395">
                                            <connections>
                                                <action selector="modifyFont:" target="420" id="423"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="396"/>
                                        <menuItem title="Kern" id="397">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <menu key="submenu" title="Kern" id="415">
                                                <items>
                                                    <menuItem title="Use Default" id="416">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="useStandardKerning:" target="-1" id="438"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Use None" id="417">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="turnOffKerning:" target="-1" id="441"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Tighten" id="418">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="tightenKerning:" target="-1" id="431"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Loosen" id="419">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="loosenKerning:" target="-1" id="435"/>
                                                        </connections>
                                                    </menuItem>
                                                </items>
                                            </menu>
                                        </menuItem>
                                        <menuItem title="Ligatures" id="398">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <menu key="submenu" title="Ligatures" id="411">
                                                <items>
                                                    <menuItem title="Use Default" id="412">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="useStandardLigatures:" target="-1" id="439"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Use None" id="413">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="turnOffLigatures:" target="-1" id="440"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Use All" id="414">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="useAllLigatures:" target="-1" id="434"/>
                                                        </connections>
                                                    </menuItem>
                                                </items>
                                            </menu>
                                        </menuItem>
                                        <menuItem title="Baseline" id="399">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <menu key="submenu" title="Baseline" id="405">
                                                <items>
                                                    <menuItem title="Use Default" id="406">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="unscript:" target="-1" id="437"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Superscript" id="407">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="superscript:" target="-1" id="430"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Subscript" id="408">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="subscript:" target="-1" id="429"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Raise" id="409">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="raiseBaseline:" target="-1" id="426"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem title="Lower" id="410">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="lowerBaseline:" target="-1" id="427"/>
                                                        </connections>
                                                    </menuItem>
                                                </items>
                                            </menu>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="400"/>
                                        <menuItem title="Show Colors" keyEquivalent="C" id="401">
                                            <connections>
                                                <action selector="orderFrontColorPanel:" target="-1" id="433"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="402"/>
                                        <menuItem title="Copy Style" keyEquivalent="c" id="403">
                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                            <connections>
                                                <action selector="copyFont:" target="-1" id="428"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Paste Style" keyEquivalent="v" id="404">
                                            <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                            <connections>
                                                <action selector="pasteFont:" target="-1" id="436"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem title="Text" id="496">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Text" id="497">
                                    <items>
                                        <menuItem title="Align Left" keyEquivalent="{" id="498">
                                            <connections>
                                                <action selector="alignLeft:" target="-1" id="524"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Center" keyEquivalent="|" id="499">
                                            <connections>
                                                <action selector="alignCenter:" target="-1" id="518"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Justify" id="500">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="alignJustified:" target="-1" id="523"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Align Right" keyEquivalent="}" id="501">
                                            <connections>
                                                <action selector="alignRight:" target="-1" id="521"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="502"/>
                                        <menuItem title="Writing Direction" id="503">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <menu key="submenu" title="Writing Direction" id="508">
                                                <items>
                                                    <menuItem title="Paragraph" enabled="NO" id="509">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                    </menuItem>
                                                    <menuItem id="510">
                                                        <string key="title">	Default</string>
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="makeBaseWritingDirectionNatural:" target="-1" id="525"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem id="511">
                                                        <string key="title">	Left to Right</string>
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="526"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem id="512">
                                                        <string key="title">	Right to Left</string>
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="527"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem isSeparatorItem="YES" id="513"/>
                                                    <menuItem title="Selection" enabled="NO" id="514">
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                    </menuItem>
                                                    <menuItem id="515">
                                                        <string key="title">	Default</string>
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="makeTextWritingDirectionNatural:" target="-1" id="528"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem id="516">
                                                        <string key="title">	Left to Right</string>
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="529"/>
                                                        </connections>
                                                    </menuItem>
                                                    <menuItem id="517">
                                                        <string key="title">	Right to Left</string>
                                                        <modifierMask key="keyEquivalentModifierMask"/>
                                                        <connections>
                                                            <action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="530"/>
                                                        </connections>
                                                    </menuItem>
                                                </items>
                                            </menu>
                                        </menuItem>
                                        <menuItem isSeparatorItem="YES" id="504"/>
                                        <menuItem title="Show Ruler" id="505">
                                            <modifierMask key="keyEquivalentModifierMask"/>
                                            <connections>
                                                <action selector="toggleRuler:" target="-1" id="520"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Copy Ruler" keyEquivalent="c" id="506">
                                            <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
                                            <connections>
                                                <action selector="copyRuler:" target="-1" id="522"/>
                                            </connections>
                                        </menuItem>
                                        <menuItem title="Paste Ruler" keyEquivalent="v" id="507">
                                            <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
                                            <connections>
                                                <action selector="pasteRuler:" target="-1" id="519"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="View" id="295">
                    <menu key="submenu" title="View" id="296">
                        <items>
                            <menuItem title="Show Toolbar" keyEquivalent="t" id="297">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="toggleToolbarShown:" target="-1" id="366"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Customize Toolbar…" id="298">
                                <connections>
                                    <action selector="runToolbarCustomizationPalette:" target="-1" id="365"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Window" id="19">
                    <menu key="submenu" title="Window" systemMenu="window" id="24">
                        <items>
                            <menuItem title="Minimize" keyEquivalent="m" id="23">
                                <connections>
                                    <action selector="performMiniaturize:" target="-1" id="37"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Zoom" id="239">
                                <connections>
                                    <action selector="performZoom:" target="-1" id="240"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="92">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Bring All to Front" id="5">
                                <connections>
                                    <action selector="arrangeInFront:" target="-1" id="39"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Help" id="490">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Help" systemMenu="help" id="491">
                        <items>
                            <menuItem title="Clock-OSX Help" keyEquivalent="?" id="492">
                                <connections>
                                    <action selector="showHelp:" target="-1" id="493"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
            </items>
        </menu>
        <window title="Clock-OSX" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
            <rect key="contentRect" x="335" y="390" width="480" height="360"/>
            <rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
            <view key="contentView" id="372">
                <rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
                <autoresizingMask key="autoresizingMask"/>
            </view>
        </window>
        <customObject id="494" customClass="AppDelegate">
            <connections>
                <outlet property="window" destination="371" id="532"/>
            </connections>
        </customObject>
        <customObject id="420" customClass="NSFontManager"/>
    </objects>
</document>

================================================
FILE: Examples/Clock-OSX/Clock-OSX-Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIconFile</key>
	<string></string>
	<key>CFBundleIdentifier</key>
	<string>com.facebook.${PRODUCT_NAME:rfc1034identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>LSMinimumSystemVersion</key>
	<string>${MACOSX_DEPLOYMENT_TARGET}</string>
	<key>NSMainNibFile</key>
	<string>MainMenu</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
</dict>
</plist>


================================================
FILE: Examples/Clock-OSX/Clock-OSX-Prefix.pch
================================================
//
//  Prefix header
//
//  The contents of this file are implicitly included at the beginning of every source file.
//

#ifdef __OBJC__
  #import <Cocoa/Cocoa.h>
#endif


================================================
FILE: Examples/Clock-OSX/ClockView.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <Cocoa/Cocoa.h>

@class Clock;

@interface ClockView : NSDatePicker
- (instancetype)initWithClock:(Clock *)clock;
@end


================================================
FILE: Examples/Clock-OSX/ClockView.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import "ClockView.h"
#import "Clock.h"
#import "FBKVOController.h"

@implementation ClockView
{
  FBKVOController *_KVOController;
}

- (instancetype)initWithFrame:(NSRect)frameRect
{
  self = [super initWithFrame:frameRect];
  if (nil != self) {
    self.datePickerStyle = NSClockAndCalendarDatePickerStyle;
    self.datePickerElements = NSHourMinuteSecondDatePickerElementFlag;
    [self sizeToFit];
  }
  return self;
}

- (instancetype)initWithClock:(Clock *)clock
{
  self = [self init];
  if (nil != self) {
    // create KVO controller instance
    _KVOController = [FBKVOController controllerWithObserver:self];

    // handle clock change, including initial value
    [_KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(ClockView *clockView, Clock *clock, NSDictionary *change) {

      // update observer with new value
      clockView.dateValue = change[NSKeyValueChangeNewKey];
    }];
  }
  return self;
}

@end


================================================
FILE: Examples/Clock-OSX/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "mac",
      "size" : "16x16",
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "size" : "16x16",
      "scale" : "2x"
    },
    {
      "idiom" : "mac",
      "size" : "32x32",
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "size" : "32x32",
      "scale" : "2x"
    },
    {
      "idiom" : "mac",
      "size" : "128x128",
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "size" : "128x128",
      "scale" : "2x"
    },
    {
      "idiom" : "mac",
      "size" : "256x256",
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "size" : "256x256",
      "scale" : "2x"
    },
    {
      "idiom" : "mac",
      "size" : "512x512",
      "scale" : "1x"
    },
    {
      "idiom" : "mac",
      "size" : "512x512",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Examples/Clock-OSX/en.lproj/Credits.rtf
================================================
{\rtf1\ansi\ansicpg1252\cocoartf1265
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset128 HiraKakuProN-W3;}
{\colortbl;\red255\green255\blue255;}
\vieww9600\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720

\f0\b\fs24 \cf0 Engineering:
\b0 \
	Kimon Tsinteris\
\

\b Testing:
\b0 \
	Kimon Tsinteris\
\

\b Documentation:
\b0 \
	Kimon Tsinteris\
\

\b With special thanks to:
\b0 \
	
\f1\fs60 \uc0\u9731 
\f0\fs24 \
}

================================================
FILE: Examples/Clock-OSX/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */



================================================
FILE: Examples/Clock-OSX/main.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[])
{
  return NSApplicationMain(argc, argv);
}


================================================
FILE: Examples/Clock-iOS/AppDelegate.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end


================================================
FILE: Examples/Clock-iOS/AppDelegate.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  return YES;
}

@end


================================================
FILE: Examples/Clock-iOS/Base.lproj/Main_iPad.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10112" systemVersion="15D21" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" initialViewController="BYZ-38-t0r">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10083"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="tne-QT-ifu">
            <objects>
                <viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Udy-qk-fWK"/>
                        <viewControllerLayoutGuide type="bottom" id="IVD-gd-LhQ"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="768" height="1024"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </view>
                    <nil key="simulatedStatusBarMetrics"/>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
    <simulatedMetricsContainer key="defaultSimulatedMetrics">
        <simulatedStatusBarMetrics key="statusBar" statusBarStyle="blackOpaque"/>
        <simulatedOrientationMetrics key="orientation"/>
        <simulatedScreenMetrics key="destination"/>
    </simulatedMetricsContainer>
</document>


================================================
FILE: Examples/Clock-iOS/Base.lproj/Main_iPhone.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10112" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="vXZ-lx-hvc">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10083"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="ufC-wZ-h7g">
            <objects>
                <viewController id="vXZ-lx-hvc" customClass="ViewController" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Zp7-iv-QNL"/>
                        <viewControllerLayoutGuide type="bottom" id="Rd3-tm-V1t"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                    </view>
                    <nil key="simulatedStatusBarMetrics"/>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
            </objects>
        </scene>
    </scenes>
</document>


================================================
FILE: Examples/Clock-iOS/Clock-iOS-Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleDisplayName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIdentifier</key>
	<string>com.facebook.${PRODUCT_NAME:rfc1034identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.0</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UIMainStoryboardFile</key>
	<string>Main_iPhone</string>
	<key>UIMainStoryboardFile~ipad</key>
	<string>Main_iPad</string>
	<key>UIRequiredDeviceCapabilities</key>
	<array>
		<string>armv7</string>
	</array>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIStatusBarHidden</key>
	<true/>
	<key>UIStatusBarStyle</key>
	<string></string>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
</dict>
</plist>


================================================
FILE: Examples/Clock-iOS/Clock-iOS-Prefix.pch
================================================
//
//  Prefix header
//
//  The contents of this file are implicitly included at the beginning of every source file.
//

#import <Availability.h>

#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif

#ifdef __OBJC__
  #import <UIKit/UIKit.h>
  #import <Foundation/Foundation.h>
#endif


================================================
FILE: Examples/Clock-iOS/Clock.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <Foundation/Foundation.h>

@interface Clock : NSObject

/// The shared clock instance.
+ (instancetype)clock;

/// The curent date and time. Observable.
@property (strong, readonly, nonatomic) NSDate *date;

@end


================================================
FILE: Examples/Clock-iOS/Clock.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import "Clock.h"

@interface Clock ()
@property (strong, readwrite, nonatomic) NSDate *date;
@end

@implementation Clock
{
  dispatch_source_t _timer;
}

+ (instancetype)clock
{
  static Clock *_clock = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _clock = [[Clock alloc] init];
  });
  return _clock;
}

- (id)init
{
  self = [super init];
  if (self) {
    [self _updateDate];

    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.0);

    __weak Clock *weakSelf = self;
    dispatch_source_set_event_handler(timer, ^{
      [weakSelf _updateDate];
    });

    _timer = timer;
    dispatch_resume(timer);
  }
  return self;
}

- (void)dealloc
{
  if (NULL != _timer) {
    dispatch_source_cancel(_timer);
  }
}

- (void)_updateDate
{
  self.date = [NSDate date];
}

@end


================================================
FILE: Examples/Clock-iOS/ClockLayer.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <QuartzCore/QuartzCore.h>

@interface ClockLayer : CALayer

+ (NSDictionary *)darkStyle;

+ (NSDictionary *)lightStyle;

@property (strong, nonatomic) NSDate *date;

@end


================================================
FILE: Examples/Clock-iOS/ClockLayer.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import "ClockLayer.h"
#import <CoreText/CoreText.h>

// number layer attributes
#define NUMBER_LAYER_COUNT 12
#define NUMBER_FONT_NAME @"HelveticaNeue"
#define NUMBER_FONT_SIZE 16.0

// normalized hand length, ratio of clock radius
#define SECOND_HAND_LENGTH 0.57
#define MINUTE_HAND_LENGTH 0.65
#define HOUR_HAND_LENGTH 0.5

@interface ElipseLayer : CAShapeLayer
@end

@implementation ElipseLayer

- (void)setBounds:(CGRect)bounds
{
  if (!CGRectEqualToRect(self.bounds, bounds)) {
    super.bounds = bounds;
    if (CGRectEqualToRect(CGRectZero, bounds)) {
      self.path = NULL;
    } else {
      CGMutablePathRef path = CGPathCreateMutable();
      CGPathAddEllipseInRect(path, nil, bounds);
      self.path = path;
      CGPathRelease(path);
    }
  }
}

@end

static CALayer *hand_layer(CGFloat contentsScale)
{
  CALayer *layer = [CALayer layer];
  layer.contentsScale = contentsScale;
  layer.shouldRasterize = YES;
  return layer;
}

static ElipseLayer *elipse_layer(CGFloat contentsScale)
{
  ElipseLayer *layer = [ElipseLayer layer];
  layer.contentsScale = contentsScale;
  layer.shouldRasterize = YES;
  return layer;
}

static CATextLayer *number_layer(CGFloat contentsScale, CTFontRef font, NSUInteger number)
{
  CATextLayer *layer = [CATextLayer layer];
  layer.string = [NSString stringWithFormat:@"%lu", (unsigned long)number];
  layer.alignmentMode = kCAAlignmentCenter;
  layer.fontSize = NUMBER_FONT_SIZE;
  layer.font = font;
  layer.contentsScale = contentsScale;
  return layer;
}

// clock style keys
static NSString * const kClockBackgroundColorKey = @"clockBackgroundColor";
static NSString * const kClockForegroundColorKey = @"clockForegroundColor";
static NSString * const kClockAccentColorKey = @"clockAccentColor";

// clock style properties
@interface ClockLayer ()
@property (readonly) UIColor *clockBackgroundColor;
@property (readonly) UIColor *clockForegroundColor;
@property (readonly) UIColor *clockAccentColor;
@end

@implementation ClockLayer
{
  ElipseLayer *_faceLayer;
  ElipseLayer *_largeDotLayer;
  ElipseLayer *_smallDotLayer;
  CALayer *_secondHandLayer;
  CALayer *_minuteHandLayer;
  CALayer *_hourHandLayer;
  NSArray *_numberLayers;
  CGFloat _radius;
  BOOL _needsFullLayout;
}

#pragma mark - Class

// dark style definition
+ (NSDictionary *)darkStyle
{
  return @{kClockBackgroundColorKey: [UIColor blackColor],
           kClockForegroundColorKey: [UIColor whiteColor],
           kClockAccentColorKey: [UIColor redColor]};
}

// light style definition
+ (NSDictionary *)lightStyle
{
  return @{kClockBackgroundColorKey: [UIColor whiteColor],
           kClockForegroundColorKey: [UIColor blackColor],
           kClockAccentColorKey: [UIColor redColor]};
}

// default style definition
+ (id)defaultValueForKey:(NSString *)key
{
  id value = [self darkStyle][key];
  if (nil != value) {
    return value;
  }
  return [super defaultValueForKey:key];
}

#pragma mark - Lifecycle

- (id)init
{
  self = [super init];
  if (self) {
    // default contents scale
    CGFloat contentsScale = [UIScreen mainScreen].scale;
    
    // elipse layers
    _faceLayer = elipse_layer(contentsScale);
    _largeDotLayer = elipse_layer(contentsScale);
    _smallDotLayer = elipse_layer(contentsScale);
    
    // number layers
    CTFontRef font = CTFontCreateWithName((CFStringRef)NUMBER_FONT_NAME, NUMBER_FONT_SIZE, NULL);
    NSMutableArray *numberLayers = [NSMutableArray arrayWithCapacity:NUMBER_LAYER_COUNT];
    for (NSUInteger i=1; i <= NUMBER_LAYER_COUNT; ++i) {
      [numberLayers addObject:number_layer(contentsScale, font, i)];
    }
    _numberLayers = numberLayers;
    
    // hand layers
    _hourHandLayer = hand_layer(contentsScale);
    _minuteHandLayer = hand_layer(contentsScale);
    _secondHandLayer = hand_layer(contentsScale);
    
    // update sublayers
    NSMutableArray *sublayers = [NSMutableArray arrayWithObjects:_faceLayer, nil];
    [sublayers addObjectsFromArray:_numberLayers];
    [sublayers addObjectsFromArray:@[_largeDotLayer, _minuteHandLayer, _hourHandLayer, _secondHandLayer, _smallDotLayer]];
    self.sublayers = sublayers;
    
    if (NULL != font) {
      CFRelease(font);
    }
  }
  return self;
}

#pragma mark - Properties

@dynamic clockBackgroundColor;
@dynamic clockForegroundColor;
@dynamic clockAccentColor;

- (void)setStyle:(NSDictionary *)style
{
  super.style = style;
  [self _updatedStyle];
}

- (void)setBounds:(CGRect)bounds
{
  if (!CGRectEqualToRect(bounds, self.bounds)) {
    _radius = MIN(CGRectGetWidth(bounds), CGRectGetHeight(bounds)) / 2.;
    _needsFullLayout = YES;
    super.bounds = bounds;
  }
}

- (void)setDate:(NSDate *)date
{
  if (_date != date && ![_date isEqualToDate:date]) {
    _date = date;
    [self setNeedsLayout];
  }
}

#pragma mark - Utilities

- (void)_updatedStyle
{
  CGColorRef backgroundColor = self.clockBackgroundColor.CGColor;
  CGColorRef foregroundColor = self.clockForegroundColor.CGColor;
  CGColorRef accentColor = self.clockAccentColor.CGColor;
  
  _faceLayer.fillColor = backgroundColor;
  _largeDotLayer.fillColor = foregroundColor;
  _smallDotLayer.fillColor = accentColor;

  [_numberLayers enumerateObjectsUsingBlock:^(CATextLayer *numberLayer, NSUInteger idx, BOOL *stop) {
    numberLayer.foregroundColor = foregroundColor;
  }];
  
  _hourHandLayer.backgroundColor = foregroundColor;
  _minuteHandLayer.backgroundColor = foregroundColor;
  _secondHandLayer.backgroundColor = accentColor;
}

- (void)_rotateHandLayers
{
  NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit fromDate:_date];
  NSInteger minutesIntoDay = dateComponents.hour * 60 + dateComponents.minute;
  CGFloat percentMinutesIntoDay = (CGFloat)minutesIntoDay / (12.0 * 60.0);
  CGFloat percentMinutesIntoHour = (CGFloat)dateComponents.minute / 60.0;
  CGFloat percentSecondsIntoMinute = (CGFloat)dateComponents.second / 60.0;
  
  // XXX set fixed time
  //  percentMinutesIntoDay = (10 * 60 + 12) / (12 * 60.);
  //  percentMinutesIntoHour = 12.0 / 60.0;
  //  percentSecondsIntoMinute = 47.0 / 60.0;
  
  _secondHandLayer.transform = CATransform3DMakeRotation(M_PI * 2 * percentSecondsIntoMinute, 0, 0, 1);
  _hourHandLayer.transform = CATransform3DMakeRotation(M_PI * 2 * percentMinutesIntoDay, 0, 0, 1);
  _minuteHandLayer.transform = CATransform3DMakeRotation(M_PI * 2 * percentMinutesIntoHour, 0, 0, 1);
}

- (void)_layoutElipseLayers
{
  CGRect bounds = self.bounds;
  CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
  
  _faceLayer.bounds = bounds;
  _faceLayer.position = center;

  _smallDotLayer.bounds = CGRectMake(0, 0, 3.0, 3.0);
  _smallDotLayer.position = center;
  
  _largeDotLayer.bounds = CGRectMake(0, 0, 9.0, 9.0);
  _largeDotLayer.position = center;
}

- (void)_layoutNumberLayers
{
  // XXX document
  CGRect bounds = self.bounds;
  CGPoint p = CGPointMake(0, _radius - 14);
  CGFloat tickAngle = 2 * M_PI / NUMBER_LAYER_COUNT;
  
  [_numberLayers enumerateObjectsUsingBlock:^(CALayer *numberLayer, NSUInteger idx, BOOL *stop) {
    CGAffineTransform t = CGAffineTransformMakeRotation(7 * tickAngle + idx * tickAngle);
    CGPoint pp = CGPointApplyAffineTransform(p, t);
    pp.x += bounds.size.width / 2;
    pp.y += bounds.size.height / 2;
    numberLayer.position = pp;
    numberLayer.bounds = CGRectMake(0.0, 0.0, 18.0, 18.0);
  }];
}

- (void)_layoutHandLayers
{
  CGRect bounds = self.bounds;
  CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
  
  _secondHandLayer.bounds = CGRectMake(0, 0, 1.0, SECOND_HAND_LENGTH * _radius);
  _secondHandLayer.anchorPoint = CGPointMake(0.5, 1);
  _secondHandLayer.position = center;
  
  _minuteHandLayer.bounds = CGRectMake(0, 0, 2.0, MINUTE_HAND_LENGTH * _radius);
  _minuteHandLayer.anchorPoint = CGPointMake(0.5, 1);
  _minuteHandLayer.position = center;
  _minuteHandLayer.cornerRadius = 1.5;
  
  _hourHandLayer.bounds = CGRectMake(0, 0, 3.0, HOUR_HAND_LENGTH * _radius);
  _hourHandLayer.anchorPoint = CGPointMake(0.5, 1);
  _hourHandLayer.position = center;
  _hourHandLayer.cornerRadius = 1.5;
  
  [self _rotateHandLayers];
}

#pragma mark - Overides

- (void)layoutSublayers
{
  if (!_needsFullLayout) {
    [self _rotateHandLayers];
  } else {
    [self _layoutElipseLayers];
    [self _layoutNumberLayers];
    [self _layoutHandLayers];
    _needsFullLayout = NO;
  }
}

@end


================================================
FILE: Examples/Clock-iOS/ClockView.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <UIKit/UIKit.h>

@class Clock;

enum
{
  kClockViewStyleLight,
  kClockViewStyleDark,
};
typedef NSUInteger ClockViewStyle;

@interface ClockView : UIView

- (instancetype)initWithClock:(Clock *)clock style:(ClockViewStyle)style;

@end


================================================
FILE: Examples/Clock-iOS/ClockView.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import "ClockView.h"
#import "ClockLayer.h"
#import <FBKVOController/FBKVOController.h>

#define CLOCK_LAYER(VIEW) ((ClockLayer *)VIEW.layer)

static NSDictionary *layer_style(ClockViewStyle viewStyle)
{
  NSDictionary *dict = nil;
  switch (viewStyle) {
    case kClockViewStyleLight:
      dict = [ClockLayer lightStyle];
      break;
    case kClockViewStyleDark:
      dict = [ClockLayer darkStyle];
      break;
    default:
      break;
  }
  return dict;
}

@implementation ClockView
{
  FBKVOController *_KVOController;
}

+ (Class)layerClass
{
  return [ClockLayer class];
}

- (instancetype)initWithClock:(Clock *)clock style:(ClockViewStyle)style
{
  self = [super init];
  if (nil != self) {
    CLOCK_LAYER(self).style = layer_style(style);
    
    // create KVO controller instance
    _KVOController = [FBKVOController controllerWithObserver:self];
    
    // handle clock change, including initial value
    [_KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(ClockView *clockView, Clock *clock, NSDictionary *change) {
      
      // update observer with new value
      CLOCK_LAYER(clockView).date = change[NSKeyValueChangeNewKey];
    }];
  }
  return self;
}

@end


================================================
FILE: Examples/Clock-iOS/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "idiom" : "iphone",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "size" : "60x60",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "29x29",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "40x40",
      "scale" : "2x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "size" : "76x76",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Examples/Clock-iOS/Images.xcassets/LaunchImage.launchimage/Contents.json
================================================
{
  "images" : [
    {
      "orientation" : "portrait",
      "idiom" : "iphone",
      "extent" : "full-screen",
      "minimum-system-version" : "7.0",
      "scale" : "2x"
    },
    {
      "orientation" : "portrait",
      "idiom" : "iphone",
      "subtype" : "retina4",
      "extent" : "full-screen",
      "minimum-system-version" : "7.0",
      "scale" : "2x"
    },
    {
      "orientation" : "portrait",
      "idiom" : "ipad",
      "extent" : "full-screen",
      "minimum-system-version" : "7.0",
      "scale" : "1x"
    },
    {
      "orientation" : "landscape",
      "idiom" : "ipad",
      "extent" : "full-screen",
      "minimum-system-version" : "7.0",
      "scale" : "1x"
    },
    {
      "orientation" : "portrait",
      "idiom" : "ipad",
      "extent" : "full-screen",
      "minimum-system-version" : "7.0",
      "scale" : "2x"
    },
    {
      "orientation" : "landscape",
      "idiom" : "ipad",
      "extent" : "full-screen",
      "minimum-system-version" : "7.0",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: Examples/Clock-iOS/ViewController.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end


================================================
FILE: Examples/Clock-iOS/ViewController.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import "ViewController.h"
#import "Clock.h"
#import "ClockView.h"

#define CLOCK_VIEW_MAX_COUNT 10
#define CLOCK_VIEW_TIME_DELAY 3.0
#define RANDOM_ENABLED 1

@interface ViewController ()

@end

@implementation ViewController
{
  NSMutableArray *_clockViews;
  dispatch_source_t _timer;
}

- (void)dealloc
{
  if (NULL != _timer) {
    dispatch_source_cancel(_timer);
  }
}

- (BOOL)prefersStatusBarHidden
{
  return YES;
}

- (void)_addClockView
{
  if (!_clockViews) {
    _clockViews = [NSMutableArray array];
  }
  
  ClockView *clockView = [[ClockView alloc] initWithClock:[Clock clock] style:arc4random_uniform(kClockViewStyleDark+1)];
  [_clockViews addObject:clockView];
  [self.view addSubview:clockView];

  clockView.bounds = CGRectMake(0, 0, 132, 132);

  CGRect contentBounds = self.view.bounds;
#if RANDOM_ENABLED
  clockView.center = CGPointMake(arc4random_uniform(contentBounds.size.width), arc4random_uniform(contentBounds.size.height));
#else
  clockView.center = CGPointMake(contentBounds.size.width / 2., contentBounds.size.height / 2.);
#endif
}

- (void)_removeClockView
{
  if (0 == _clockViews.count) {
    return;
  }

  [_clockViews[0] removeFromSuperview];
  [_clockViews removeObjectAtIndex:0];
}

- (void)_removeAddClockView
{
  [self _removeClockView];
  [self _addClockView];
}

- (void)_scheduleTimer
{
  dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
  dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, CLOCK_VIEW_TIME_DELAY * NSEC_PER_SEC), CLOCK_VIEW_TIME_DELAY * NSEC_PER_SEC, 1.0);
  
  __weak id weakSelf = self;
  dispatch_source_set_event_handler(timer, ^{
    [weakSelf _removeAddClockView];
  });
  
  _timer = timer;
#if RANDOM_ENABLED
  dispatch_resume(timer);
#endif
}

- (void)viewDidLoad
{
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];

  while (_clockViews.count < CLOCK_VIEW_MAX_COUNT) {
    [self _addClockView];
  }

  [self _scheduleTimer];
}

@end


================================================
FILE: Examples/Clock-iOS/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */



================================================
FILE: Examples/Clock-iOS/main.m
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

int main(int argc, char * argv[])
{
  @autoreleasepool {
      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  }
}


================================================
FILE: Examples/Examples.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		EC45CACE18ADC7CE0063DD11 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CACD18ADC7CE0063DD11 /* Foundation.framework */; };
		EC45CAD018ADC7CE0063DD11 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CACF18ADC7CE0063DD11 /* CoreGraphics.framework */; };
		EC45CAD218ADC7CE0063DD11 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CAD118ADC7CE0063DD11 /* UIKit.framework */; };
		EC45CAD818ADC7CE0063DD11 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC45CAD618ADC7CE0063DD11 /* InfoPlist.strings */; };
		EC45CADA18ADC7CE0063DD11 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CAD918ADC7CE0063DD11 /* main.m */; };
		EC45CADE18ADC7CE0063DD11 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CADD18ADC7CE0063DD11 /* AppDelegate.m */; };
		EC45CAE118ADC7CE0063DD11 /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC45CADF18ADC7CE0063DD11 /* Main_iPhone.storyboard */; };
		EC45CAE418ADC7CE0063DD11 /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC45CAE218ADC7CE0063DD11 /* Main_iPad.storyboard */; };
		EC45CAE718ADC7CE0063DD11 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CAE618ADC7CE0063DD11 /* ViewController.m */; };
		EC45CAE918ADC7CE0063DD11 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC45CAE818ADC7CE0063DD11 /* Images.xcassets */; };
		EC45CB0418ADC7E80063DD11 /* libFBKVOController.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CB0318ADC7E80063DD11 /* libFBKVOController.a */; };
		EC45CB7718ADD0B80063DD11 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC45CB0A18ADC8570063DD11 /* Cocoa.framework */; };
		EC45CB7D18ADD0B80063DD11 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC45CB7B18ADD0B80063DD11 /* InfoPlist.strings */; };
		EC45CB7F18ADD0B80063DD11 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CB7E18ADD0B80063DD11 /* main.m */; };
		EC45CB8318ADD0B80063DD11 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = EC45CB8118ADD0B80063DD11 /* Credits.rtf */; };
		EC45CB8618ADD0B80063DD11 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CB8518ADD0B80063DD11 /* AppDelegate.m */; };
		EC45CB8918ADD0B80063DD11 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC45CB8718ADD0B80063DD11 /* MainMenu.xib */; };
		EC45CB8B18ADD0B80063DD11 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC45CB8A18ADD0B80063DD11 /* Images.xcassets */; };
		EC45CBA518ADD0F60063DD11 /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CBA418ADD0F60063DD11 /* FBKVOController.m */; };
		EC45CBA918ADD1A00063DD11 /* Clock.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CBA818ADD1A00063DD11 /* Clock.m */; };
		EC45CBAA18ADD6BB0063DD11 /* Clock.m in Sources */ = {isa = PBXBuildFile; fileRef = EC45CBA818ADD1A00063DD11 /* Clock.m */; };
		ECC5760818ADDE4E00C2BFB8 /* ClockView.m in Sources */ = {isa = PBXBuildFile; fileRef = ECC5760718ADDE4E00C2BFB8 /* ClockView.m */; };
		ECC5761818ADF2F100C2BFB8 /* ClockView.m in Sources */ = {isa = PBXBuildFile; fileRef = ECC5761718ADF2F100C2BFB8 /* ClockView.m */; };
		ECC5761B18ADF76500C2BFB8 /* ClockLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = ECC5761A18ADF76500C2BFB8 /* ClockLayer.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		EC45CACA18ADC7CE0063DD11 /* Clock-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Clock-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
		EC45CACD18ADC7CE0063DD11 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
		EC45CACF18ADC7CE0063DD11 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
		EC45CAD118ADC7CE0063DD11 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
		EC45CAD518ADC7CE0063DD11 /* Clock-iOS-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Clock-iOS-Info.plist"; sourceTree = "<group>"; };
		EC45CAD718ADC7CE0063DD11 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
		EC45CAD918ADC7CE0063DD11 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		EC45CADB18ADC7CE0063DD11 /* Clock-iOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Clock-iOS-Prefix.pch"; sourceTree = "<group>"; };
		EC45CADC18ADC7CE0063DD11 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		EC45CADD18ADC7CE0063DD11 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		EC45CAE018ADC7CE0063DD11 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPhone.storyboard; sourceTree = "<group>"; };
		EC45CAE318ADC7CE0063DD11 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPad.storyboard; sourceTree = "<group>"; };
		EC45CAE518ADC7CE0063DD11 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
		EC45CAE618ADC7CE0063DD11 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
		EC45CAE818ADC7CE0063DD11 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
		EC45CAEF18ADC7CE0063DD11 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
		EC45CB0318ADC7E80063DD11 /* libFBKVOController.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libFBKVOController.a; path = "../../../Library/Developer/Xcode/DerivedData/FBKVOController-amnevtoymcgzwwazjmzbwvbeduoi/Build/Products/Debug-iphoneos/libFBKVOController.a"; sourceTree = "<group>"; };
		EC45CB0A18ADC8570063DD11 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
		EC45CB0D18ADC8570063DD11 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
		EC45CB0E18ADC8570063DD11 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
		EC45CB0F18ADC8570063DD11 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
		EC45CB7618ADD0B80063DD11 /* Clock-OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Clock-OSX.app"; sourceTree = BUILT_PRODUCTS_DIR; };
		EC45CB7A18ADD0B80063DD11 /* Clock-OSX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Clock-OSX-Info.plist"; sourceTree = "<group>"; };
		EC45CB7C18ADD0B80063DD11 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
		EC45CB7E18ADD0B80063DD11 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
		EC45CB8018ADD0B80063DD11 /* Clock-OSX-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Clock-OSX-Prefix.pch"; sourceTree = "<group>"; };
		EC45CB8218ADD0B80063DD11 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = "<group>"; };
		EC45CB8418ADD0B80063DD11 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
		EC45CB8518ADD0B80063DD11 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
		EC45CB8818ADD0B80063DD11 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
		EC45CB8A18ADD0B80063DD11 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
		EC45CBA318ADD0F60063DD11 /* FBKVOController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBKVOController.h; path = ../../FBKVOController/FBKVOController.h; sourceTree = "<group>"; };
		EC45CBA418ADD0F60063DD11 /* FBKVOController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FBKVOController.m; path = ../../FBKVOController/FBKVOController.m; sourceTree = "<group>"; };
		EC45CBA718ADD1A00063DD11 /* Clock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Clock.h; path = "Clock-iOS/Clock.h"; sourceTree = "<group>"; };
		EC45CBA818ADD1A00063DD11 /* Clock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Clock.m; path = "Clock-iOS/Clock.m"; sourceTree = "<group>"; };
		ECC5760618ADDE4E00C2BFB8 /* ClockView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClockView.h; sourceTree = "<group>"; };
		ECC5760718ADDE4E00C2BFB8 /* ClockView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClockView.m; sourceTree = "<group>"; };
		ECC5761618ADF2F100C2BFB8 /* ClockView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClockView.h; sourceTree = "<group>"; };
		ECC5761718ADF2F100C2BFB8 /* ClockView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClockView.m; sourceTree = "<group>"; };
		ECC5761918ADF76500C2BFB8 /* ClockLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClockLayer.h; sourceTree = "<group>"; };
		ECC5761A18ADF76500C2BFB8 /* ClockLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClockLayer.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		EC45CAC718ADC7CE0063DD11 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				EC45CB0418ADC7E80063DD11 /* libFBKVOController.a in Frameworks */,
				EC45CAD018ADC7CE0063DD11 /* CoreGraphics.framework in Frameworks */,
				EC45CAD218ADC7CE0063DD11 /* UIKit.framework in Frameworks */,
				EC45CACE18ADC7CE0063DD11 /* Foundation.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		EC45CB7318ADD0B80063DD11 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				EC45CB7718ADD0B80063DD11 /* Cocoa.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		EC45CABF18ADC7920063DD11 = {
			isa = PBXGroup;
			children = (
				ECC5761518ADEDFC00C2BFB8 /* Clock */,
				EC45CACC18ADC7CE0063DD11 /* Frameworks */,
				EC45CACB18ADC7CE0063DD11 /* Products */,
			);
			sourceTree = "<group>";
		};
		EC45CACB18ADC7CE0063DD11 /* Products */ = {
			isa = PBXGroup;
			children = (
				EC45CACA18ADC7CE0063DD11 /* Clock-iOS.app */,
				EC45CB7618ADD0B80063DD11 /* Clock-OSX.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		EC45CACC18ADC7CE0063DD11 /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				EC45CB0318ADC7E80063DD11 /* libFBKVOController.a */,
				EC45CACD18ADC7CE0063DD11 /* Foundation.framework */,
				EC45CACF18ADC7CE0063DD11 /* CoreGraphics.framework */,
				EC45CAD118ADC7CE0063DD11 /* UIKit.framework */,
				EC45CAEF18ADC7CE0063DD11 /* XCTest.framework */,
				EC45CB0A18ADC8570063DD11 /* Cocoa.framework */,
				EC45CB0C18ADC8570063DD11 /* Other Frameworks */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
		EC45CAD318ADC7CE0063DD11 /* Clock-iOS */ = {
			isa = PBXGroup;
			children = (
				EC45CADC18ADC7CE0063DD11 /* AppDelegate.h */,
				EC45CADD18ADC7CE0063DD11 /* AppDelegate.m */,
				EC45CADF18ADC7CE0063DD11 /* Main_iPhone.storyboard */,
				EC45CAE218ADC7CE0063DD11 /* Main_iPad.storyboard */,
				EC45CAE518ADC7CE0063DD11 /* ViewController.h */,
				EC45CAE618ADC7CE0063DD11 /* ViewController.m */,
				ECC5761618ADF2F100C2BFB8 /* ClockView.h */,
				ECC5761718ADF2F100C2BFB8 /* ClockView.m */,
				ECC5761918ADF76500C2BFB8 /* ClockLayer.h */,
				ECC5761A18ADF76500C2BFB8 /* ClockLayer.m */,
				EC45CAE818ADC7CE0063DD11 /* Images.xcassets */,
				EC45CAD418ADC7CE0063DD11 /* Supporting Files */,
			);
			path = "Clock-iOS";
			sourceTree = "<group>";
		};
		EC45CAD418ADC7CE0063DD11 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				EC45CAD518ADC7CE0063DD11 /* Clock-iOS-Info.plist */,
				EC45CAD618ADC7CE0063DD11 /* InfoPlist.strings */,
				EC45CAD918ADC7CE0063DD11 /* main.m */,
				EC45CADB18ADC7CE0063DD11 /* Clock-iOS-Prefix.pch */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		EC45CB0C18ADC8570063DD11 /* Other Frameworks */ = {
			isa = PBXGroup;
			children = (
				EC45CB0D18ADC8570063DD11 /* AppKit.framework */,
				EC45CB0E18ADC8570063DD11 /* CoreData.framework */,
				EC45CB0F18ADC8570063DD11 /* Foundation.framework */,
			);
			name = "Other Frameworks";
			sourceTree = "<group>";
		};
		EC45CB7818ADD0B80063DD11 /* Clock-OSX */ = {
			isa = PBXGroup;
			children = (
				EC45CB8418ADD0B80063DD11 /* AppDelegate.h */,
				EC45CB8518ADD0B80063DD11 /* AppDelegate.m */,
				ECC5760618ADDE4E00C2BFB8 /* ClockView.h */,
				ECC5760718ADDE4E00C2BFB8 /* ClockView.m */,
				EC45CBA318ADD0F60063DD11 /* FBKVOController.h */,
				EC45CBA418ADD0F60063DD11 /* FBKVOController.m */,
				EC45CB8718ADD0B80063DD11 /* MainMenu.xib */,
				EC45CB8A18ADD0B80063DD11 /* Images.xcassets */,
				EC45CB7918ADD0B80063DD11 /* Supporting Files */,
			);
			path = "Clock-OSX";
			sourceTree = "<group>";
		};
		EC45CB7918ADD0B80063DD11 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				EC45CB7A18ADD0B80063DD11 /* Clock-OSX-Info.plist */,
				EC45CB7B18ADD0B80063DD11 /* InfoPlist.strings */,
				EC45CB7E18ADD0B80063DD11 /* main.m */,
				EC45CB8018ADD0B80063DD11 /* Clock-OSX-Prefix.pch */,
				EC45CB8118ADD0B80063DD11 /* Credits.rtf */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		ECC5761518ADEDFC00C2BFB8 /* Clock */ = {
			isa = PBXGroup;
			children = (
				EC45CBA718ADD1A00063DD11 /* Clock.h */,
				EC45CBA818ADD1A00063DD11 /* Clock.m */,
				EC45CAD318ADC7CE0063DD11 /* Clock-iOS */,
				EC45CB7818ADD0B80063DD11 /* Clock-OSX */,
			);
			name = Clock;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		EC45CAC918ADC7CE0063DD11 /* Clock-iOS */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = EC45CAFD18ADC7CE0063DD11 /* Build configuration list for PBXNativeTarget "Clock-iOS" */;
			buildPhases = (
				EC45CAC618ADC7CE0063DD11 /* Sources */,
				EC45CAC718ADC7CE0063DD11 /* Frameworks */,
				EC45CAC818ADC7CE0063DD11 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "Clock-iOS";
			productName = "Clock-iOS";
			productReference = EC45CACA18ADC7CE0063DD11 /* Clock-iOS.app */;
			productType = "com.apple.product-type.application";
		};
		EC45CB7518ADD0B80063DD11 /* Clock-OSX */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = EC45CB9D18ADD0B80063DD11 /* Build configuration list for PBXNativeTarget "Clock-OSX" */;
			buildPhases = (
				EC45CB7218ADD0B80063DD11 /* Sources */,
				EC45CB7318ADD0B80063DD11 /* Frameworks */,
				EC45CB7418ADD0B80063DD11 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "Clock-OSX";
			productName = "Clock-OSX";
			productReference = EC45CB7618ADD0B80063DD11 /* Clock-OSX.app */;
			productType = "com.apple.product-type.application";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		EC45CAC018ADC7920063DD11 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0730;
			};
			buildConfigurationList = EC45CAC318ADC7920063DD11 /* Build configuration list for PBXProject "Examples" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
				Base,
			);
			mainGroup = EC45CABF18ADC7920063DD11;
			productRefGroup = EC45CACB18ADC7CE0063DD11 /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				EC45CAC918ADC7CE0063DD11 /* Clock-iOS */,
				EC45CB7518ADD0B80063DD11 /* Clock-OSX */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		EC45CAC818ADC7CE0063DD11 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				EC45CAE418ADC7CE0063DD11 /* Main_iPad.storyboard in Resources */,
				EC45CAE918ADC7CE0063DD11 /* Images.xcassets in Resources */,
				EC45CAE118ADC7CE0063DD11 /* Main_iPhone.storyboard in Resources */,
				EC45CAD818ADC7CE0063DD11 /* InfoPlist.strings in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		EC45CB7418ADD0B80063DD11 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				EC45CB7D18ADD0B80063DD11 /* InfoPlist.strings in Resources */,
				EC45CB8B18ADD0B80063DD11 /* Images.xcassets in Resources */,
				EC45CB8318ADD0B80063DD11 /* Credits.rtf in Resources */,
				EC45CB8918ADD0B80063DD11 /* MainMenu.xib in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		EC45CAC618ADC7CE0063DD11 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				ECC5761B18ADF76500C2BFB8 /* ClockLayer.m in Sources */,
				EC45CAE718ADC7CE0063DD11 /* ViewController.m in Sources */,
				ECC5761818ADF2F100C2BFB8 /* ClockView.m in Sources */,
				EC45CADE18ADC7CE0063DD11 /* AppDelegate.m in Sources */,
				EC45CBA918ADD1A00063DD11 /* Clock.m in Sources */,
				EC45CADA18ADC7CE0063DD11 /* main.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		EC45CB7218ADD0B80063DD11 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				EC45CB8618ADD0B80063DD11 /* AppDelegate.m in Sources */,
				ECC5760818ADDE4E00C2BFB8 /* ClockView.m in Sources */,
				EC45CBA518ADD0F60063DD11 /* FBKVOController.m in Sources */,
				EC45CBAA18ADD6BB0063DD11 /* Clock.m in Sources */,
				EC45CB7F18ADD0B80063DD11 /* main.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXVariantGroup section */
		EC45CAD618ADC7CE0063DD11 /* InfoPlist.strings */ = {
			isa = PBXVariantGroup;
			children = (
				EC45CAD718ADC7CE0063DD11 /* en */,
			);
			name = InfoPlist.strings;
			sourceTree = "<group>";
		};
		EC45CADF18ADC7CE0063DD11 /* Main_iPhone.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				EC45CAE018ADC7CE0063DD11 /* Base */,
			);
			name = Main_iPhone.storyboard;
			sourceTree = "<group>";
		};
		EC45CAE218ADC7CE0063DD11 /* Main_iPad.storyboard */ = {
			isa = PBXVariantGroup;
			children = (
				EC45CAE318ADC7CE0063DD11 /* Base */,
			);
			name = Main_iPad.storyboard;
			sourceTree = "<group>";
		};
		EC45CB7B18ADD0B80063DD11 /* InfoPlist.strings */ = {
			isa = PBXVariantGroup;
			children = (
				EC45CB7C18ADD0B80063DD11 /* en */,
			);
			name = InfoPlist.strings;
			sourceTree = "<group>";
		};
		EC45CB8118ADD0B80063DD11 /* Credits.rtf */ = {
			isa = PBXVariantGroup;
			children = (
				EC45CB8218ADD0B80063DD11 /* en */,
			);
			name = Credits.rtf;
			sourceTree = "<group>";
		};
		EC45CB8718ADD0B80063DD11 /* MainMenu.xib */ = {
			isa = PBXVariantGroup;
			children = (
				EC45CB8818ADD0B80063DD11 /* Base */,
			);
			name = MainMenu.xib;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		EC45CAC418ADC7920063DD11 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ENABLE_TESTABILITY = YES;
				ONLY_ACTIVE_ARCH = YES;
			};
			name = Debug;
		};
		EC45CAC518ADC7920063DD11 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
			};
			name = Release;
		};
		EC45CAFE18ADC7CE0063DD11 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				FRAMEWORK_SEARCH_PATHS = (
					"$(inherited)",
					"$(DEVELOPER_FRAMEWORKS_DIR)",
				);
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "Clock-iOS/Clock-iOS-Prefix.pch";
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				INFOPLIST_FILE = "Clock-iOS/Clock-iOS-Info.plist";
				IPHONEOS_DEPLOYMENT_TARGET = 7.0;
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(BUILT_PRODUCTS_DIR)",
				);
				ONLY_ACTIVE_ARCH = YES;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
				WRAPPER_EXTENSION = app;
			};
			name = Debug;
		};
		EC45CAFF18ADC7CE0063DD11 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = YES;
				ENABLE_NS_ASSERTIONS = NO;
				FRAMEWORK_SEARCH_PATHS = (
					"$(inherited)",
					"$(DEVELOPER_FRAMEWORKS_DIR)",
				);
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "Clock-iOS/Clock-iOS-Prefix.pch";
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				INFOPLIST_FILE = "Clock-iOS/Clock-iOS-Info.plist";
				IPHONEOS_DEPLOYMENT_TARGET = 7.0;
				LIBRARY_SEARCH_PATHS = (
					"$(inherited)",
					"$(BUILT_PRODUCTS_DIR)",
				);
				PRODUCT_NAME = "$(TARGET_NAME)";
				SDKROOT = iphoneos;
				TARGETED_DEVICE_FAMILY = "1,2";
				VALIDATE_PRODUCT = YES;
				WRAPPER_EXTENSION = app;
			};
			name = Release;
		};
		EC45CB9E18ADD0B80063DD11 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COMBINE_HIDPI_IMAGES = YES;
				COPY_PHASE_STRIP = NO;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "Clock-OSX/Clock-OSX-Prefix.pch";
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				INFOPLIST_FILE = "Clock-OSX/Clock-OSX-Info.plist";
				MACOSX_DEPLOYMENT_TARGET = 10.9;
				ONLY_ACTIVE_ARCH = YES;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SDKROOT = macosx;
				WRAPPER_EXTENSION = app;
			};
			name = Debug;
		};
		EC45CB9F18ADD0B80063DD11 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COMBINE_HIDPI_IMAGES = YES;
				COPY_PHASE_STRIP = YES;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "Clock-OSX/Clock-OSX-Prefix.pch";
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				INFOPLIST_FILE = "Clock-OSX/Clock-OSX-Info.plist";
				MACOSX_DEPLOYMENT_TARGET = 10.9;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SDKROOT = macosx;
				WRAPPER_EXTENSION = app;
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		EC45CAC318ADC7920063DD11 /* Build configuration list for PBXProject "Examples" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				EC45CAC418ADC7920063DD11 /* Debug */,
				EC45CAC518ADC7920063DD11 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		EC45CAFD18ADC7CE0063DD11 /* Build configuration list for PBXNativeTarget "Clock-iOS" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				EC45CAFE18ADC7CE0063DD11 /* Debug */,
				EC45CAFF18ADC7CE0063DD11 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		EC45CB9D18ADD0B80063DD11 /* Build configuration list for PBXNativeTarget "Clock-OSX" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				EC45CB9E18ADD0B80063DD11 /* Debug */,
				EC45CB9F18ADD0B80063DD11 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = EC45CAC018ADC7920063DD11 /* Project object */;
}


================================================
FILE: FBKVOController/FBKVOController.h
================================================
/**
 Copyright (c) 2014-present, Facebook, Inc.
 All rights reserved.

 This source code is licensed under the BSD-style license found in the
 LICENSE file in the root directory of this source tree. An additional grant
 of patent rights can be found in the PATENTS file in the same directory.
 */

#import <Foundation/Foundation.h>

/**
 This macro ensures that key path exists at compile time.
 Given a real receiver with a key path as you would call it, it verifies at compile time that the key path exists, without calling it.

 For example:

 FBKVOKeyPath(string.length) => @"length"

 Or even the complex case:

 FBKVOKeyPath(string.lowercaseString.length) => @"lowercaseString.length".
 */
#define FBKVOKeyPath(KEYPATH) \
@(((void)(NO && ((void)KEYPATH, NO)), \
({ const char *fbkvokeypath = strchr(#KEYPATH, '.'); NSCAssert(fbkvokeypath, @"Provided key path is invalid."); fbkvokeypath + 1; })))

/**
 This macro ensures that key path exists at compile time.
 Given a receiver type and a key path, it verifies at compile time that the key path exists, without calling it.

 For example:

 FBKVOClassKeyPath(NSString, length) => @"length"
 FBKVOClassKeyPath(NSString, lowercaseString.length) => @"lowercaseString.length"
 */
#define FBKVOClassKeyPath(CLASS, KEYPATH) \
@(((void)(NO && ((void)((CLASS *)(nil)).KEYPATH, NO)), #KEYPATH))

NS_ASSUME_NONNULL_BEGIN

/**
 Key provided in the @c change dictionary of @c FBKVONotificationBlock that's value represents the key-path being observed
 */
extern NSString *const FBKVONotificationKeyPathKey;

/**
 @abstract Block called on key-value change notification.
 @param observer The observer of the change.
 @param object The object changed.
 @param change The change dictionary which also includes @c FBKVONotificationKeyPathKey
 */
typedef void (^FBKVONotificationBlock)(id _Nullable observer, id object, NSDictionary<NSKeyValueChangeKey, id> *change);

/**
 @abstract FBKVOController makes Key-Value Observing simpler and safer.
 @discussion FBKVOController adds support for handling key-value changes with blocks and custom actions, as well as the NSKeyValueObserving callback. Notification will never message a deallocated observer. Observer removal never throws exceptions, and observers are removed implicitly on controller deallocation. FBKVOController is also thread safe. When used in a concurrent environment, it protects observers from possible resurrection and avoids ensuing crash. By default, the controller maintains a strong reference to objects observed.
 */
@interface FBKVOController : NSObject

///--------------------------------------
#pragma mark - Initialize
///--------------------------------------

/**
 @abstract Creates and returns an initialized KVO controller instance.
 @param observer The object notified on key-value change.
 @return The initialized KVO controller instance.
 */
+ (instancetype)controllerWithObserver:(nullable id)observer;

/**
 @abstract The designated initializer.
 @param observer The object notified on key-value change. The specified observer must support weak references.
 @param retainObserved Flag indicating whether observed objects should be retained.
 @return The initialized KVO controller instance.
 @discussion Use retainObserved = NO when a strong reference between controller and observee would create a retain loop. When not retaining observees, special care must be taken to remove observation info prior to observee dealloc.
 */
- (instancetype)initWithObserver:(nullable id)observer retainObserved:(BOOL)retainObserved NS_DESIGNATED_INITIALIZER;

/**
 @abstract Convenience initializer.
 @param observer The object notified on key-value change. The specified observer must support weak references.
 @return The initialized KVO controller instance.
 @discussion By default, KVO controller retains objects observed.
 */
- (instancetype)initWithObserver:(nullable id)observer;

/**
 @abstract Initializes a new instance.

 @warning This method is unavaialble. Please use `initWithObserver:` instead.
 */
- (instancetype)init NS_UNAVAILABLE;

/**
 @abstract Allocates memory and initializes a new instance into it.

 @warning This method is unavaialble. Please use `controllerWithObserver:` instead.
 */
+ (instancetype)new NS_UNAVAILABLE;

///--------------------------------------
#pragma mark - Observe
///--------------------------------------

/**
 The observer notified on key-value change. Specified on initialization.
 */
@property (nullable, nonatomic, weak, readonly) id observer;

/**
 @abstract Registers observer for key-value change notification.
 @param object The object to observe.
 @param keyPath The key path to observe.
 @param options The NSKeyValueObservingOptions to use for observation.
 @param block The block to execute on notification.
 @discussion On key-value change, the specified block is called. In order to avoid retain loops, the block must avoid referencing the KVO controller or an owner thereof. Observing an already observed object key path or nil results in no operation.
 */
- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block;

/**
 @abstract Registers observer for key-value change notification.
 @param object The object to observe.
 @param keyPath The key path to observe.
 @param options The NSKeyValueObservingOptions to use for observation.
 @param action The observer selector called on key-value change.
 @discussion On key-value change, the observer's action selector is called. The selector provided should take the form of -propertyDidChange, -propertyDidChange: or -propertyDidChange:object:, where optional parameters delivered will be KVO change dictionary and object observed. Observing nil or observing an already observed object's key path results in no operation.
 */
- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action;

/**
 @abstract Registers observer for key-value change notification.
 @param object The object to observe.
 @param keyPath The key path to observe.
 @param options The NSKeyValueObservingOptions to use for observation.
 @param context The context specified.
 @discussion On key-value change, the observer's -observeValueForKeyPath:ofObject:change:context: method is called. Observing an already observed object key path or nil results in no operation.
 */
- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;


/**
 @abstract Registers observer for key-value change notification.
 @param object The object to observe.
 @param keyPaths The key paths to observe.
 @param options The NSKeyValueObservingOptions to use for observation.
 @param block The block to execute on notification.
 @discussion On key-value change, the specified block is called. Inorder to avoid retain loops, the block must avoid referencing the KVO controller or an owner thereof. Observing an already observed object key path or nil results in no operation.
 */
- (void)observe:(nullable id)object keyPaths:(NSArray<NSString *> *)keyPaths options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block;

/**
 @abstract Registers observer for key-value change notification.
 @param object The object to observe.
 @param keyPaths The key paths to observe.
 @param options The NSKeyValueObservingOptions to use for observation.
 @param action The observer selector called on key-value change.
 @discussion On key-value change, the observer's action selector is called. The selector provided should take the form of -propertyDidChange, -propertyDidChange: or -propertyDidChange:object:, where optional parameters delivered will be KVO change dictionary and object observed. Observing nil or observing an already observed object's key path results in no operation.
 */
- (void)observe:(nullable id)object keyPaths:(NSArray<NSString *> *)keyPaths options:(NSKeyValueObservingOptions)options action:(SEL)action;

/**
 @abstract Registers observer for key-value change notification.
 @param object The object to observe.
 @param keyPaths The key paths to observe.
 @param options The NSKeyValueObservingOptions to use for observation.
 @param context The context specified.
 @discussion On key-value change, the observer's -observeValueForKeyPath:ofObject:change:context: method is called. Observing an already observed object key path or nil results in no operation.
 */
- (void)observe:(nullable id)object keyPaths:(NSArray<NSString *> *)keyPaths options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

///--------------------------------------
#pragma mark - Unobserve
///--------------------------------------

/**
 @abstract Unobserve object key path.
 @param object The object to unobserve.
 @param keyPath The key path to observe.
 @discussion If not observing object key path, or unobserving nil, this method results in no operation.
 */
- (void)unobserve:(nullable id)object keyPath:(NSString *)keyPath;

/**
 @abstract Unobserve all object key paths.
 @param object The object to unobserve.
 @discussion If not observing object, or unobserving nil, this method results in no operation.
 */
- (void)unobserve:(nullable id)object;

/**
 @abstract Unobserve all objects.
 @discussion If not observing any objects, this method results in no operation.
 */
- (void)unobserveAll;

@end

NS_ASSUME_NONNULL_END


================================================
FILE: FBKVOController/FBKVOController.m
================================================
/**
 Copyright (c) 2014-present, Facebook, Inc.
 All rights reserved.

 This source code is licensed under the BSD-style license found in the
 LICENSE file in the root directory of this source tree. An additional grant
 of patent rights can be found in the PATENTS file in the same directory.
 */

#import "FBKVOController.h"

#import <objc/message.h>
#import <pthread.h>

#if !__has_feature(objc_arc)
#error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag.
#endif

NS_ASSUME_NONNULL_BEGIN

#pragma mark Utilities -

static NSString *describe_option(NSKeyValueObservingOptions option)
{
  switch (option) {
    case NSKeyValueObservingOptionNew:
      return @"NSKeyValueObservingOptionNew";
      break;
    case NSKeyValueObservingOptionOld:
      return @"NSKeyValueObservingOptionOld";
      break;
    case NSKeyValueObservingOptionInitial:
      return @"NSKeyValueObservingOptionInitial";
      break;
    case NSKeyValueObservingOptionPrior:
      return @"NSKeyValueObservingOptionPrior";
      break;
    default:
      NSCAssert(NO, @"unexpected option %tu", option);
      break;
  }
  return nil;
}

static void append_option_description(NSMutableString *s, NSUInteger option)
{
  if (0 == s.length) {
    [s appendString:describe_option(option)];
  } else {
    [s appendString:@"|"];
    [s appendString:describe_option(option)];
  }
}

static NSUInteger enumerate_flags(NSUInteger *ptrFlags)
{
  NSCAssert(ptrFlags, @"expected ptrFlags");
  if (!ptrFlags) {
    return 0;
  }

  NSUInteger flags = *ptrFlags;
  if (!flags) {
    return 0;
  }

  NSUInteger flag = 1 << __builtin_ctzl(flags);
  flags &= ~flag;
  *ptrFlags = flags;
  return flag;
}

static NSString *describe_options(NSKeyValueObservingOptions options)
{
  NSMutableString *s = [NSMutableString string];
  NSUInteger option;
  while (0 != (option = enumerate_flags(&options))) {
    append_option_description(s, option);
  }
  return s;
}

#pragma mark _FBKVOInfo -

typedef NS_ENUM(uint8_t, _FBKVOInfoState) {
  _FBKVOInfoStateInitial = 0,

  // whether the observer registration in Foundation has completed
  _FBKVOInfoStateObserving,

  // whether `unobserve` was called before observer registration in Foundation has completed
  // this could happen when `NSKeyValueObservingOptionInitial` is one of the NSKeyValueObservingOptions
  _FBKVOInfoStateNotObserving,
};

NSString *const FBKVONotificationKeyPathKey = @"FBKVONotificationKeyPathKey";

/**
 @abstract The key-value observation info.
 @discussion Object equality is only used within the scope of a controller instance. Safely omit controller from equality definition.
 */
@interface _FBKVOInfo : NSObject
@end

@implementation _FBKVOInfo
{
@public
  __weak FBKVOController *_controller;
  NSString *_keyPath;
  NSKeyValueObservingOptions _options;
  SEL _action;
  void *_context;
  FBKVONotificationBlock _block;
  _FBKVOInfoState _state;
}

- (instancetype)initWithController:(FBKVOController *)controller
                           keyPath:(NSString *)keyPath
                           options:(NSKeyValueObservingOptions)options
                             block:(nullable FBKVONotificationBlock)block
                            action:(nullable SEL)action
                           context:(nullable void *)context
{
  self = [super init];
  if (nil != self) {
    _controller = controller;
    _block = [block copy];
    _keyPath = [keyPath copy];
    _options = options;
    _action = action;
    _context = context;
  }
  return self;
}

- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block
{
  return [self initWithController:controller keyPath:keyPath options:options block:block action:NULL context:NULL];
}

- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action
{
  return [self initWithController:controller keyPath:keyPath options:options block:NULL action:action context:NULL];
}

- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
  return [self initWithController:controller keyPath:keyPath options:options block:NULL action:NULL context:context];
}

- (instancetype)initWithController:(FBKVOController *)controller keyPath:(NSString *)keyPath
{
  return [self initWithController:controller keyPath:keyPath options:0 block:NULL action:NULL context:NULL];
}

- (NSUInteger)hash
{
  return [_keyPath hash];
}

- (BOOL)isEqual:(id)object
{
  if (nil == object) {
    return NO;
  }
  if (self == object) {
    return YES;
  }
  if (![object isKindOfClass:[self class]]) {
    return NO;
  }
  return [_keyPath isEqualToString:((_FBKVOInfo *)object)->_keyPath];
}

- (NSString *)debugDescription
{
  NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p keyPath:%@", NSStringFromClass([self class]), self, _keyPath];
  if (0 != _options) {
    [s appendFormat:@" options:%@", describe_options(_options)];
  }
  if (NULL != _action) {
    [s appendFormat:@" action:%@", NSStringFromSelector(_action)];
  }
  if (NULL != _context) {
    [s appendFormat:@" context:%p", _context];
  }
  if (NULL != _block) {
    [s appendFormat:@" block:%p", _block];
  }
  [s appendString:@">"];
  return s;
}

@end

#pragma mark _FBKVOSharedController -

/**
 @abstract The shared KVO controller instance.
 @discussion Acts as a receptionist, receiving and forwarding KVO notifications.
 */
@interface _FBKVOSharedController : NSObject

/** A shared instance that never deallocates. */
+ (instancetype)sharedController;

/** observe an object, info pair */
- (void)observe:(id)object info:(nullable _FBKVOInfo *)info;

/** unobserve an object, info pair */
- (void)unobserve:(id)object info:(nullable _FBKVOInfo *)info;

/** unobserve an object with a set of infos */
- (void)unobserve:(id)object infos:(nullable NSSet *)infos;

@end

@implementation _FBKVOSharedController
{
  NSHashTable<_FBKVOInfo *> *_infos;
  pthread_mutex_t _mutex;
}

+ (instancetype)sharedController
{
  static _FBKVOSharedController *_controller = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _controller = [[_FBKVOSharedController alloc] init];
  });
  return _controller;
}

- (instancetype)init
{
  self = [super init];
  if (nil != self) {
    NSHashTable *infos = [NSHashTable alloc];
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
    _infos = [infos initWithOptions:NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
    if ([NSHashTable respondsToSelector:@selector(weakObjectsHashTable)]) {
      _infos = [infos initWithOptions:NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];
    } else {
      // silence deprecated warnings
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
      _infos = [infos initWithOptions:NSPointerFunctionsZeroingWeakMemory|NSPointerFunctionsObjectPointerPersonality capacity:0];
#pragma clang diagnostic pop
    }

#endif
    pthread_mutex_init(&_mutex, NULL);
  }
  return self;
}

- (void)dealloc
{
  pthread_mutex_destroy(&_mutex);
}

- (NSString *)debugDescription
{
  NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p", NSStringFromClass([self class]), self];

  // lock
  pthread_mutex_lock(&_mutex);

  NSMutableArray *infoDescriptions = [NSMutableArray arrayWithCapacity:_infos.count];
  for (_FBKVOInfo *info in _infos) {
    [infoDescriptions addObject:info.debugDescription];
  }

  [s appendFormat:@" contexts:%@", infoDescriptions];

  // unlock
  pthread_mutex_unlock(&_mutex);

  [s appendString:@">"];
  return s;
}

- (void)observe:(id)object info:(nullable _FBKVOInfo *)info
{
  if (nil == info) {
    return;
  }

  // register info
  pthread_mutex_lock(&_mutex);
  [_infos addObject:info];
  pthread_mutex_unlock(&_mutex);

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

  if (info->_state == _FBKVOInfoStateInitial) {
    info->_state = _FBKVOInfoStateObserving;
  } else if (info->_state == _FBKVOInfoStateNotObserving) {
    // this could happen when `NSKeyValueObservingOptionInitial` is one of the NSKeyValueObservingOptions,
    // and the observer is unregistered within the callback block.
    // at this time the object has been registered as an observer (in Foundation KVO),
    // so we can safely unobserve it.
    [object removeObserver:self forKeyPath:info->_keyPath context:(void *)info];
  }
}

- (void)unobserve:(id)object info:(nullable _FBKVOInfo *)info
{
  if (nil == info) {
    return;
  }

  // unregister info
  pthread_mutex_lock(&_mutex);
  [_infos removeObject:info];
  pthread_mutex_unlock(&_mutex);

  // remove observer
  if (info->_state == _FBKVOInfoStateObserving) {
    [object removeObserver:self forKeyPath:info->_keyPath context:(void *)info];
  }
  info->_state = _FBKVOInfoStateNotObserving;
}

- (void)unobserve:(id)object infos:(nullable NSSet<_FBKVOInfo *> *)infos
{
  if (0 == infos.count) {
    return;
  }

  // unregister info
  pthread_mutex_lock(&_mutex);
  for (_FBKVOInfo *info in infos) {
    [_infos removeObject:info];
  }
  pthread_mutex_unlock(&_mutex);

  // remove observer
  for (_FBKVOInfo *info in infos) {
    if (info->_state == _FBKVOInfoStateObserving) {
      [object removeObserver:self forKeyPath:info->_keyPath context:(void *)info];
    }
    info->_state = _FBKVOInfoStateNotObserving;
  }
}

- (void)observeValueForKeyPath:(nullable NSString *)keyPath
                      ofObject:(nullable id)object
                        change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change
                       context:(nullable void *)context
{
  NSAssert(context, @"missing context keyPath:%@ object:%@ change:%@", keyPath, object, change);

  _FBKVOInfo *info;

  {
    // lookup context in registered infos, taking out a strong reference only if it exists
    pthread_mutex_lock(&_mutex);
    info = [_infos member:(__bridge id)context];
    pthread_mutex_unlock(&_mutex);
  }

  if (nil != info) {

    // take strong reference to controller
    FBKVOController *controller = info->_controller;
    if (nil != controller) {

      // take strong reference to observer
      id observer = controller.observer;
      if (nil != observer) {

        // dispatch custom block or action, fall back to default action
        if (info->_block) {
          NSDictionary<NSKeyValueChangeKey, id> *changeWithKeyPath = change;
          // add the keyPath to the change dictionary for clarity when mulitple keyPaths are being observed
          if (keyPath) {
            NSMutableDictionary<NSString *, id> *mChange = [NSMutableDictionary dictionaryWithObject:keyPath forKey:FBKVONotificationKeyPathKey];
            [mChange addEntriesFromDictionary:change];
            changeWithKeyPath = [mChange copy];
          }
          info->_block(observer, object, changeWithKeyPath);
        } else if (info->_action) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
          [observer performSelector:info->_action withObject:change withObject:object];
#pragma clang diagnostic pop
        } else {
          [observer observeValueForKeyPath:keyPath ofObject:object change:change context:info->_context];
        }
      }
    }
  }
}

@end

#pragma mark FBKVOController -

@implementation FBKVOController
{
  NSMapTable<id, NSMutableSet<_FBKVOInfo *> *> *_objectInfosMap;
  pthread_mutex_t _lock;
}

#pragma mark Lifecycle -

+ (instancetype)controllerWithObserver:(nullable id)observer
{
  return [[self alloc] initWithObserver:observer];
}

- (instancetype)initWithObserver:(nullable id)observer retainObserved:(BOOL)retainObserved
{
  self = [super init];
  if (nil != self) {
    _observer = observer;
    NSPointerFunctionsOptions keyOptions = retainObserved ? NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPointerPersonality : NSPointerFunctionsWeakMemory|NSPointerFunctionsObjectPointerPersonality;
    _objectInfosMap = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPersonality capacity:0];
    pthread_mutex_init(&_lock, NULL);
  }
  return self;
}

- (instancetype)initWithObserver:(nullable id)observer
{
  return [self initWithObserver:observer retainObserved:YES];
}

- (void)dealloc
{
  [self unobserveAll];
  pthread_mutex_destroy(&_lock);
}

#pragma mark Properties -

- (NSString *)debugDescription
{
  NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p", NSStringFromClass([self class]), self];
  [s appendFormat:@" observer:<%@:%p>", NSStringFromClass([_observer class]), _observer];

  // lock
  pthread_mutex_lock(&_lock);

  if (0 != _objectInfosMap.count) {
    [s appendString:@"\n  "];
  }

  for (id object in _objectInfosMap) {
    NSMutableSet *infos = [_objectInfosMap objectForKey:object];
    NSMutableArray *infoDescriptions = [NSMutableArray arrayWithCapacity:infos.count];
    [infos enumerateObjectsUsingBlock:^(_FBKVOInfo *info, BOOL *stop) {
      [infoDescriptions addObject:info.debugDescription];
    }];
    [s appendFormat:@"%@ -> %@", object, infoDescriptions];
  }

  // unlock
  pthread_mutex_unlock(&_lock);

  [s appendString:@">"];
  return s;
}

#pragma mark Utilities -

- (void)_observe:(id)object info:(_FBKVOInfo *)info
{
  // lock
  pthread_mutex_lock(&_lock);

  NSMutableSet *infos = [_objectInfosMap objectForKey:object];

  // check for info existence
  _FBKVOInfo *existingInfo = [infos member:info];
  if (nil != existingInfo) {
    // observation info already exists; do not observe it again

    // unlock and return
    pthread_mutex_unlock(&_lock);
    return;
  }

  // lazilly create set of infos
  if (nil == infos) {
    infos = [NSMutableSet set];
    [_objectInfosMap setObject:infos forKey:object];
  }

  // add info and oberve
  [infos addObject:info];

  // unlock prior to callout
  pthread_mutex_unlock(&_lock);

  [[_FBKVOSharedController sharedController] observe:object info:info];
}

- (void)_unobserve:(id)object info:(_FBKVOInfo *)info
{
  // lock
  pthread_mutex_lock(&_lock);

  // get observation infos
  NSMutableSet *infos = [_objectInfosMap objectForKey:object];

  // lookup registered info instance
  _FBKVOInfo *registeredInfo = [infos member:info];

  if (nil != registeredInfo) {
    [infos removeObject:registeredInfo];

    // remove no longer used infos
    if (0 == infos.count) {
      [_objectInfosMap removeObjectForKey:object];
    }
  }

  // unlock
  pthread_mutex_unlock(&_lock);

  // unobserve
  [[_FBKVOSharedController sharedController] unobserve:object info:registeredInfo];
}

- (void)_unobserve:(id)object
{
  // lock
  pthread_mutex_lock(&_lock);

  NSMutableSet *infos = [_objectInfosMap objectForKey:object];

  // remove infos
  [_objectInfosMap removeObjectForKey:object];

  // unlock
  pthread_mutex_unlock(&_lock);

  // unobserve
  [[_FBKVOSharedController sharedController] unobserve:object infos:infos];
}

- (void)_unobserveAll
{
  // lock
  pthread_mutex_lock(&_lock);

  NSMapTable *objectInfoMaps = [_objectInfosMap copy];

  // clear table and map
  [_objectInfosMap removeAllObjects];

  // unlock
  pthread_mutex_unlock(&_lock);

  _FBKVOSharedController *shareController = [_FBKVOSharedController sharedController];

  for (id object in objectInfoMaps) {
    // unobserve each registered object and infos
    NSSet *infos = [objectInfoMaps objectForKey:object];
    [shareController unobserve:object infos:infos];
  }
}

#pragma mark API -

- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block
{
  NSAssert(0 != keyPath.length && NULL != block, @"missing required parameters observe:%@ keyPath:%@ block:%p", object, keyPath, block);
  if (nil == object || 0 == keyPath.length || NULL == block) {
    return;
  }

  // create info
  _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options block:block];

  // observe object with info
  [self _observe:object info:info];
}


- (void)observe:(nullable id)object keyPaths:(NSArray<NSString *> *)keyPaths options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block
{
  NSAssert(0 != keyPaths.count && NULL != block, @"missing required parameters observe:%@ keyPath:%@ block:%p", object, keyPaths, block);
  if (nil == object || 0 == keyPaths.count || NULL == block) {
    return;
  }

  for (NSString *keyPath in keyPaths) {
    [self observe:object keyPath:keyPath options:options block:block];
  }
}

- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options action:(SEL)action
{
  NSAssert(0 != keyPath.length && NULL != action, @"missing required parameters observe:%@ keyPath:%@ action:%@", object, keyPath, NSStringFromSelector(action));
  NSAssert([_observer respondsToSelector:action], @"%@ does not respond to %@", _observer, NSStringFromSelector(action));
  if (nil == object || 0 == keyPath.length || NULL == action) {
    return;
  }

  // create info
  _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options action:action];

  // observe object with info
  [self _observe:object info:info];
}

- (void)observe:(nullable id)object keyPaths:(NSArray<NSString *> *)keyPaths options:(NSKeyValueObservingOptions)options action:(SEL)action
{
  NSAssert(0 != keyPaths.count && NULL != action, @"missing required parameters observe:%@ keyPath:%@ action:%@", object, keyPaths, NSStringFromSelector(action));
  NSAssert([_observer respondsToSelector:action], @"%@ does not respond to %@", _observer, NSStringFromSelector(action));
  if (nil == object || 0 == keyPaths.count || NULL == action) {
    return;
  }

  for (NSString *keyPath in keyPaths) {
    [self observe:object keyPath:keyPath options:options action:action];
  }
}

- (void)observe:(nullable id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context
{
  NSAssert(0 != keyPath.length, @"missing required parameters observe:%@ keyPath:%@", object, keyPath);
  if (nil == object || 0 == keyPath.length) {
    return;
  }

  // create info
  _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath options:options context:context];

  // observe object with info
  [self _observe:object info:info];
}

- (void)observe:(nullable id)object keyPaths:(NSArray<NSString *> *)keyPaths options:(NSKeyValueObservingOptions)options context:(nullable void *)context
{
  NSAssert(0 != keyPaths.count, @"missing required parameters observe:%@ keyPath:%@", object, keyPaths);
  if (nil == object || 0 == keyPaths.count) {
    return;
  }

  for (NSString *keyPath in keyPaths) {
    [self observe:object keyPath:keyPath options:options context:context];
  }
}

- (void)unobserve:(nullable id)object keyPath:(NSString *)keyPath
{
  // create representative info
  _FBKVOInfo *info = [[_FBKVOInfo alloc] initWithController:self keyPath:keyPath];

  // unobserve object property
  [self _unobserve:object info:info];
}

- (void)unobserve:(nullable id)object
{
  if (nil == object) {
    return;
  }

  [self _unobserve:object];
}

- (void)unobserveAll
{
  [self _unobserveAll];
}

@end

NS_ASSUME_NONNULL_END


================================================
FILE: FBKVOController/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>$(PRODUCT_NAME)</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>1.2.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.2.0</string>
	<key>NSPrincipalClass</key>
	<string></string>
</dict>
</plist>


================================================
FILE: FBKVOController/KVOController.h
================================================
/**
 Copyright (c) 2014-present, Facebook, Inc.
 All rights reserved.

 This source code is licensed under the BSD-style license found in the
 LICENSE file in the root directory of this source tree. An additional grant
 of patent rights can be found in the PATENTS file in the same directory.
 */

#import <KVOController/FBKVOController.h>
#import <KVOController/NSObject+FBKVOController.h>


================================================
FILE: FBKVOController/NSObject+FBKVOController.h
================================================
/**
  Copyright (c) 2014-present, Facebook, Inc.
  All rights reserved.

  This source code is licensed under the BSD-style license found in the
  LICENSE file in the root directory of this source tree. An additional grant
  of patent rights can be found in the PATENTS file in the same directory.
 */

#import <Foundation/Foundation.h>

#import "FBKVOController.h"

NS_ASSUME_NONNULL_BEGIN

/**
 Category that adds built-in `KVOController` and `KVOControllerNonRetaining` on any instance of `NSObject`.

 This makes it convenient to simply create and forget a `FBKVOController`, 
 and when this object gets dealloc'd, so will the associated controller and the observation info.
 */
@interface NSObject (FBKVOController)

/**
 @abstract Lazy-loaded FBKVOController for use with any object
 @return FBKVOController associated with this object, creating one if necessary
 @discussion This makes it convenient to simply create and forget a FBKVOController, and when this object gets dealloc'd, so will the associated controller and the observation info.
 */
@property (nonatomic, strong) FBKVOController *KVOController;

/**
 @abstract Lazy-loaded FBKVOController for use with any object
 @return FBKVOController associated with this object, creating one if necessary
 @discussion This makes it convenient to simply create and forget a FBKVOController.
 Use this version when a strong reference between controller and observed object would create a retain cycle.
 When not retaining observed objects, special care must be taken to remove observation info prior to deallocation of the observed object.
 */
@property (nonatomic, strong) FBKVOController *KVOControllerNonRetaining;

@end

NS_ASSUME_NONNULL_END


================================================
FILE: FBKVOController/NSObject+FBKVOController.m
================================================
/**
 Copyright (c) 2014-present, Facebook, Inc.
 All rights reserved.
 
 This source code is licensed under the BSD-style license found in the
 LICENSE file in the root directory of this source tree. An additional grant
 of patent rights can be found in the PATENTS file in the same directory.
 */

#import "NSObject+FBKVOController.h"

#import <objc/message.h>

#if !__has_feature(objc_arc)
#error This file must be compiled with ARC. Convert your project to ARC or specify the -fobjc-arc flag.
#endif

#pragma mark NSObject Category -

NS_ASSUME_NONNULL_BEGIN

static void *NSObjectKVOControllerKey = &NSObjectKVOControllerKey;
static void *NSObjectKVOControllerNonRetainingKey = &NSObjectKVOControllerNonRetainingKey;

@implementation NSObject (FBKVOController)

- (FBKVOController *)KVOController
{
  id controller = objc_getAssociatedObject(self, NSObjectKVOControllerKey);
  
  // lazily create the KVOController
  if (nil == controller) {
    controller = [FBKVOController controllerWithObserver:self];
    self.KVOController = controller;
  }
  
  return controller;
}

- (void)setKVOController:(FBKVOController *)KVOController
{
  objc_setAssociatedObject(self, NSObjectKVOControllerKey, KVOController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (FBKVOController *)KVOControllerNonRetaining
{
  id controller = objc_getAssociatedObject(self, NSObjectKVOControllerNonRetainingKey);
  
  if (nil == controller) {
    controller = [[FBKVOController alloc] initWithObserver:self retainObserved:NO];
    self.KVOControllerNonRetaining = controller;
  }
  
  return controller;
}

- (void)setKVOControllerNonRetaining:(FBKVOController *)KVOControllerNonRetaining
{
  objc_setAssociatedObject(self, NSObjectKVOControllerNonRetainingKey, KVOControllerNonRetaining, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end


NS_ASSUME_NONNULL_END


================================================
FILE: FBKVOController.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXAggregateTarget section */
		ECEA612C18A4A7360064AFF4 /* Framework */ = {
			isa = PBXAggregateTarget;
			buildConfigurationList = ECEA612D18A4A7360064AFF4 /* Build configuration list for PBXAggregateTarget "Framework" */;
			buildPhases = (
				ECEA613218A4A76E0064AFF4 /* ShellScript */,
			);
			dependencies = (
				ECEA613118A4A73D0064AFF4 /* PBXTargetDependency */,
			);
			name = Framework;
			productName = Framework;
		};
/* End PBXAggregateTarget section */

/* Begin PBXBuildFile section */
		46B05A2E1A076AD70022AB70 /* NSObject+FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 46B05A2D1A076AD70022AB70 /* NSObject+FBKVOController.m */; };
		46B05A301A076CC40022AB70 /* NSObject+FBKVOController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 46B05A2F1A076ADD0022AB70 /* NSObject+FBKVOController.h */; };
		81BD70BD1CA4B57F00FB8E4D /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = ECEA610818A49C620064AFF4 /* FBKVOController.m */; };
		81BD70BE1CA4B57F00FB8E4D /* NSObject+FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 46B05A2D1A076AD70022AB70 /* NSObject+FBKVOController.m */; };
		81BD70C11CA4B57F00FB8E4D /* KVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 81EC40D81CA3623D00BD9226 /* KVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81BD70C21CA4B57F00FB8E4D /* FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = ECEA610618A49C620064AFF4 /* FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81BD70C31CA4B57F00FB8E4D /* NSObject+FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B05A2F1A076ADD0022AB70 /* NSObject+FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81BD70FE1CA607F500FB8E4D /* KVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 81EC40D81CA3623D00BD9226 /* KVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81BD70FF1CA607F500FB8E4D /* NSObject+FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B05A2F1A076ADD0022AB70 /* NSObject+FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81BD71001CA607F500FB8E4D /* NSObject+FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 46B05A2D1A076AD70022AB70 /* NSObject+FBKVOController.m */; };
		81BD71011CA607F500FB8E4D /* FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = ECEA610618A49C620064AFF4 /* FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81BD71021CA607F500FB8E4D /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = ECEA610818A49C620064AFF4 /* FBKVOController.m */; };
		81EC40D01CA3621E00BD9226 /* NSObject+FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B05A2F1A076ADD0022AB70 /* NSObject+FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81EC40D11CA3621E00BD9226 /* NSObject+FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 46B05A2D1A076AD70022AB70 /* NSObject+FBKVOController.m */; };
		81EC40D21CA3621E00BD9226 /* FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = ECEA610618A49C620064AFF4 /* FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81EC40D31CA3621E00BD9226 /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = ECEA610818A49C620064AFF4 /* FBKVOController.m */; };
		81EC40D91CA3623D00BD9226 /* KVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 81EC40D81CA3623D00BD9226 /* KVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81EC410C1CA363FC00BD9226 /* KVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 81EC40D81CA3623D00BD9226 /* KVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81EC41101CA3640600BD9226 /* NSObject+FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B05A2F1A076ADD0022AB70 /* NSObject+FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81EC41111CA3640600BD9226 /* FBKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = ECEA610618A49C620064AFF4 /* FBKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
		81EC41151CA3640B00BD9226 /* NSObject+FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = 46B05A2D1A076AD70022AB70 /* NSObject+FBKVOController.m */; };
		81EC41161CA3640B00BD9226 /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = ECEA610818A49C620064AFF4 /* FBKVOController.m */; };
		EC8BB5AE18A5792D00EB2793 /* FBKVOTesting.m in Sources */ = {isa = PBXBuildFile; fileRef = EC8BB5AD18A5792D00EB2793 /* FBKVOTesting.m */; };
		ECEA610218A49C620064AFF4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEA610118A49C620064AFF4 /* Foundation.framework */; };
		ECEA610718A49C620064AFF4 /* FBKVOController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = ECEA610618A49C620064AFF4 /* FBKVOController.h */; };
		ECEA610918A49C620064AFF4 /* FBKVOController.m in Sources */ = {isa = PBXBuildFile; fileRef = ECEA610818A49C620064AFF4 /* FBKVOController.m */; };
		ECEA611018A49C620064AFF4 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEA610F18A49C620064AFF4 /* XCTest.framework */; };
		ECEA611118A49C620064AFF4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEA610118A49C620064AFF4 /* Foundation.framework */; };
		ECEA611318A49C620064AFF4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEA611218A49C620064AFF4 /* UIKit.framework */; };
		ECEA611618A49C620064AFF4 /* libFBKVOController.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ECEA60FE18A49C620064AFF4 /* libFBKVOController.a */; };
		ECEA611C18A49C620064AFF4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = ECEA611A18A49C620064AFF4 /* InfoPlist.strings */; };
		ECEA611E18A49C620064AFF4 /* FBKVOControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = ECEA611D18A49C620064AFF4 /* FBKVOControllerTests.m */; };
		F2755F5F5CED1DAAAFED68B2 /* libPods-FBKVOControllerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 044A6FECA9893D2B98CA99B7 /* libPods-FBKVOControllerTests.a */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		ECEA611418A49C620064AFF4 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = ECEA60F618A49C620064AFF4 /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = ECEA60FD18A49C620064AFF4;
			remoteInfo = FBKVOController;
		};
		ECEA613018A4A73D0064AFF4 /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = ECEA60F618A49C620064AFF4 /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = ECEA60FD18A49C620064AFF4;
			remoteInfo = FBKVOController;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
		ECEA60FC18A49C620064AFF4 /* CopyFiles */ = {
			isa = PBXCopyFilesBuildPhase;
			buildActionMask = 2147483647;
			dstPath = "$(PRODUCT_NAME)Headers";
			dstSubfolderSpec = 16;
			files = (
				46B05A301A076CC40022AB70 /* NSObject+FBKVOController.h in CopyFiles */,
				ECEA610718A49C620064AFF4 /* FBKVOController.h in CopyFiles */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
		044A6FECA9893D2B98CA99B7 /* libPods-FBKVOControllerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-FBKVOControllerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
		2316F70E2DD4D80B87440A05 /* Pods-FBKVOControllerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FBKVOControllerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FBKVOControllerTests/Pods-FBKVOControllerTests.debug.xcconfig"; sourceTree = "<group>"; };
		3E0BB792112F905E950F2AE4 /* Pods-FBKVOControllerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FBKVOControllerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-FBKVOControllerTests/Pods-FBKVOControllerTests.release.xcconfig"; sourceTree = "<group>"; };
		46B05A2D1A076AD70022AB70 /* NSObject+FBKVOController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+FBKVOController.m"; sourceTree = "<group>"; };
		46B05A2F1A076ADD0022AB70 /* NSObject+FBKVOController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+FBKVOController.h"; sourceTree = "<group>"; };
		81BD70C81CA4B57F00FB8E4D /* KVOController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KVOController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		81BD70EA1CA4B98D00FB8E4D /* KVOController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KVOController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		81EC40C61CA3620A00BD9226 /* KVOController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KVOController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		81EC40D81CA3623D00BD9226 /* KVOController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KVOController.h; sourceTree = "<group>"; };
		81EC40EE1CA3630200BD9226 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
		81EC40F81CA3639C00BD9226 /* KVOController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KVOController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
		EC8BB5AC18A5792D00EB2793 /* FBKVOTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBKVOTesting.h; sourceTree = "<group>"; };
		EC8BB5AD18A5792D00EB2793 /* FBKVOTesting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBKVOTesting.m; sourceTree = "<group>"; };
		EC8BB5B318A5A1EE00EB2793 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
		EC8BB5B418A5A1F500EB2793 /* PATENTS */ = {isa = PBXFileReference; lastKnownFileType = text; path = PATENTS; sourceTree = "<group>"; };
		EC8BB5B518A5A30700EB2793 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = CONTRIBUTING.md; sourceTree = "<group>"; };
		EC8BB5B618A5A30F00EB2793 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = "<group>"; };
		ECAFBD5E18BD47BE009B4EC6 /* KVOController.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = KVOController.podspec; sourceTree = "<group>"; };
		ECEA60FE18A49C620064AFF4 /* libFBKVOController.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFBKVOController.a; sourceTree = BUILT_PRODUCTS_DIR; };
		ECEA610118A49C620064AFF4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
		ECEA610618A49C620064AFF4 /* FBKVOController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBKVOController.h; sourceTree = "<group>"; };
		ECEA610818A49C620064AFF4 /* FBKVOController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBKVOController.m; sourceTree = "<group>"; tabWidth = 4; };
		ECEA610E18A49C620064AFF4 /* FBKVOControllerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FBKVOControllerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
		ECEA610F18A49C620064AFF4 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
		ECEA611218A49C620064AFF4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
		ECEA611918A49C620064AFF4 /* FBKVOControllerTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FBKVOControllerTests-Info.plist"; sourceTree = "<group>"; };
		ECEA611B18A49C620064AFF4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
		ECEA611D18A49C620064AFF4 /* FBKVOControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBKVOControllerTests.m; sourceTree = "<group>"; tabWidth = 4; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		81BD70BF1CA4B57F00FB8E4D /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81BD70E61CA4B98D00FB8E4D /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40C21CA3620A00BD9226 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40F41CA3639C00BD9226 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		ECEA60FB18A49C620064AFF4 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				ECEA610218A49C620064AFF4 /* Foundation.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		ECEA610B18A49C620064AFF4 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				ECEA611018A49C620064AFF4 /* XCTest.framework in Frameworks */,
				ECEA611318A49C620064AFF4 /* UIKit.framework in Frameworks */,
				ECEA611618A49C620064AFF4 /* libFBKVOController.a in Frameworks */,
				ECEA611118A49C620064AFF4 /* Foundation.framework in Frameworks */,
				F2755F5F5CED1DAAAFED68B2 /* libPods-FBKVOControllerTests.a in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		DE977FB840686E597267F657 /* Pods */ = {
			isa = PBXGroup;
			children = (
				2316F70E2DD4D80B87440A05 /* Pods-FBKVOControllerTests.debug.xcconfig */,
				3E0BB792112F905E950F2AE4 /* Pods-FBKVOControllerTests.release.xcconfig */,
			);
			name = Pods;
			sourceTree = "<group>";
		};
		ECEA60F518A49C620064AFF4 = {
			isa = PBXGroup;
			children = (
				EC8BB5B618A5A30F00EB2793 /* README.md */,
				EC8BB5B518A5A30700EB2793 /* CONTRIBUTING.md */,
				EC8BB5B318A5A1EE00EB2793 /* LICENSE */,
				EC8BB5B418A5A1F500EB2793 /* PATENTS */,
				ECAFBD5E18BD47BE009B4EC6 /* KVOController.podspec */,
				ECEA610318A49C620064AFF4 /* FBKVOController */,
				ECEA611718A49C620064AFF4 /* FBKVOControllerTests */,
				ECEA610018A49C620064AFF4 /* Frameworks */,
				ECEA60FF18A49C620064AFF4 /* Products */,
				DE977FB840686E597267F657 /* Pods */,
			);
			indentWidth = 2;
			sourceTree = "<group>";
			tabWidth = 2;
		};
		ECEA60FF18A49C620064AFF4 /* Products */ = {
			isa = PBXGroup;
			children = (
				ECEA60FE18A49C620064AFF4 /* libFBKVOController.a */,
				ECEA610E18A49C620064AFF4 /* FBKVOControllerTests.xctest */,
				81EC40C61CA3620A00BD9226 /* KVOController.framework */,
				81EC40F81CA3639C00BD9226 /* KVOController.framework */,
				81BD70C81CA4B57F00FB8E4D /* KVOController.framework */,
				81BD70EA1CA4B98D00FB8E4D /* KVOController.framework */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		ECEA610018A49C620064AFF4 /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				ECEA610118A49C620064AFF4 /* Foundation.framework */,
				ECEA610F18A49C620064AFF4 /* XCTest.framework */,
				ECEA611218A49C620064AFF4 /* UIKit.framework */,
				044A6FECA9893D2B98CA99B7 /* libPods-FBKVOControllerTests.a */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
		ECEA610318A49C620064AFF4 /* FBKVOController */ = {
			isa = PBXGroup;
			children = (
				81EC40D81CA3623D00BD9226 /* KVOController.h */,
				46B05A2F1A076ADD0022AB70 /* NSObject+FBKVOController.h */,
				46B05A2D1A076AD70022AB70 /* NSObject+FBKVOController.m */,
				ECEA610618A49C620064AFF4 /* FBKVOController.h */,
				ECEA610818A49C620064AFF4 /* FBKVOController.m */,
				ECEA610418A49C620064AFF4 /* Supporting Files */,
			);
			path = FBKVOController;
			sourceTree = "<group>";
		};
		ECEA610418A49C620064AFF4 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				81EC40EE1CA3630200BD9226 /* Info.plist */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		ECEA611718A49C620064AFF4 /* FBKVOControllerTests */ = {
			isa = PBXGroup;
			children = (
				ECEA611D18A49C620064AFF4 /* FBKVOControllerTests.m */,
				EC8BB5AC18A5792D00EB2793 /* FBKVOTesting.h */,
				EC8BB5AD18A5792D00EB2793 /* FBKVOTesting.m */,
				ECEA611818A49C620064AFF4 /* Supporting Files */,
			);
			path = FBKVOControllerTests;
			sourceTree = "<group>";
		};
		ECEA611818A49C620064AFF4 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				ECEA611918A49C620064AFF4 /* FBKVOControllerTests-Info.plist */,
				ECEA611A18A49C620064AFF4 /* InfoPlist.strings */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
		81BD70C01CA4B57F00FB8E4D /* Headers */ = {
			isa = PBXHeadersBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81BD70C11CA4B57F00FB8E4D /* KVOController.h in Headers */,
				81BD70C21CA4B57F00FB8E4D /* FBKVOController.h in Headers */,
				81BD70C31CA4B57F00FB8E4D /* NSObject+FBKVOController.h in Headers */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81BD70E71CA4B98D00FB8E4D /* Headers */ = {
			isa = PBXHeadersBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81BD70FE1CA607F500FB8E4D /* KVOController.h in Headers */,
				81BD71011CA607F500FB8E4D /* FBKVOController.h in Headers */,
				81BD70FF1CA607F500FB8E4D /* NSObject+FBKVOController.h in Headers */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40C31CA3620A00BD9226 /* Headers */ = {
			isa = PBXHeadersBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81EC40D91CA3623D00BD9226 /* KVOController.h in Headers */,
				81EC40D21CA3621E00BD9226 /* FBKVOController.h in Headers */,
				81EC40D01CA3621E00BD9226 /* NSObject+FBKVOController.h in Headers */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40F51CA3639C00BD9226 /* Headers */ = {
			isa = PBXHeadersBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81EC410C1CA363FC00BD9226 /* KVOController.h in Headers */,
				81EC41101CA3640600BD9226 /* NSObject+FBKVOController.h in Headers */,
				81EC41111CA3640600BD9226 /* FBKVOController.h in Headers */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXHeadersBuildPhase section */

/* Begin PBXNativeTarget section */
		81BD70BB1CA4B57F00FB8E4D /* FBKVOController-tvOS-Dynamic */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 81BD70C51CA4B57F00FB8E4D /* Build configuration list for PBXNativeTarget "FBKVOController-tvOS-Dynamic" */;
			buildPhases = (
				81BD70BC1CA4B57F00FB8E4D /* Sources */,
				81BD70BF1CA4B57F00FB8E4D /* Frameworks */,
				81BD70C01CA4B57F00FB8E4D /* Headers */,
				81BD70C41CA4B57F00FB8E4D /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "FBKVOController-tvOS-Dynamic";
			productName = KVOController;
			productReference = 81BD70C81CA4B57F00FB8E4D /* KVOController.framework */;
			productType = "com.apple.product-type.framework";
		};
		81BD70E91CA4B98D00FB8E4D /* FBKVOController-watchOS-Dynamic */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 81BD70EF1CA4B98D00FB8E4D /* Build configuration list for PBXNativeTarget "FBKVOController-watchOS-Dynamic" */;
			buildPhases = (
				81BD70E51CA4B98D00FB8E4D /* Sources */,
				81BD70E61CA4B98D00FB8E4D /* Frameworks */,
				81BD70E71CA4B98D00FB8E4D /* Headers */,
				81BD70E81CA4B98D00FB8E4D /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "FBKVOController-watchOS-Dynamic";
			productName = "FBKVOController-watchOS-Dynamic";
			productReference = 81BD70EA1CA4B98D00FB8E4D /* KVOController.framework */;
			productType = "com.apple.product-type.framework";
		};
		81EC40C51CA3620A00BD9226 /* FBKVOController-iOS-Dynamic */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 81EC40CD1CA3620A00BD9226 /* Build configuration list for PBXNativeTarget "FBKVOController-iOS-Dynamic" */;
			buildPhases = (
				81EC40C11CA3620A00BD9226 /* Sources */,
				81EC40C21CA3620A00BD9226 /* Frameworks */,
				81EC40C31CA3620A00BD9226 /* Headers */,
				81EC40C41CA3620A00BD9226 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "FBKVOController-iOS-Dynamic";
			productName = KVOController;
			productReference = 81EC40C61CA3620A00BD9226 /* KVOController.framework */;
			productType = "com.apple.product-type.framework";
		};
		81EC40F71CA3639C00BD9226 /* FBKVOController-OSX-Dynamic */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = 81EC40FD1CA3639C00BD9226 /* Build configuration list for PBXNativeTarget "FBKVOController-OSX-Dynamic" */;
			buildPhases = (
				81EC40F31CA3639C00BD9226 /* Sources */,
				81EC40F41CA3639C00BD9226 /* Frameworks */,
				81EC40F51CA3639C00BD9226 /* Headers */,
				81EC40F61CA3639C00BD9226 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = "FBKVOController-OSX-Dynamic";
			productName = "KVOController-OSX-Dynamic";
			productReference = 81EC40F81CA3639C00BD9226 /* KVOController.framework */;
			productType = "com.apple.product-type.framework";
		};
		ECEA60FD18A49C620064AFF4 /* FBKVOController */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = ECEA612118A49C620064AFF4 /* Build configuration list for PBXNativeTarget "FBKVOController" */;
			buildPhases = (
				ECEA60FA18A49C620064AFF4 /* Sources */,
				ECEA60FB18A49C620064AFF4 /* Frameworks */,
				ECEA60FC18A49C620064AFF4 /* CopyFiles */,
				ECEA612718A49DDD0064AFF4 /* ShellScript */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = FBKVOController;
			productName = FBKVOController;
			productReference = ECEA60FE18A49C620064AFF4 /* libFBKVOController.a */;
			productType = "com.apple.product-type.library.static";
		};
		ECEA610D18A49C620064AFF4 /* FBKVOControllerTests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = ECEA612418A49C620064AFF4 /* Build configuration list for PBXNativeTarget "FBKVOControllerTests" */;
			buildPhases = (
				BEB3825BB272703E7F8D5FAD /* [CP] Check Pods Manifest.lock */,
				ECEA610A18A49C620064AFF4 /* Sources */,
				ECEA610B18A49C620064AFF4 /* Frameworks */,
				ECEA610C18A49C620064AFF4 /* Resources */,
				EC1E7A550C7FEF37584E8438 /* [CP] Embed Pods Frameworks */,
				4815293B1AA905E7D81CAD3F /* [CP] Copy Pods Resources */,
			);
			buildRules = (
			);
			dependencies = (
				ECEA611518A49C620064AFF4 /* PBXTargetDependency */,
			);
			name = FBKVOControllerTests;
			productName = FBKVOControllerTests;
			productReference = ECEA610E18A49C620064AFF4 /* FBKVOControllerTests.xctest */;
			productType = "com.apple.product-type.bundle.unit-test";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		ECEA60F618A49C620064AFF4 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0820;
				ORGANIZATIONNAME = "Kimon Tsinteris";
				TargetAttributes = {
					81BD70E91CA4B98D00FB8E4D = {
						CreatedOnToolsVersion = 7.3;
					};
					81EC40C51CA3620A00BD9226 = {
						CreatedOnToolsVersion = 7.3;
					};
					81EC40F71CA3639C00BD9226 = {
						CreatedOnToolsVersion = 7.3;
					};
				};
			};
			buildConfigurationList = ECEA60F918A49C620064AFF4 /* Build configuration list for PBXProject "FBKVOController" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
			);
			mainGroup = ECEA60F518A49C620064AFF4;
			productRefGroup = ECEA60FF18A49C620064AFF4 /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				ECEA60FD18A49C620064AFF4 /* FBKVOController */,
				ECEA610D18A49C620064AFF4 /* FBKVOControllerTests */,
				ECEA612C18A4A7360064AFF4 /* Framework */,
				81EC40C51CA3620A00BD9226 /* FBKVOController-iOS-Dynamic */,
				81EC40F71CA3639C00BD9226 /* FBKVOController-OSX-Dynamic */,
				81BD70BB1CA4B57F00FB8E4D /* FBKVOController-tvOS-Dynamic */,
				81BD70E91CA4B98D00FB8E4D /* FBKVOController-watchOS-Dynamic */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		81BD70C41CA4B57F00FB8E4D /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81BD70E81CA4B98D00FB8E4D /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40C41CA3620A00BD9226 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40F61CA3639C00BD9226 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		ECEA610C18A49C620064AFF4 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				ECEA611C18A49C620064AFF4 /* InfoPlist.strings in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
		4815293B1AA905E7D81CAD3F /* [CP] Copy Pods Resources */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Copy Pods Resources";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FBKVOControllerTests/Pods-FBKVOControllerTests-resources.sh\"\n";
			showEnvVarsInLog = 0;
		};
		BEB3825BB272703E7F8D5FAD /* [CP] Check Pods Manifest.lock */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Check Pods Manifest.lock";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
			showEnvVarsInLog = 0;
		};
		EC1E7A550C7FEF37584E8438 /* [CP] Embed Pods Frameworks */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			name = "[CP] Embed Pods Frameworks";
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FBKVOControllerTests/Pods-FBKVOControllerTests-frameworks.sh\"\n";
			showEnvVarsInLog = 0;
		};
		ECEA612718A49DDD0064AFF4 /* ShellScript */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "set -e\n\nmkdir -p \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers\"\n\n# Link the \"Current\" version to \"A\"\n/bin/ln -sfh A \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/Current\"\n/bin/ln -sfh Versions/Current/Headers \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Headers\"\n/bin/ln -sfh \"Versions/Current/${PRODUCT_NAME}\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/${PRODUCT_NAME}\"\n\n# The -a ensures that the headers maintain the source modification date so that we don't constantly\n# cause propagating rebuilds of files that import these headers.\n/bin/cp -a \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Versions/A/Headers\"";
		};
		ECEA613218A4A76E0064AFF4 /* ShellScript */ = {
			isa = PBXShellScriptBuildPhase;
			buildActionMask = 2147483647;
			files = (
			);
			inputPaths = (
			);
			outputPaths = (
			);
			runOnlyForDeploymentPostprocessing = 0;
			shellPath = /bin/sh;
			shellScript = "set -e\nset +u\n# Avoid recursively calling this script.\nif [[ $SF_MASTER_SCRIPT_RUNNING ]]\nthen\nexit 0\nfi\nset -u\nexport SF_MASTER_SCRIPT_RUNNING=1\n\nSF_TARGET_NAME=${PROJECT_NAME}\nSF_EXECUTABLE_PATH=\"lib${SF_TARGET_NAME}.a\"\nSF_WRAPPER_NAME=\"${SF_TARGET_NAME}.framework\"\n\n# The following conditionals come from\n# https://github.com/kstenerud/iOS-Universal-Framework\n\nif [[ \"$SDK_NAME\" =~ ([A-Za-z]+) ]]\nthen\nSF_SDK_PLATFORM=${BASH_REMATCH[1]}\nelse\necho \"Could not find platform name from SDK_NAME: $SDK_NAME\"\nexit 1\nfi\n\nif [[ \"$SDK_NAME\" =~ ([0-9]+.*$) ]]\nthen\nSF_SDK_VERSION=${BASH_REMATCH[1]}\nelse\necho \"Could not find sdk version from SDK_NAME: $SDK_NAME\"\nexit 1\nfi\n\nif [[ \"$SF_SDK_PLATFORM\" = \"iphoneos\" ]]\nthen\nSF_OTHER_PLATFORM=iphonesimulator\nelse\nSF_OTHER_PLATFORM=iphoneos\nfi\n\nif [[ \"$BUILT_PRODUCTS_DIR\" =~ (.*)$SF_SDK_PLATFORM$ ]]\nthen\nSF_OTHER_BUILT_PRODUCTS_DIR=\"${BASH_REMATCH[1]}${SF_OTHER_PLATFORM}\"\nelse\necho \"Could not find platform name from build products directory: $BUILT_PRODUCTS_DIR\"\nexit 1\nfi\n\n# Build the other platform.\nxcodebuild -project \"${PROJECT_FILE_PATH}\" -target \"${TARGET_NAME}\" -configuration \"${CONFIGURATION}\" -sdk ${SF_OTHER_PLATFORM}${SF_SDK_VERSION} BUILD_DIR=\"${BUILD_DIR}\" OBJROOT=\"${OBJROOT}\" BUILD_ROOT=\"${BUILD_ROOT}\" SYMROOT=\"${SYMROOT}\" $ACTION\n\n# Smash the two static libraries into one fat binary and store it in the .framework\nlipo -create \"${BUILT_PRODUCTS_DIR}/${SF_EXECUTABLE_PATH}\" \"${SF_OTHER_BUILT_PRODUCTS_DIR}/${SF_EXECUTABLE_PATH}\" -output \"${BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/${FRAMEWORK_VERSION}/${SF_TARGET_NAME}\"\n\n# Copy the binary to the other architecture folder to have a complete framework in both.\ncp -a \"${BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/${FRAMEWORK_VERSION}/${SF_TARGET_NAME}\" \"${SF_OTHER_BUILT_PRODUCTS_DIR}/${SF_WRAPPER_NAME}/Versions/${FRAMEWORK_VERSION}/${SF_TARGET_NAME}\"\n";
		};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		81BD70BC1CA4B57F00FB8E4D /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81BD70BD1CA4B57F00FB8E4D /* FBKVOController.m in Sources */,
				81BD70BE1CA4B57F00FB8E4D /* NSObject+FBKVOController.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81BD70E51CA4B98D00FB8E4D /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81BD71021CA607F500FB8E4D /* FBKVOController.m in Sources */,
				81BD71001CA607F500FB8E4D /* NSObject+FBKVOController.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40C11CA3620A00BD9226 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81EC40D31CA3621E00BD9226 /* FBKVOController.m in Sources */,
				81EC40D11CA3621E00BD9226 /* NSObject+FBKVOController.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		81EC40F31CA3639C00BD9226 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				81EC41161CA3640B00BD9226 /* FBKVOController.m in Sources */,
				81EC41151CA3640B00BD9226 /* NSObject+FBKVOController.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		ECEA60FA18A49C620064AFF4 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				46B05A2E1A076AD70022AB70 /* NSObject+FBKVOController.m in Sources */,
				ECEA610918A49C620064AFF4 /* FBKVOController.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		ECEA610A18A49C620064AFF4 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				ECEA611E18A49C620064AFF4 /* FBKVOControllerTests.m in Sources */,
				EC8BB5AE18A5792D00EB2793 /* FBKVOTesting.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		ECEA611518A49C620064AFF4 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = ECEA60FD18A49C620064AFF4 /* FBKVOController */;
			targetProxy = ECEA611418A49C620064AFF4 /* PBXContainerItemProxy */;
		};
		ECEA613118A4A73D0064AFF4 /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = ECEA60FD18A49C620064AFF4 /* FBKVOController */;
			targetProxy = ECEA613018A4A73D0064AFF4 /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
		ECEA611A18A49C620064AFF4 /* InfoPlist.strings */ = {
			isa = PBXVariantGroup;
			children = (
				ECEA611B18A49C620064AFF4 /* en */,
			);
			name = InfoPlist.strings;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		81BD70C61CA4B57F00FB8E4D /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = dwarf;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				MTL_ENABLE_DEBUG_INFO = YES;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.tvos;
				PRODUCT_NAME = KVOController;
				SDKROOT = appletvos;
				SKIP_INSTALL = YES;
				TARGETED_DEVICE_FAMILY = 3;
				TVOS_DEPLOYMENT_TARGET = 9.0;
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Debug;
		};
		81BD70C71CA4B57F00FB8E4D /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
				COPY_PHASE_STRIP = NO;
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				MTL_ENABLE_DEBUG_INFO = NO;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.tvos;
				PRODUCT_NAME = KVOController;
				SDKROOT = appletvos;
				SKIP_INSTALL = YES;
				TARGETED_DEVICE_FAMILY = 3;
				TVOS_DEPLOYMENT_TARGET = 9.0;
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Release;
		};
		81BD70F01CA4B98D00FB8E4D /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = dwarf;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				MTL_ENABLE_DEBUG_INFO = YES;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.watchos;
				PRODUCT_NAME = KVOController;
				SDKROOT = watchos;
				SKIP_INSTALL = YES;
				TARGETED_DEVICE_FAMILY = 4;
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
				WATCHOS_DEPLOYMENT_TARGET = 2.0;
			};
			name = Debug;
		};
		81BD70F11CA4B98D00FB8E4D /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
				COPY_PHASE_STRIP = NO;
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				MTL_ENABLE_DEBUG_INFO = NO;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.watchos;
				PRODUCT_NAME = KVOController;
				SDKROOT = watchos;
				SKIP_INSTALL = YES;
				TARGETED_DEVICE_FAMILY = 4;
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
				WATCHOS_DEPLOYMENT_TARGET = 2.0;
			};
			name = Release;
		};
		81EC40CB1CA3620A00BD9226 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = dwarf;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				MTL_ENABLE_DEBUG_INFO = YES;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.ios;
				PRODUCT_NAME = KVOController;
				SKIP_INSTALL = YES;
				TARGETED_DEVICE_FAMILY = "1,2";
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Debug;
		};
		81EC40CC1CA3620A00BD9226 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
				COPY_PHASE_STRIP = NO;
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
				MTL_ENABLE_DEBUG_INFO = NO;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.ios;
				PRODUCT_NAME = KVOController;
				SKIP_INSTALL = YES;
				TARGETED_DEVICE_FAMILY = "1,2";
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Release;
		};
		81EC40FE1CA3639C00BD9226 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CODE_SIGN_IDENTITY = "-";
				COMBINE_HIDPI_IMAGES = YES;
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = dwarf;
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				FRAMEWORK_VERSION = A;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
				MACOSX_DEPLOYMENT_TARGET = 10.7;
				MTL_ENABLE_DEBUG_INFO = YES;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.osx;
				PRODUCT_NAME = KVOController;
				SDKROOT = macosx;
				SKIP_INSTALL = YES;
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Debug;
		};
		81EC40FF1CA3639C00BD9226 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				APPLICATION_EXTENSION_API_ONLY = YES;
				CLANG_ANALYZER_NONNULL = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CODE_SIGN_IDENTITY = "-";
				COMBINE_HIDPI_IMAGES = YES;
				COPY_PHASE_STRIP = NO;
				CURRENT_PROJECT_VERSION = 1;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				DEFINES_MODULE = YES;
				DYLIB_COMPATIBILITY_VERSION = 1;
				DYLIB_CURRENT_VERSION = 1;
				DYLIB_INSTALL_NAME_BASE = "@rpath";
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				FRAMEWORK_VERSION = A;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
				INFOPLIST_FILE = "$(SRCROOT)/FBKVOController/Info.plist";
				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
				MACOSX_DEPLOYMENT_TARGET = 10.7;
				MTL_ENABLE_DEBUG_INFO = NO;
				PRODUCT_BUNDLE_IDENTIFIER = com.facebook.kvocontroller.osx;
				PRODUCT_NAME = KVOController;
				SDKROOT = macosx;
				SKIP_INSTALL = YES;
				VERSIONING_SYSTEM = "apple-generic";
				VERSION_INFO_PREFIX = "";
			};
			name = Release;
		};
		ECEA611F18A49C620064AFF4 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				ENABLE_TESTABILITY = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = iphoneos;
			};
			name = Debug;
		};
		ECEA612018A49C620064AFF4 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INFINITE_RECURSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN_SUSPICIOUS_MOVE = YES;
				CLANG_WARN_UNREACHABLE_CODE = YES;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = YES;
				ENABLE_NS_ASSERTIONS = NO;
				ENABLE_STRICT_OBJC_MSGSEND = YES;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_NO_COMMON_BLOCKS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
				SDKROOT = iphoneos;
				VALIDATE_PRODUCT = YES;
			};
			name = Release;
		};
		ECEA612218A49C620064AFF4 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				COPY_PHASE_STRIP = NO;
				DEAD_CODE_STRIPPING = NO;
				DSTROOT = /tmp/FBKVOController.dst;
				OTHER_LDFLAGS = "-ObjC";
				PRODUCT_NAME = "$(TARGET_NAME)";
				PUBLIC_HEADERS_FOLDER_PATH = "$(PROJECT_NAME)Headers";
				SKIP_INSTALL = YES;
				STRIP_STYLE = "non-global";
			};
			name = Debug;
		};
		ECEA612318A49C620064AFF4 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				COPY_PHASE_STRIP = NO;
				DEAD_CODE_STRIPPING = NO;
				DSTROOT = /tmp/FBKVOController.dst;
				OTHER_LDFLAGS = "-ObjC";
				PRODUCT_NAME = "$(TARGET_NAME)";
				PUBLIC_HEADERS_FOLDER_PATH = "$(PROJECT_NAME)Headers";
				SKIP_INSTALL = YES;
				STRIP_STYLE = "non-global";
			};
			name = Release;
		};
		ECEA612518A49C620064AFF4 /* Debug */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 2316F70E2DD4D80B87440A05 /* Pods-FBKVOControllerTests.debug.xcconfig */;
			buildSettings = {
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				INFOPLIST_FILE = "FBKVOControllerTests/FBKVOControllerTests-Info.plist";
				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}";
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = xctest;
			};
			name = Debug;
		};
		ECEA612618A49C620064AFF4 /* Release */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = 3E0BB792112F905E950F2AE4 /* Pods-FBKVOControllerTests.release.xcconfig */;
			buildSettings = {
				INFOPLIST_FILE = "FBKVOControllerTests/FBKVOControllerTests-Info.plist";
				PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.${PRODUCT_NAME:rfc1034identifier}";
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = xctest;
			};
			name = Release;
		};
		ECEA612E18A4A7360064AFF4 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Debug;
		};
		ECEA612F18A4A7360064AFF4 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = "$(TARGET_NAME)";
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		81BD70C51CA4B57F00FB8E4D /* Build configuration list for PBXNativeTarget "FBKVOController-tvOS-Dynamic" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				81BD70C61CA4B57F00FB8E4D /* Debug */,
				81BD70C71CA4B57F00FB8E4D /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		81BD70EF1CA4B98D00FB8E4D /* Build configuration list for PBXNativeTarget "FBKVOController-watchOS-Dynamic" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				81BD70F01CA4B98D00FB8E4D /* Debug */,
				81BD70F11CA4B98D00FB8E4D /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		81EC40CD1CA3620A00BD9226 /* Build configuration list for PBXNativeTarget "FBKVOController-iOS-Dynamic" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				81EC40CB1CA3620A00BD9226 /* Debug */,
				81EC40CC1CA3620A00BD9226 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		81EC40FD1CA3639C00BD9226 /* Build configuration list for PBXNativeTarget "FBKVOController-OSX-Dynamic" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				81EC40FE1CA3639C00BD9226 /* Debug */,
				81EC40FF1CA3639C00BD9226 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		ECEA60F918A49C620064AFF4 /* Build configuration list for PBXProject "FBKVOController" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				ECEA611F18A49C620064AFF4 /* Debug */,
				ECEA612018A49C620064AFF4 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultCo
Download .txt
gitextract_aqb3k6nd/

├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── Examples/
│   ├── Clock-OSX/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Base.lproj/
│   │   │   └── MainMenu.xib
│   │   ├── Clock-OSX-Info.plist
│   │   ├── Clock-OSX-Prefix.pch
│   │   ├── ClockView.h
│   │   ├── ClockView.m
│   │   ├── Images.xcassets/
│   │   │   └── AppIcon.appiconset/
│   │   │       └── Contents.json
│   │   ├── en.lproj/
│   │   │   ├── Credits.rtf
│   │   │   └── InfoPlist.strings
│   │   └── main.m
│   ├── Clock-iOS/
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── Base.lproj/
│   │   │   ├── Main_iPad.storyboard
│   │   │   └── Main_iPhone.storyboard
│   │   ├── Clock-iOS-Info.plist
│   │   ├── Clock-iOS-Prefix.pch
│   │   ├── Clock.h
│   │   ├── Clock.m
│   │   ├── ClockLayer.h
│   │   ├── ClockLayer.m
│   │   ├── ClockView.h
│   │   ├── ClockView.m
│   │   ├── Images.xcassets/
│   │   │   ├── AppIcon.appiconset/
│   │   │   │   └── Contents.json
│   │   │   └── LaunchImage.launchimage/
│   │   │       └── Contents.json
│   │   ├── ViewController.h
│   │   ├── ViewController.m
│   │   ├── en.lproj/
│   │   │   └── InfoPlist.strings
│   │   └── main.m
│   └── Examples.xcodeproj/
│       └── project.pbxproj
├── FBKVOController/
│   ├── FBKVOController.h
│   ├── FBKVOController.m
│   ├── Info.plist
│   ├── KVOController.h
│   ├── NSObject+FBKVOController.h
│   └── NSObject+FBKVOController.m
├── FBKVOController.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   └── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           ├── FBKVOController-OSX-Dynamic.xcscheme
│           ├── FBKVOController-iOS-Dynamic.xcscheme
│           ├── FBKVOController-tvOS-Dynamic.xcscheme
│           ├── FBKVOController-watchOS-Dynamic.xcscheme
│           └── FBKVOController.xcscheme
├── FBKVOController.xcworkspace/
│   └── contents.xcworkspacedata
├── FBKVOControllerTests/
│   ├── FBKVOControllerTests-Info.plist
│   ├── FBKVOControllerTests.m
│   ├── FBKVOTesting.h
│   ├── FBKVOTesting.m
│   └── en.lproj/
│       └── InfoPlist.strings
├── KVOController.podspec
├── LICENSE
├── PATENTS
├── Podfile
├── README.md
├── Rakefile
└── codecov.yml
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: Examples/Clock-iOS/ClockView.h
  type NSUInteger (line 19) | typedef NSUInteger ClockViewStyle;
Condensed preview — 59 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (265K chars).
[
  {
    "path": ".gitignore",
    "chars": 379,
    "preview": "## OS X\n.DS_Store\n\n## Build generated\nbuild/\nDerivedData\n\n## Various settings\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!defa"
  },
  {
    "path": ".travis.yml",
    "chars": 1114,
    "preview": "branches:\n  only:\n    - master\nlanguage: objective-c\nos: osx\nosx_image: xcode8.2\nenv:\n  matrix:\n    - TEST_TYPE=iOS\n    "
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1124,
    "preview": "# Contributing\nWe want to make contributing to KVOController as easy and transparent as\npossible. If you run into proble"
  },
  {
    "path": "Examples/Clock-OSX/AppDelegate.h",
    "chars": 439,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-OSX/AppDelegate.m",
    "chars": 2073,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-OSX/Base.lproj/MainMenu.xib",
    "chars": 46727,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "Examples/Clock-OSX/Clock-OSX-Info.plist",
    "chars": 994,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Examples/Clock-OSX/Clock-OSX-Prefix.pch",
    "chars": 170,
    "preview": "//\n//  Prefix header\n//\n//  The contents of this file are implicitly included at the beginning of every source file.\n//\n"
  },
  {
    "path": "Examples/Clock-OSX/ClockView.h",
    "chars": 430,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-OSX/ClockView.m",
    "chars": 1301,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-OSX/Images.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 903,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"mac\",\n      \"size\" : \"16x16\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : "
  },
  {
    "path": "Examples/Clock-OSX/en.lproj/Credits.rtf",
    "chars": 483,
    "preview": "{\\rtf1\\ansi\\ansicpg1252\\cocoartf1265\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;\\f1\\fnil\\fcharset128 HiraKakuProN-W3;}\n{\\co"
  },
  {
    "path": "Examples/Clock-OSX/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "Examples/Clock-OSX/main.m",
    "chars": 412,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/AppDelegate.h",
    "chars": 444,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/AppDelegate.m",
    "chars": 490,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/Base.lproj/Main_iPad.storyboard",
    "chars": 1915,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "Examples/Clock-iOS/Base.lproj/Main_iPhone.storyboard",
    "chars": 1622,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "Examples/Clock-iOS/Clock-iOS-Info.plist",
    "chars": 1675,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Examples/Clock-iOS/Clock-iOS-Prefix.pch",
    "chars": 340,
    "preview": "//\n//  Prefix header\n//\n//  The contents of this file are implicitly included at the beginning of every source file.\n//\n"
  },
  {
    "path": "Examples/Clock-iOS/Clock.h",
    "chars": 524,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/Clock.m",
    "chars": 1249,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/ClockLayer.h",
    "chars": 482,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/ClockLayer.m",
    "chars": 8738,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/ClockView.h",
    "chars": 547,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/ClockView.m",
    "chars": 1564,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/Images.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 825,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\""
  },
  {
    "path": "Examples/Clock-iOS/Images.xcassets/LaunchImage.launchimage/Contents.json",
    "chars": 1100,
    "preview": "{\n  \"images\" : [\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"extent\" : \"full-screen\",\n     "
  },
  {
    "path": "Examples/Clock-iOS/ViewController.h",
    "chars": 379,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/ViewController.m",
    "chars": 2332,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Clock-iOS/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "Examples/Clock-iOS/main.m",
    "chars": 505,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "Examples/Examples.xcodeproj/project.pbxproj",
    "chars": 29224,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "FBKVOController/FBKVOController.h",
    "chars": 9475,
    "preview": "/**\n Copyright (c) 2014-present, Facebook, Inc.\n All rights reserved.\n\n This source code is licensed under the BSD-style"
  },
  {
    "path": "FBKVOController/FBKVOController.m",
    "chars": 19599,
    "preview": "/**\n Copyright (c) 2014-present, Facebook, Inc.\n All rights reserved.\n\n This source code is licensed under the BSD-style"
  },
  {
    "path": "FBKVOController/Info.plist",
    "chars": 787,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "FBKVOController/KVOController.h",
    "chars": 391,
    "preview": "/**\n Copyright (c) 2014-present, Facebook, Inc.\n All rights reserved.\n\n This source code is licensed under the BSD-style"
  },
  {
    "path": "FBKVOController/NSObject+FBKVOController.h",
    "chars": 1705,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "FBKVOController/NSObject+FBKVOController.m",
    "chars": 1832,
    "preview": "/**\n Copyright (c) 2014-present, Facebook, Inc.\n All rights reserved.\n \n This source code is licensed under the BSD-styl"
  },
  {
    "path": "FBKVOController.xcodeproj/project.pbxproj",
    "chars": 51027,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXAggregateTarget sec"
  },
  {
    "path": "FBKVOController.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 160,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:FBKVOController"
  },
  {
    "path": "FBKVOController.xcodeproj/xcshareddata/xcschemes/FBKVOController-OSX-Dynamic.xcscheme",
    "chars": 2952,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0820\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "FBKVOController.xcodeproj/xcshareddata/xcschemes/FBKVOController-iOS-Dynamic.xcscheme",
    "chars": 2952,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0820\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "FBKVOController.xcodeproj/xcshareddata/xcschemes/FBKVOController-tvOS-Dynamic.xcscheme",
    "chars": 2955,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0820\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "FBKVOController.xcodeproj/xcshareddata/xcschemes/FBKVOController-watchOS-Dynamic.xcscheme",
    "chars": 2964,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0820\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "FBKVOController.xcodeproj/xcshareddata/xcschemes/FBKVOController.xcscheme",
    "chars": 2979,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0820\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "FBKVOController.xcworkspace/contents.xcworkspacedata",
    "chars": 313,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:FBKVOControlle"
  },
  {
    "path": "FBKVOControllerTests/FBKVOControllerTests-Info.plist",
    "chars": 674,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "FBKVOControllerTests/FBKVOControllerTests.m",
    "chars": 20523,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "FBKVOControllerTests/FBKVOTesting.h",
    "chars": 1261,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "FBKVOControllerTests/FBKVOTesting.m",
    "chars": 1138,
    "preview": "/**\n  Copyright (c) 2014-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-st"
  },
  {
    "path": "FBKVOControllerTests/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "KVOController.podspec",
    "chars": 1296,
    "preview": "Pod::Spec.new do |spec|\n  spec.name         = 'KVOController'\n  spec.version      = '1.2.0'\n  spec.license      =  { :ty"
  },
  {
    "path": "LICENSE",
    "chars": 1526,
    "preview": "BSD License\n\nFor KVOController software\n\nCopyright (c) 2014, Facebook, Inc. All rights reserved.\n\nRedistribution and use"
  },
  {
    "path": "PATENTS",
    "chars": 1982,
    "preview": "Additional Grant of Patent Rights Version 2\n\n\"Software\" means the KVOController software distributed by Facebook, Inc.\n\n"
  },
  {
    "path": "Podfile",
    "chars": 149,
    "preview": "source 'https://github.com/CocoaPods/Specs.git'\nproject 'FBKVOController.xcodeproj'\n\ntarget :FBKVOControllerTests do\n  p"
  },
  {
    "path": "README.md",
    "chars": 4694,
    "preview": "# [KVOController](https://github.com/facebook/KVOController)\n[![Build Status](https://img.shields.io/travis/facebook/KVO"
  },
  {
    "path": "Rakefile",
    "chars": 1503,
    "preview": "#\n# Copyright (c) 2016-present, Facebook, Inc.\n# All rights reserved.\n#\n# This source code is licensed under the BSD-sty"
  },
  {
    "path": "codecov.yml",
    "chars": 157,
    "preview": "coverage:\n  ignore:\n    - FBKVOControllerTests/*\n  status:\n    patch: false\n    changes: false\n    project:\n      defaul"
  }
]

About this extraction

This page contains the full source code of the facebookarchive/KVOController GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 59 files (239.9 KB), approximately 64.1k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!