├── OKObserver ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── NSObject+ObservingKeypath.h │ ├── OKObserver.h │ ├── NSObject+ObservingKeypath.m │ ├── EXTKeyPathCoding.h │ ├── OKObserver.m │ └── metamacros.h ├── _Pods.xcodeproj ├── Example ├── Tests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── Tests-Info.plist ├── OKObserver │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── XXObject.m │ ├── OKViewController.h │ ├── OKAppDelegate.h │ ├── XXObject.h │ ├── OKObserver-Prefix.pch │ ├── main.m │ ├── OKViewController.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── OKObserver-Info.plist │ ├── Main.storyboard │ └── OKAppDelegate.m ├── OKObserver.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── xcshareddata │ │ └── xcschemes │ │ │ └── OKObserver-Example.xcscheme │ └── project.pbxproj ├── Podfile ├── OKObserver.xcworkspace │ └── contents.xcworkspacedata └── Podfile.lock ├── .gitattributes ├── fastlane ├── Appfile ├── README.md ├── Fastfile └── actions │ ├── sync_build_number_to_git.rb │ └── git_commit_all.rb ├── .travis.yml ├── .gitignore ├── OKObserver.podspec ├── LICENSE └── README.md /OKObserver/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /OKObserver/Classes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.c linguist-language=Objective-C 2 | *.h linguist-language=Objective-C 3 | 4 | -------------------------------------------------------------------------------- /Example/OKObserver/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // The contents of this file are implicitly included at the beginning of every test case source file. 2 | 3 | #ifdef __OBJC__ 4 | 5 | @import Specta; 6 | @import Expecta; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /Example/OKObserver.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'OKObserver_Example' do 4 | pod 'OKObserver', :path => '../' 5 | 6 | target 'OKObserver_Tests' do 7 | inherit! :search_paths 8 | 9 | pod 'Specta' 10 | pod 'Expecta' 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /Example/OKObserver/XXObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // XXObject.m 3 | // Tied 4 | // 5 | // Created by Draveness on 5/18/16. 6 | // Copyright © 2016 Draveness. All rights reserved. 7 | // 8 | 9 | #import "XXObject.h" 10 | 11 | @implementation XXObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/OKObserver/OKViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // OKViewController.h 3 | // OKObserver 4 | // 5 | // Created by Draveness on 05/18/2016. 6 | // Copyright (c) 2016 Draveness. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface OKViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/OKObserver.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OKObserver/Classes/NSObject+ObservingKeypath.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+ObservingKeypath.h 3 | // Pods 4 | // 5 | // Created by Draveness on 5/18/16. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (ObservingKeypath) 12 | 13 | @property (nonatomic, strong) NSMutableArray *observingKeypath; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | app_identifier "" # The bundle identifier of your app 2 | apple_id "" # Your Apple email address 3 | 4 | team_id "[[DEV_PORTAL_TEAM_ID]]" # Developer Portal Team ID 5 | 6 | # you can even provide different app identifiers, Apple IDs and team names per lane: 7 | # More information: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Appfile.md 8 | -------------------------------------------------------------------------------- /Example/OKObserver/OKAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // OKAppDelegate.h 3 | // OKObserver 4 | // 5 | // Created by Draveness on 05/18/2016. 6 | // Copyright (c) 2016 Draveness. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface OKAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/OKObserver/XXObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // XXObject.h 3 | // Tied 4 | // 5 | // Created by Draveness on 5/18/16. 6 | // Copyright © 2016 Draveness. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XXObject : NSObject 12 | 13 | @property (nonatomic, assign) CGFloat number; 14 | @property (nonatomic, strong) UIColor *color; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Example/OKObserver/OKObserver-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | @import Foundation; 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/OKObserver/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OKObserver 4 | // 5 | // Created by Draveness on 05/18/2016. 6 | // Copyright (c) 2016 Draveness. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "OKAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([OKAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | language: objective-c 6 | podfile: Example/Podfile 7 | osx_image: xcode7.3 8 | before_install: 9 | - gem install cocoapods # Since Travis is not always on latest version 10 | - pod install --project-directory=Example 11 | script: 12 | - set -o pipefail && xcodebuild test -workspace Example/OKObserver.xcworkspace -scheme OKObserver-Example -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty 13 | - pod lib lint 14 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Expecta (1.0.5) 3 | - OKObserver (0.1.0) 4 | - Specta (1.0.5) 5 | 6 | DEPENDENCIES: 7 | - Expecta 8 | - OKObserver (from `../`) 9 | - Specta 10 | 11 | EXTERNAL SOURCES: 12 | OKObserver: 13 | :path: "../" 14 | 15 | SPEC CHECKSUMS: 16 | Expecta: e1c022fcd33910b6be89c291d2775b3fe27a89fe 17 | OKObserver: d4f94b85e09182414624592066b2030a71108ffa 18 | Specta: ac94d110b865115fe60ff2c6d7281053c6f8e8a2 19 | 20 | PODFILE CHECKSUM: 4df3c55e5f1e167d3c1430091b699e47421a29e7 21 | 22 | COCOAPODS: 1.0.0 23 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | ``` 5 | sudo gem install fastlane 6 | ``` 7 | # Available Actions 8 | ### release 9 | ``` 10 | fastlane release 11 | ``` 12 | Release new version 13 | 14 | ---- 15 | 16 | This README.md is auto-generated and will be re-generated every time to run [fastlane](https://fastlane.tools). 17 | More information about fastlane can be found on [https://fastlane.tools](https://fastlane.tools). 18 | The documentation of fastlane can be found on [GitHub](https://github.com/fastlane/fastlane/tree/master/fastlane). -------------------------------------------------------------------------------- /OKObserver/Classes/OKObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // OKObserver.h 3 | // Pods 4 | // 5 | // Created by Draveness on 5/18/16. 6 | // 7 | // 8 | 9 | #import 10 | #import "EXTKeyPathCoding.h" 11 | 12 | #define OKObserve(OBSERVEE, KEYPATH) [OKObserver observerWithObservee:OBSERVEE keypath:@keypath(OBSERVEE, KEYPATH)] 13 | 14 | @interface OKObserver : NSObject 15 | 16 | - (instancetype)initWithObservee:(id)observee keypath:(NSString *)keypath; 17 | 18 | + (OKObserver *)observerWithObservee:(id)observee keypath:(NSString *)keypath; 19 | 20 | - (void)whenUpdated:(void(^)(id newValue))updateBlock; 21 | 22 | - (void)update:(OKObserver *)observer; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // OKObserverTests.m 3 | // OKObserverTests 4 | // 5 | // Created by Draveness on 05/18/2016. 6 | // Copyright (c) 2016 Draveness. All rights reserved. 7 | // 8 | 9 | // https://github.com/Specta/Specta 10 | 11 | SpecBegin(InitialSpecs) 12 | 13 | describe(@"these will pass", ^{ 14 | 15 | it(@"can do maths", ^{ 16 | expect(1).beLessThan(23); 17 | }); 18 | 19 | it(@"can read", ^{ 20 | expect(@"team").toNot.contain(@"I"); 21 | }); 22 | 23 | it(@"will wait and succeed", ^{ 24 | waitUntil(^(DoneCallback done) { 25 | done(); 26 | }); 27 | }); 28 | }); 29 | 30 | SpecEnd 31 | 32 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | Carthage 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Note: if you ignore the Pods directory, make sure to uncomment 31 | # `pod install` in .travis.yml 32 | # 33 | Pods/ 34 | 35 | # Fastlane 36 | fastlane/report.xml 37 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | fastlane_version "1.89.0" 2 | 3 | default_platform :ios 4 | 5 | # Fastfile 6 | desc "Release new version" 7 | lane :release do |options| 8 | target_version = options[:version] 9 | raise "The version is missed." if target_version.nil? 10 | ensure_git_branch 11 | ensure_git_status_clean 12 | # scan 13 | 14 | sync_build_number_to_git 15 | increment_version_number(version_number: target_version) 16 | 17 | version_bump_podspec(path: "OKObserver.podspec", 18 | version_number: target_version) 19 | git_commit_all(message: "Bump version to #{target_version}") 20 | add_git_tag tag: target_version 21 | push_to_git_remote 22 | pod_push 23 | end 24 | 25 | -------------------------------------------------------------------------------- /Example/OKObserver/OKViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // OKViewController.m 3 | // OKObserver 4 | // 5 | // Created by Draveness on 05/18/2016. 6 | // Copyright (c) 2016 Draveness. All rights reserved. 7 | // 8 | 9 | #import "OKViewController.h" 10 | #import "OKObserver.h" 11 | #import "XXObject.h" 12 | 13 | @interface OKViewController () 14 | 15 | @end 16 | 17 | @implementation OKViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | XXObject *object = [XXObject new]; 22 | object.color = [UIColor redColor]; 23 | [OKObserve(object, color) update:OKObserve(self, view.backgroundColor)]; 24 | 25 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 26 | object.color = [UIColor yellowColor]; 27 | }); 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /OKObserver/Classes/NSObject+ObservingKeypath.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+ObservingKeypath.m 3 | // Pods 4 | // 5 | // Created by Draveness on 5/18/16. 6 | // 7 | // 8 | 9 | #import "NSObject+ObservingKeypath.h" 10 | 11 | @import ObjectiveC.runtime; 12 | @import ObjectiveC.message; 13 | 14 | 15 | @implementation NSObject (ObservingKeypath) 16 | 17 | - (NSMutableArray *)observingKeypath { 18 | NSMutableArray *result = objc_getAssociatedObject(self, @selector(observingKeypath)); 19 | if (!result) { 20 | result = [[NSMutableArray alloc] init]; 21 | [self setObservingKeypath:result]; 22 | } 23 | return result; 24 | } 25 | 26 | - (void)setObservingKeypath:(NSMutableArray *)observingKeypath { 27 | objc_setAssociatedObject(self, @selector(observingKeypath), observingKeypath, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 28 | } 29 | 30 | @end 31 | 32 | -------------------------------------------------------------------------------- /fastlane/actions/sync_build_number_to_git.rb: -------------------------------------------------------------------------------- 1 | module Fastlane 2 | module Actions 3 | module SharedValues 4 | BUILD_NUMBER = :BUILD_NUMBER 5 | end 6 | class SyncBuildNumberToGitAction < Action 7 | def self.is_git? 8 | Actions.sh 'git rev-parse HEAD' 9 | return true 10 | rescue 11 | return false 12 | end 13 | 14 | def self.run(params) 15 | if is_git? 16 | command = 'git rev-list HEAD --count' 17 | else 18 | raise "Not in a git repository." 19 | end 20 | build_number = (Actions.sh command).strip 21 | Fastlane::Actions::IncrementBuildNumberAction.run(build_number: build_number) 22 | Actions.lane_context[SharedValues::BUILD_NUMBER] = build_number 23 | end 24 | 25 | def self.output 26 | [ 27 | ['BUILD_NUMBER', 'The new build number'] 28 | ] 29 | end 30 | end 31 | end 32 | end 33 | 34 | -------------------------------------------------------------------------------- /fastlane/actions/git_commit_all.rb: -------------------------------------------------------------------------------- 1 | module Fastlane 2 | module Actions 3 | class GitCommitAllAction < Action 4 | def self.run(params) 5 | Actions.sh "git commit -am \"#{params[:message]}\"" 6 | end 7 | 8 | ##################################################### 9 | # @!group Documentation 10 | ##################################################### 11 | 12 | def self.description 13 | "Commit all unsaved changes to git." 14 | end 15 | 16 | def self.available_options 17 | [ 18 | FastlaneCore::ConfigItem.new(key: :message, 19 | env_name: "FL_GIT_COMMIT_ALL", 20 | description: "The git message for the commit", 21 | is_string: true) 22 | ] 23 | end 24 | 25 | def self.is_supported?(platform) 26 | true 27 | end 28 | end 29 | end 30 | end 31 | 32 | -------------------------------------------------------------------------------- /OKObserver.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "OKObserver" 3 | s.version = "0.1.0" 4 | s.summary = "A lightweight framework which makes KVO easily to use." 5 | 6 | s.description = <<-DESC 7 | KVO is very troublesome to use, you need to call addObserver: method, override method 8 | to observe the event. All I need is when there is somthing changed, execute blocks. 9 | At first ReactiveCocoa fits my requirement, and I really had a happy time with it. But 10 | it is a swift framework and doesn't officially support cocoapods as installation method. 11 | OKObserver is created under this circumstance to help us bind model and view. 12 | DESC 13 | 14 | s.homepage = "https://github.com/draveness/OKObserver" 15 | s.license = 'MIT' 16 | s.author = { "Draveness" => "stark.draven@gmail.com" } 17 | s.source = { :git => "https://github.com/draveness/OKObserver.git", :tag => s.version.to_s } 18 | 19 | s.ios.deployment_target = '8.0' 20 | 21 | s.source_files = 'OKObserver/Classes/**/*' 22 | 23 | end 24 | -------------------------------------------------------------------------------- /Example/OKObserver/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Draveness 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/OKObserver/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OKObserver 2 | 3 | A lightweight framework which makes KVO easily to use. 4 | 5 | [![CI Status](http://img.shields.io/travis/Draveness/OKObserver.svg?style=flat)](https://travis-ci.org/Draveness/OKObserver) 6 | [![Version](https://img.shields.io/cocoapods/v/OKObserver.svg?style=flat)](http://cocoapods.org/pods/OKObserver) 7 | [![License](https://img.shields.io/cocoapods/l/OKObserver.svg?style=flat)](http://cocoapods.org/pods/OKObserver) 8 | [![Platform](https://img.shields.io/cocoapods/p/OKObserver.svg?style=flat)](http://cocoapods.org/pods/OKObserver) 9 | 10 | ## Installation 11 | 12 | OKObserver is available through [CocoaPods](http://cocoapods.org). To install 13 | it, simply add the following line to your Podfile: 14 | 15 | ```ruby 16 | pod "OKObserver" 17 | ``` 18 | 19 | ## Usage 20 | 21 | Use `OKObserver` to bind view and model. 22 | 23 | ```objectivec 24 | [OKObserve(object, color) update:OKObserve(self.view, backgroundColor)]; 25 | ``` 26 | 27 | Easily to use API for KVO 28 | 29 | ```objectivec 30 | [OKObserve(object, color) whenUpdated:^(UIColor *backgroundColor) { 31 | self.view.backgroundColor = backgroundColor; 32 | }]; 33 | ``` 34 | 35 | The two usage above has the same function. 36 | 37 | ## Author 38 | 39 | Draveness, stark.draven@gmail.com 40 | 41 | ## License 42 | 43 | OKObserver is available under the MIT license. See the LICENSE file for more info. 44 | -------------------------------------------------------------------------------- /Example/OKObserver/OKObserver-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Example/OKObserver/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/OKObserver/OKAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // OKAppDelegate.m 3 | // OKObserver 4 | // 5 | // Created by Draveness on 05/18/2016. 6 | // Copyright (c) 2016 Draveness. All rights reserved. 7 | // 8 | 9 | #import "OKAppDelegate.h" 10 | 11 | @implementation OKAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /OKObserver/Classes/EXTKeyPathCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXTKeyPathCoding.h 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 19.06.12. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import 11 | #import "metamacros.h" 12 | 13 | /** 14 | * \@keypath allows compile-time verification of key paths. Given a real object 15 | * receiver and key path: 16 | * 17 | * @code 18 | 19 | NSString *UTF8StringPath = @keypath(str.lowercaseString.UTF8String); 20 | // => @"lowercaseString.UTF8String" 21 | 22 | NSString *versionPath = @keypath(NSObject, version); 23 | // => @"version" 24 | 25 | NSString *lowercaseStringPath = @keypath(NSString.new, lowercaseString); 26 | // => @"lowercaseString" 27 | 28 | * @endcode 29 | * 30 | * ... the macro returns an \c NSString containing all but the first path 31 | * component or argument (e.g., @"lowercaseString.UTF8String", @"version"). 32 | * 33 | * In addition to simply creating a key path, this macro ensures that the key 34 | * path is valid at compile-time (causing a syntax error if not), and supports 35 | * refactoring, such that changing the name of the property will also update any 36 | * uses of \@keypath. 37 | */ 38 | #define keypath(...) \ 39 | _Pragma("clang diagnostic push") \ 40 | _Pragma("clang diagnostic ignored \"-Warc-repeated-use-of-weak\"") \ 41 | metamacro_if_eq(1, metamacro_argcount(__VA_ARGS__))(keypath1(__VA_ARGS__))(keypath2(__VA_ARGS__)) \ 42 | _Pragma("clang diagnostic pop") \ 43 | 44 | #define keypath1(PATH) \ 45 | (((void)(NO && ((void)PATH, NO)), strchr(# PATH, '.') + 1)) 46 | 47 | #define keypath2(OBJ, PATH) \ 48 | (((void)(NO && ((void)OBJ.PATH, NO)), # PATH)) 49 | 50 | /** 51 | * \@collectionKeypath allows compile-time verification of key paths across collections NSArray/NSSet etc. Given a real object 52 | * receiver, collection object receiver and related keypaths: 53 | * 54 | * @code 55 | 56 | NSString *employeesFirstNamePath = @collectionKeypath(department.employees, Employee.new, firstName) 57 | // => @"employees.firstName" 58 | 59 | NSString *employeesFirstNamePath = @collectionKeypath(Department.new, employees, Employee.new, firstName) 60 | // => @"employees.firstName" 61 | 62 | * @endcode 63 | * 64 | */ 65 | #define collectionKeypath(...) \ 66 | metamacro_if_eq(3, metamacro_argcount(__VA_ARGS__))(collectionKeypath3(__VA_ARGS__))(collectionKeypath4(__VA_ARGS__)) 67 | 68 | #define collectionKeypath3(PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String]) 69 | 70 | #define collectionKeypath4(OBJ, PATH, COLLECTION_OBJECT, COLLECTION_PATH) ([[NSString stringWithFormat:@"%s.%s",keypath(OBJ, PATH), keypath(COLLECTION_OBJECT, COLLECTION_PATH)] UTF8String]) 71 | 72 | -------------------------------------------------------------------------------- /Example/OKObserver.xcodeproj/xcshareddata/xcschemes/OKObserver-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /OKObserver/Classes/OKObserver.m: -------------------------------------------------------------------------------- 1 | // 2 | // OKObserver.m 3 | // Pods 4 | // 5 | // Created by Draveness on 5/18/16. 6 | // 7 | // 8 | 9 | #import "OKObserver.h" 10 | #import "NSObject+ObservingKeypath.h" 11 | 12 | @import ObjectiveC.runtime; 13 | @import ObjectiveC.message; 14 | 15 | @interface OKObserver () 16 | 17 | @property (nonatomic, weak) id observee; 18 | @property (nonatomic, strong) NSString *keypath; 19 | 20 | @property (nonatomic, copy) void(^updateBlock)(id newValue); 21 | 22 | @end 23 | 24 | @implementation OKObserver 25 | 26 | 27 | static NSMutableArray *SwizzledDeallocClasses; 28 | 29 | + (void)load { 30 | SwizzledDeallocClasses = [[NSMutableArray alloc] init]; 31 | } 32 | 33 | + (OKObserver *)observerWithObservee:(id)observee keypath:(NSString *)keypath { 34 | OKObserver *observer = [[OKObserver alloc] initWithObservee:observee keypath:keypath]; 35 | 36 | return observer; 37 | } 38 | 39 | - (instancetype)initWithObservee:(id)observee keypath:(NSString *)keypath { 40 | if (self = [super init]) { 41 | _observee = observee; 42 | _keypath = keypath; 43 | 44 | 45 | } 46 | return self; 47 | } 48 | 49 | - (void)whenUpdated:(void (^)(id))updateBlock { 50 | [_observee addObserver:self 51 | forKeyPath:_keypath 52 | options:NSKeyValueObservingOptionNew 53 | context:NULL]; 54 | [[_observee observingKeypath] addObject:_keypath]; 55 | [self swizzledDeallocSelectorForObject:_observee]; 56 | 57 | _updateBlock = updateBlock; 58 | id newValue = [self.observee valueForKeyPath:self.keypath]; 59 | _updateBlock(newValue); 60 | } 61 | 62 | - (void)update:(OKObserver *)observer { 63 | [self whenUpdated:_updateBlock = ^(id newValue) { 64 | [observer.observee setValue:newValue forKeyPath:observer.keypath]; 65 | }]; 66 | } 67 | 68 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 69 | if ([keyPath isEqualToString:self.keypath]) { 70 | id newValue = change[NSKeyValueChangeNewKey]; 71 | _updateBlock(newValue); 72 | } 73 | } 74 | 75 | #pragma mark - Swizzling 76 | 77 | - (void)swizzledDeallocSelectorForObject:(id)observee { 78 | Class classToSwizzle = [_observee class]; 79 | 80 | @synchronized (SwizzledDeallocClasses) { 81 | NSString *className = NSStringFromClass(classToSwizzle); 82 | if (![SwizzledDeallocClasses containsObject:className]) { 83 | SEL deallocSelector = sel_registerName("dealloc"); 84 | 85 | __block void (*originalDealloc)(__unsafe_unretained id, SEL) = NULL; 86 | 87 | id newDealloc = ^(__unsafe_unretained id objSelf) { 88 | for (NSString *keypath in [observee observingKeypath]) { 89 | [observee removeObserver:self forKeyPath:keypath]; 90 | } 91 | [observee setObservingKeypath:nil]; 92 | 93 | if (originalDealloc == NULL) { 94 | struct objc_super superInfo = { 95 | .receiver = objSelf, 96 | .super_class = class_getSuperclass(classToSwizzle) 97 | }; 98 | 99 | void (*msgSend)(struct objc_super *, SEL) = (__typeof__(msgSend))objc_msgSendSuper; 100 | msgSend(&superInfo, deallocSelector); 101 | } else { 102 | originalDealloc(objSelf, deallocSelector); 103 | } 104 | }; 105 | 106 | IMP newDeallocIMP = imp_implementationWithBlock(newDealloc); 107 | 108 | if (!class_addMethod(classToSwizzle, deallocSelector, newDeallocIMP, "v@:")) { 109 | // The class already contains a method implementation. 110 | Method deallocMethod = class_getInstanceMethod(classToSwizzle, deallocSelector); 111 | 112 | // We need to store original implementation before setting new implementation 113 | // in case method is called at the time of setting. 114 | originalDealloc = (void(*)(__unsafe_unretained id, SEL))method_getImplementation(deallocMethod); 115 | 116 | // We need to store original implementation again, in case it just changed. 117 | originalDealloc = (void(*)(__unsafe_unretained id, SEL))method_setImplementation(deallocMethod, newDeallocIMP); 118 | } 119 | 120 | [SwizzledDeallocClasses addObject:className]; 121 | } 122 | } 123 | } 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /Example/OKObserver.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 11 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 12 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 13 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; 14 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; 15 | 6003F59E195388D20070C39A /* OKAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* OKAppDelegate.m */; }; 16 | 6003F5A7195388D20070C39A /* OKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* OKViewController.m */; }; 17 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; 18 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 19 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 20 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 21 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 22 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; 23 | 728E05331CECB0C70043EE32 /* XXObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 728E05321CECB0C70043EE32 /* XXObject.m */; }; 24 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; }; 25 | A81C1E5CFBACC17F096DFF8D /* Pods_OKObserver_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B4E290A60EAC40112D147673 /* Pods_OKObserver_Tests.framework */; }; 26 | C8FDF618C51C9F290D967C2E /* Pods_OKObserver_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F82DA1E5552B0B63AAA2528 /* Pods_OKObserver_Example.framework */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 6003F582195388D10070C39A /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 6003F589195388D20070C39A; 35 | remoteInfo = OKObserver; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 2F0D94B829998A6D0DD0AAAA /* Pods-OKObserver_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OKObserver_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-OKObserver_Tests/Pods-OKObserver_Tests.debug.xcconfig"; sourceTree = ""; }; 41 | 3A0448665801C104A9EA6720 /* Pods-OKObserver_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OKObserver_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-OKObserver_Tests/Pods-OKObserver_Tests.release.xcconfig"; sourceTree = ""; }; 42 | 5052914208A19F9BDC23C4B0 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 43 | 6003F58A195388D20070C39A /* OKObserver_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OKObserver_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 45 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 46 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 47 | 6003F595195388D20070C39A /* OKObserver-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OKObserver-Info.plist"; sourceTree = ""; }; 48 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 49 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 50 | 6003F59B195388D20070C39A /* OKObserver-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OKObserver-Prefix.pch"; sourceTree = ""; }; 51 | 6003F59C195388D20070C39A /* OKAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OKAppDelegate.h; sourceTree = ""; }; 52 | 6003F59D195388D20070C39A /* OKAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OKAppDelegate.m; sourceTree = ""; }; 53 | 6003F5A5195388D20070C39A /* OKViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OKViewController.h; sourceTree = ""; }; 54 | 6003F5A6195388D20070C39A /* OKViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OKViewController.m; sourceTree = ""; }; 55 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 56 | 6003F5AE195388D20070C39A /* OKObserver_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OKObserver_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 58 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 59 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 60 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 61 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 62 | 728E05311CECB0C70043EE32 /* XXObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XXObject.h; sourceTree = ""; }; 63 | 728E05321CECB0C70043EE32 /* XXObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XXObject.m; sourceTree = ""; }; 64 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 65 | 87EF675D222DCD0F9CB90FCD /* Pods-OKObserver_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OKObserver_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-OKObserver_Example/Pods-OKObserver_Example.release.xcconfig"; sourceTree = ""; }; 66 | 9141E2533DDA672CA564680D /* OKObserver.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = OKObserver.podspec; path = ../OKObserver.podspec; sourceTree = ""; }; 67 | 9144D3D6B9448411B7751F2F /* Pods-OKObserver_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OKObserver_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-OKObserver_Example/Pods-OKObserver_Example.debug.xcconfig"; sourceTree = ""; }; 68 | 9F82DA1E5552B0B63AAA2528 /* Pods_OKObserver_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OKObserver_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | B4E290A60EAC40112D147673 /* Pods_OKObserver_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OKObserver_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 70 | C605D964621B4C7464742C8D /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 71 | /* End PBXFileReference section */ 72 | 73 | /* Begin PBXFrameworksBuildPhase section */ 74 | 6003F587195388D20070C39A /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 79 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 80 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, 81 | C8FDF618C51C9F290D967C2E /* Pods_OKObserver_Example.framework in Frameworks */, 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | 6003F5AB195388D20070C39A /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 90 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 91 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, 92 | A81C1E5CFBACC17F096DFF8D /* Pods_OKObserver_Tests.framework in Frameworks */, 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | /* End PBXFrameworksBuildPhase section */ 97 | 98 | /* Begin PBXGroup section */ 99 | 0172A996DFAD2C8CF24EC1A2 /* Pods */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 9144D3D6B9448411B7751F2F /* Pods-OKObserver_Example.debug.xcconfig */, 103 | 87EF675D222DCD0F9CB90FCD /* Pods-OKObserver_Example.release.xcconfig */, 104 | 2F0D94B829998A6D0DD0AAAA /* Pods-OKObserver_Tests.debug.xcconfig */, 105 | 3A0448665801C104A9EA6720 /* Pods-OKObserver_Tests.release.xcconfig */, 106 | ); 107 | name = Pods; 108 | sourceTree = ""; 109 | }; 110 | 6003F581195388D10070C39A = { 111 | isa = PBXGroup; 112 | children = ( 113 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 114 | 6003F593195388D20070C39A /* Example for OKObserver */, 115 | 6003F5B5195388D20070C39A /* Tests */, 116 | 6003F58C195388D20070C39A /* Frameworks */, 117 | 6003F58B195388D20070C39A /* Products */, 118 | 0172A996DFAD2C8CF24EC1A2 /* Pods */, 119 | ); 120 | sourceTree = ""; 121 | }; 122 | 6003F58B195388D20070C39A /* Products */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 6003F58A195388D20070C39A /* OKObserver_Example.app */, 126 | 6003F5AE195388D20070C39A /* OKObserver_Tests.xctest */, 127 | ); 128 | name = Products; 129 | sourceTree = ""; 130 | }; 131 | 6003F58C195388D20070C39A /* Frameworks */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 6003F58D195388D20070C39A /* Foundation.framework */, 135 | 6003F58F195388D20070C39A /* CoreGraphics.framework */, 136 | 6003F591195388D20070C39A /* UIKit.framework */, 137 | 6003F5AF195388D20070C39A /* XCTest.framework */, 138 | 9F82DA1E5552B0B63AAA2528 /* Pods_OKObserver_Example.framework */, 139 | B4E290A60EAC40112D147673 /* Pods_OKObserver_Tests.framework */, 140 | ); 141 | name = Frameworks; 142 | sourceTree = ""; 143 | }; 144 | 6003F593195388D20070C39A /* Example for OKObserver */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 6003F59C195388D20070C39A /* OKAppDelegate.h */, 148 | 6003F59D195388D20070C39A /* OKAppDelegate.m */, 149 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */, 150 | 6003F5A5195388D20070C39A /* OKViewController.h */, 151 | 6003F5A6195388D20070C39A /* OKViewController.m */, 152 | 728E05311CECB0C70043EE32 /* XXObject.h */, 153 | 728E05321CECB0C70043EE32 /* XXObject.m */, 154 | 6003F5A8195388D20070C39A /* Images.xcassets */, 155 | 6003F594195388D20070C39A /* Supporting Files */, 156 | ); 157 | name = "Example for OKObserver"; 158 | path = OKObserver; 159 | sourceTree = ""; 160 | }; 161 | 6003F594195388D20070C39A /* Supporting Files */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 6003F595195388D20070C39A /* OKObserver-Info.plist */, 165 | 6003F596195388D20070C39A /* InfoPlist.strings */, 166 | 6003F599195388D20070C39A /* main.m */, 167 | 6003F59B195388D20070C39A /* OKObserver-Prefix.pch */, 168 | ); 169 | name = "Supporting Files"; 170 | sourceTree = ""; 171 | }; 172 | 6003F5B5195388D20070C39A /* Tests */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 6003F5BB195388D20070C39A /* Tests.m */, 176 | 6003F5B6195388D20070C39A /* Supporting Files */, 177 | ); 178 | path = Tests; 179 | sourceTree = ""; 180 | }; 181 | 6003F5B6195388D20070C39A /* Supporting Files */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 6003F5B7195388D20070C39A /* Tests-Info.plist */, 185 | 6003F5B8195388D20070C39A /* InfoPlist.strings */, 186 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, 187 | ); 188 | name = "Supporting Files"; 189 | sourceTree = ""; 190 | }; 191 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 9141E2533DDA672CA564680D /* OKObserver.podspec */, 195 | 5052914208A19F9BDC23C4B0 /* README.md */, 196 | C605D964621B4C7464742C8D /* LICENSE */, 197 | ); 198 | name = "Podspec Metadata"; 199 | sourceTree = ""; 200 | }; 201 | /* End PBXGroup section */ 202 | 203 | /* Begin PBXNativeTarget section */ 204 | 6003F589195388D20070C39A /* OKObserver_Example */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "OKObserver_Example" */; 207 | buildPhases = ( 208 | EA867EEE6668783E85C3AA92 /* 📦 Check Pods Manifest.lock */, 209 | 6003F586195388D20070C39A /* Sources */, 210 | 6003F587195388D20070C39A /* Frameworks */, 211 | 6003F588195388D20070C39A /* Resources */, 212 | E5809A73AFFD5DC9C8CC982F /* 📦 Embed Pods Frameworks */, 213 | D4CB71AF72288900DD53DC58 /* 📦 Copy Pods Resources */, 214 | ); 215 | buildRules = ( 216 | ); 217 | dependencies = ( 218 | ); 219 | name = OKObserver_Example; 220 | productName = OKObserver; 221 | productReference = 6003F58A195388D20070C39A /* OKObserver_Example.app */; 222 | productType = "com.apple.product-type.application"; 223 | }; 224 | 6003F5AD195388D20070C39A /* OKObserver_Tests */ = { 225 | isa = PBXNativeTarget; 226 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "OKObserver_Tests" */; 227 | buildPhases = ( 228 | D45D64C6D394258712301EB8 /* 📦 Check Pods Manifest.lock */, 229 | 6003F5AA195388D20070C39A /* Sources */, 230 | 6003F5AB195388D20070C39A /* Frameworks */, 231 | 6003F5AC195388D20070C39A /* Resources */, 232 | 8DE1F124571246FA8BA9D762 /* 📦 Embed Pods Frameworks */, 233 | A749340159E4B39BE4484653 /* 📦 Copy Pods Resources */, 234 | ); 235 | buildRules = ( 236 | ); 237 | dependencies = ( 238 | 6003F5B4195388D20070C39A /* PBXTargetDependency */, 239 | ); 240 | name = OKObserver_Tests; 241 | productName = OKObserverTests; 242 | productReference = 6003F5AE195388D20070C39A /* OKObserver_Tests.xctest */; 243 | productType = "com.apple.product-type.bundle.unit-test"; 244 | }; 245 | /* End PBXNativeTarget section */ 246 | 247 | /* Begin PBXProject section */ 248 | 6003F582195388D10070C39A /* Project object */ = { 249 | isa = PBXProject; 250 | attributes = { 251 | CLASSPREFIX = OK; 252 | LastUpgradeCheck = 0720; 253 | ORGANIZATIONNAME = Draveness; 254 | TargetAttributes = { 255 | 6003F5AD195388D20070C39A = { 256 | TestTargetID = 6003F589195388D20070C39A; 257 | }; 258 | }; 259 | }; 260 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "OKObserver" */; 261 | compatibilityVersion = "Xcode 3.2"; 262 | developmentRegion = English; 263 | hasScannedForEncodings = 0; 264 | knownRegions = ( 265 | en, 266 | Base, 267 | ); 268 | mainGroup = 6003F581195388D10070C39A; 269 | productRefGroup = 6003F58B195388D20070C39A /* Products */; 270 | projectDirPath = ""; 271 | projectRoot = ""; 272 | targets = ( 273 | 6003F589195388D20070C39A /* OKObserver_Example */, 274 | 6003F5AD195388D20070C39A /* OKObserver_Tests */, 275 | ); 276 | }; 277 | /* End PBXProject section */ 278 | 279 | /* Begin PBXResourcesBuildPhase section */ 280 | 6003F588195388D20070C39A /* Resources */ = { 281 | isa = PBXResourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */, 285 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, 286 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, 287 | ); 288 | runOnlyForDeploymentPostprocessing = 0; 289 | }; 290 | 6003F5AC195388D20070C39A /* Resources */ = { 291 | isa = PBXResourcesBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | /* End PBXResourcesBuildPhase section */ 299 | 300 | /* Begin PBXShellScriptBuildPhase section */ 301 | 8DE1F124571246FA8BA9D762 /* 📦 Embed Pods Frameworks */ = { 302 | isa = PBXShellScriptBuildPhase; 303 | buildActionMask = 2147483647; 304 | files = ( 305 | ); 306 | inputPaths = ( 307 | ); 308 | name = "📦 Embed Pods Frameworks"; 309 | outputPaths = ( 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | shellPath = /bin/sh; 313 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-OKObserver_Tests/Pods-OKObserver_Tests-frameworks.sh\"\n"; 314 | showEnvVarsInLog = 0; 315 | }; 316 | A749340159E4B39BE4484653 /* 📦 Copy Pods Resources */ = { 317 | isa = PBXShellScriptBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | ); 321 | inputPaths = ( 322 | ); 323 | name = "📦 Copy Pods Resources"; 324 | outputPaths = ( 325 | ); 326 | runOnlyForDeploymentPostprocessing = 0; 327 | shellPath = /bin/sh; 328 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-OKObserver_Tests/Pods-OKObserver_Tests-resources.sh\"\n"; 329 | showEnvVarsInLog = 0; 330 | }; 331 | D45D64C6D394258712301EB8 /* 📦 Check Pods Manifest.lock */ = { 332 | isa = PBXShellScriptBuildPhase; 333 | buildActionMask = 2147483647; 334 | files = ( 335 | ); 336 | inputPaths = ( 337 | ); 338 | name = "📦 Check Pods Manifest.lock"; 339 | outputPaths = ( 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | shellPath = /bin/sh; 343 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 344 | showEnvVarsInLog = 0; 345 | }; 346 | D4CB71AF72288900DD53DC58 /* 📦 Copy Pods Resources */ = { 347 | isa = PBXShellScriptBuildPhase; 348 | buildActionMask = 2147483647; 349 | files = ( 350 | ); 351 | inputPaths = ( 352 | ); 353 | name = "📦 Copy Pods Resources"; 354 | outputPaths = ( 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | shellPath = /bin/sh; 358 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-OKObserver_Example/Pods-OKObserver_Example-resources.sh\"\n"; 359 | showEnvVarsInLog = 0; 360 | }; 361 | E5809A73AFFD5DC9C8CC982F /* 📦 Embed Pods Frameworks */ = { 362 | isa = PBXShellScriptBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | ); 366 | inputPaths = ( 367 | ); 368 | name = "📦 Embed Pods Frameworks"; 369 | outputPaths = ( 370 | ); 371 | runOnlyForDeploymentPostprocessing = 0; 372 | shellPath = /bin/sh; 373 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-OKObserver_Example/Pods-OKObserver_Example-frameworks.sh\"\n"; 374 | showEnvVarsInLog = 0; 375 | }; 376 | EA867EEE6668783E85C3AA92 /* 📦 Check Pods Manifest.lock */ = { 377 | isa = PBXShellScriptBuildPhase; 378 | buildActionMask = 2147483647; 379 | files = ( 380 | ); 381 | inputPaths = ( 382 | ); 383 | name = "📦 Check Pods Manifest.lock"; 384 | outputPaths = ( 385 | ); 386 | runOnlyForDeploymentPostprocessing = 0; 387 | shellPath = /bin/sh; 388 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 389 | showEnvVarsInLog = 0; 390 | }; 391 | /* End PBXShellScriptBuildPhase section */ 392 | 393 | /* Begin PBXSourcesBuildPhase section */ 394 | 6003F586195388D20070C39A /* Sources */ = { 395 | isa = PBXSourcesBuildPhase; 396 | buildActionMask = 2147483647; 397 | files = ( 398 | 728E05331CECB0C70043EE32 /* XXObject.m in Sources */, 399 | 6003F59E195388D20070C39A /* OKAppDelegate.m in Sources */, 400 | 6003F5A7195388D20070C39A /* OKViewController.m in Sources */, 401 | 6003F59A195388D20070C39A /* main.m in Sources */, 402 | ); 403 | runOnlyForDeploymentPostprocessing = 0; 404 | }; 405 | 6003F5AA195388D20070C39A /* Sources */ = { 406 | isa = PBXSourcesBuildPhase; 407 | buildActionMask = 2147483647; 408 | files = ( 409 | 6003F5BC195388D20070C39A /* Tests.m in Sources */, 410 | ); 411 | runOnlyForDeploymentPostprocessing = 0; 412 | }; 413 | /* End PBXSourcesBuildPhase section */ 414 | 415 | /* Begin PBXTargetDependency section */ 416 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { 417 | isa = PBXTargetDependency; 418 | target = 6003F589195388D20070C39A /* OKObserver_Example */; 419 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; 420 | }; 421 | /* End PBXTargetDependency section */ 422 | 423 | /* Begin PBXVariantGroup section */ 424 | 6003F596195388D20070C39A /* InfoPlist.strings */ = { 425 | isa = PBXVariantGroup; 426 | children = ( 427 | 6003F597195388D20070C39A /* en */, 428 | ); 429 | name = InfoPlist.strings; 430 | sourceTree = ""; 431 | }; 432 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { 433 | isa = PBXVariantGroup; 434 | children = ( 435 | 6003F5B9195388D20070C39A /* en */, 436 | ); 437 | name = InfoPlist.strings; 438 | sourceTree = ""; 439 | }; 440 | /* End PBXVariantGroup section */ 441 | 442 | /* Begin XCBuildConfiguration section */ 443 | 6003F5BD195388D20070C39A /* Debug */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | ALWAYS_SEARCH_USER_PATHS = NO; 447 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 448 | CLANG_CXX_LIBRARY = "libc++"; 449 | CLANG_ENABLE_MODULES = YES; 450 | CLANG_ENABLE_OBJC_ARC = YES; 451 | CLANG_WARN_BOOL_CONVERSION = YES; 452 | CLANG_WARN_CONSTANT_CONVERSION = YES; 453 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 454 | CLANG_WARN_EMPTY_BODY = YES; 455 | CLANG_WARN_ENUM_CONVERSION = YES; 456 | CLANG_WARN_INT_CONVERSION = YES; 457 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 458 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 460 | COPY_PHASE_STRIP = NO; 461 | ENABLE_TESTABILITY = YES; 462 | GCC_C_LANGUAGE_STANDARD = gnu99; 463 | GCC_DYNAMIC_NO_PIC = NO; 464 | GCC_OPTIMIZATION_LEVEL = 0; 465 | GCC_PREPROCESSOR_DEFINITIONS = ( 466 | "DEBUG=1", 467 | "$(inherited)", 468 | ); 469 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 470 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 471 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 472 | GCC_WARN_UNDECLARED_SELECTOR = YES; 473 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 474 | GCC_WARN_UNUSED_FUNCTION = YES; 475 | GCC_WARN_UNUSED_VARIABLE = YES; 476 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 477 | ONLY_ACTIVE_ARCH = YES; 478 | SDKROOT = iphoneos; 479 | TARGETED_DEVICE_FAMILY = "1,2"; 480 | }; 481 | name = Debug; 482 | }; 483 | 6003F5BE195388D20070C39A /* Release */ = { 484 | isa = XCBuildConfiguration; 485 | buildSettings = { 486 | ALWAYS_SEARCH_USER_PATHS = NO; 487 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 488 | CLANG_CXX_LIBRARY = "libc++"; 489 | CLANG_ENABLE_MODULES = YES; 490 | CLANG_ENABLE_OBJC_ARC = YES; 491 | CLANG_WARN_BOOL_CONVERSION = YES; 492 | CLANG_WARN_CONSTANT_CONVERSION = YES; 493 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 494 | CLANG_WARN_EMPTY_BODY = YES; 495 | CLANG_WARN_ENUM_CONVERSION = YES; 496 | CLANG_WARN_INT_CONVERSION = YES; 497 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 498 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 499 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 500 | COPY_PHASE_STRIP = YES; 501 | ENABLE_NS_ASSERTIONS = NO; 502 | GCC_C_LANGUAGE_STANDARD = gnu99; 503 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 504 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 505 | GCC_WARN_UNDECLARED_SELECTOR = YES; 506 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 507 | GCC_WARN_UNUSED_FUNCTION = YES; 508 | GCC_WARN_UNUSED_VARIABLE = YES; 509 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 510 | SDKROOT = iphoneos; 511 | TARGETED_DEVICE_FAMILY = "1,2"; 512 | VALIDATE_PRODUCT = YES; 513 | }; 514 | name = Release; 515 | }; 516 | 6003F5C0195388D20070C39A /* Debug */ = { 517 | isa = XCBuildConfiguration; 518 | baseConfigurationReference = 9144D3D6B9448411B7751F2F /* Pods-OKObserver_Example.debug.xcconfig */; 519 | buildSettings = { 520 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 521 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 522 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 523 | GCC_PREFIX_HEADER = "OKObserver/OKObserver-Prefix.pch"; 524 | INFOPLIST_FILE = "OKObserver/OKObserver-Info.plist"; 525 | MODULE_NAME = ExampleApp; 526 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 527 | PRODUCT_NAME = "$(TARGET_NAME)"; 528 | WRAPPER_EXTENSION = app; 529 | }; 530 | name = Debug; 531 | }; 532 | 6003F5C1195388D20070C39A /* Release */ = { 533 | isa = XCBuildConfiguration; 534 | baseConfigurationReference = 87EF675D222DCD0F9CB90FCD /* Pods-OKObserver_Example.release.xcconfig */; 535 | buildSettings = { 536 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 537 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 538 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 539 | GCC_PREFIX_HEADER = "OKObserver/OKObserver-Prefix.pch"; 540 | INFOPLIST_FILE = "OKObserver/OKObserver-Info.plist"; 541 | MODULE_NAME = ExampleApp; 542 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 543 | PRODUCT_NAME = "$(TARGET_NAME)"; 544 | WRAPPER_EXTENSION = app; 545 | }; 546 | name = Release; 547 | }; 548 | 6003F5C3195388D20070C39A /* Debug */ = { 549 | isa = XCBuildConfiguration; 550 | baseConfigurationReference = 2F0D94B829998A6D0DD0AAAA /* Pods-OKObserver_Tests.debug.xcconfig */; 551 | buildSettings = { 552 | BUNDLE_LOADER = "$(TEST_HOST)"; 553 | FRAMEWORK_SEARCH_PATHS = ( 554 | "$(SDKROOT)/Developer/Library/Frameworks", 555 | "$(inherited)", 556 | "$(DEVELOPER_FRAMEWORKS_DIR)", 557 | ); 558 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 559 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 560 | GCC_PREPROCESSOR_DEFINITIONS = ( 561 | "DEBUG=1", 562 | "$(inherited)", 563 | ); 564 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 565 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 566 | PRODUCT_NAME = "$(TARGET_NAME)"; 567 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OKObserver_Example.app/OKObserver_Example"; 568 | WRAPPER_EXTENSION = xctest; 569 | }; 570 | name = Debug; 571 | }; 572 | 6003F5C4195388D20070C39A /* Release */ = { 573 | isa = XCBuildConfiguration; 574 | baseConfigurationReference = 3A0448665801C104A9EA6720 /* Pods-OKObserver_Tests.release.xcconfig */; 575 | buildSettings = { 576 | BUNDLE_LOADER = "$(TEST_HOST)"; 577 | FRAMEWORK_SEARCH_PATHS = ( 578 | "$(SDKROOT)/Developer/Library/Frameworks", 579 | "$(inherited)", 580 | "$(DEVELOPER_FRAMEWORKS_DIR)", 581 | ); 582 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 583 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 584 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 585 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 586 | PRODUCT_NAME = "$(TARGET_NAME)"; 587 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OKObserver_Example.app/OKObserver_Example"; 588 | WRAPPER_EXTENSION = xctest; 589 | }; 590 | name = Release; 591 | }; 592 | /* End XCBuildConfiguration section */ 593 | 594 | /* Begin XCConfigurationList section */ 595 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "OKObserver" */ = { 596 | isa = XCConfigurationList; 597 | buildConfigurations = ( 598 | 6003F5BD195388D20070C39A /* Debug */, 599 | 6003F5BE195388D20070C39A /* Release */, 600 | ); 601 | defaultConfigurationIsVisible = 0; 602 | defaultConfigurationName = Release; 603 | }; 604 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "OKObserver_Example" */ = { 605 | isa = XCConfigurationList; 606 | buildConfigurations = ( 607 | 6003F5C0195388D20070C39A /* Debug */, 608 | 6003F5C1195388D20070C39A /* Release */, 609 | ); 610 | defaultConfigurationIsVisible = 0; 611 | defaultConfigurationName = Release; 612 | }; 613 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "OKObserver_Tests" */ = { 614 | isa = XCConfigurationList; 615 | buildConfigurations = ( 616 | 6003F5C3195388D20070C39A /* Debug */, 617 | 6003F5C4195388D20070C39A /* Release */, 618 | ); 619 | defaultConfigurationIsVisible = 0; 620 | defaultConfigurationName = Release; 621 | }; 622 | /* End XCConfigurationList section */ 623 | }; 624 | rootObject = 6003F582195388D10070C39A /* Project object */; 625 | } 626 | -------------------------------------------------------------------------------- /OKObserver/Classes/metamacros.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Macros for metaprogramming 3 | * ExtendedC 4 | * 5 | * Copyright (C) 2012 Justin Spahr-Summers 6 | * Released under the MIT license 7 | */ 8 | 9 | #ifndef EXTC_METAMACROS_H 10 | #define EXTC_METAMACROS_H 11 | 12 | 13 | /** 14 | * Executes one or more expressions (which may have a void type, such as a call 15 | * to a function that returns no value) and always returns true. 16 | */ 17 | #define metamacro_exprify(...) \ 18 | ((__VA_ARGS__), true) 19 | 20 | /** 21 | * Returns a string representation of VALUE after full macro expansion. 22 | */ 23 | #define metamacro_stringify(VALUE) \ 24 | metamacro_stringify_(VALUE) 25 | 26 | /** 27 | * Returns A and B concatenated after full macro expansion. 28 | */ 29 | #define metamacro_concat(A, B) \ 30 | metamacro_concat_(A, B) 31 | 32 | /** 33 | * Returns the Nth variadic argument (starting from zero). At least 34 | * N + 1 variadic arguments must be given. N must be between zero and twenty, 35 | * inclusive. 36 | */ 37 | #define metamacro_at(N, ...) \ 38 | metamacro_concat(metamacro_at, N)(__VA_ARGS__) 39 | 40 | /** 41 | * Returns the number of arguments (up to twenty) provided to the macro. At 42 | * least one argument must be provided. 43 | * 44 | * Inspired by P99: http://p99.gforge.inria.fr 45 | */ 46 | #define metamacro_argcount(...) \ 47 | metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) 48 | 49 | /** 50 | * Identical to #metamacro_foreach_cxt, except that no CONTEXT argument is 51 | * given. Only the index and current argument will thus be passed to MACRO. 52 | */ 53 | #define metamacro_foreach(MACRO, SEP, ...) \ 54 | metamacro_foreach_cxt(metamacro_foreach_iter, SEP, MACRO, __VA_ARGS__) 55 | 56 | /** 57 | * For each consecutive variadic argument (up to twenty), MACRO is passed the 58 | * zero-based index of the current argument, CONTEXT, and then the argument 59 | * itself. The results of adjoining invocations of MACRO are then separated by 60 | * SEP. 61 | * 62 | * Inspired by P99: http://p99.gforge.inria.fr 63 | */ 64 | #define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \ 65 | metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__) 66 | 67 | /** 68 | * Identical to #metamacro_foreach_cxt. This can be used when the former would 69 | * fail due to recursive macro expansion. 70 | */ 71 | #define metamacro_foreach_cxt_recursive(MACRO, SEP, CONTEXT, ...) \ 72 | metamacro_concat(metamacro_foreach_cxt_recursive, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__) 73 | 74 | /** 75 | * In consecutive order, appends each variadic argument (up to twenty) onto 76 | * BASE. The resulting concatenations are then separated by SEP. 77 | * 78 | * This is primarily useful to manipulate a list of macro invocations into instead 79 | * invoking a different, possibly related macro. 80 | */ 81 | #define metamacro_foreach_concat(BASE, SEP, ...) \ 82 | metamacro_foreach_cxt(metamacro_foreach_concat_iter, SEP, BASE, __VA_ARGS__) 83 | 84 | /** 85 | * Iterates COUNT times, each time invoking MACRO with the current index 86 | * (starting at zero) and CONTEXT. The results of adjoining invocations of MACRO 87 | * are then separated by SEP. 88 | * 89 | * COUNT must be an integer between zero and twenty, inclusive. 90 | */ 91 | #define metamacro_for_cxt(COUNT, MACRO, SEP, CONTEXT) \ 92 | metamacro_concat(metamacro_for_cxt, COUNT)(MACRO, SEP, CONTEXT) 93 | 94 | /** 95 | * Returns the first argument given. At least one argument must be provided. 96 | * 97 | * This is useful when implementing a variadic macro, where you may have only 98 | * one variadic argument, but no way to retrieve it (for example, because \c ... 99 | * always needs to match at least one argument). 100 | * 101 | * @code 102 | 103 | #define varmacro(...) \ 104 | metamacro_head(__VA_ARGS__) 105 | 106 | * @endcode 107 | */ 108 | #define metamacro_head(...) \ 109 | metamacro_head_(__VA_ARGS__, 0) 110 | 111 | /** 112 | * Returns every argument except the first. At least two arguments must be 113 | * provided. 114 | */ 115 | #define metamacro_tail(...) \ 116 | metamacro_tail_(__VA_ARGS__) 117 | 118 | /** 119 | * Returns the first N (up to twenty) variadic arguments as a new argument list. 120 | * At least N variadic arguments must be provided. 121 | */ 122 | #define metamacro_take(N, ...) \ 123 | metamacro_concat(metamacro_take, N)(__VA_ARGS__) 124 | 125 | /** 126 | * Removes the first N (up to twenty) variadic arguments from the given argument 127 | * list. At least N variadic arguments must be provided. 128 | */ 129 | #define metamacro_drop(N, ...) \ 130 | metamacro_concat(metamacro_drop, N)(__VA_ARGS__) 131 | 132 | /** 133 | * Decrements VAL, which must be a number between zero and twenty, inclusive. 134 | * 135 | * This is primarily useful when dealing with indexes and counts in 136 | * metaprogramming. 137 | */ 138 | #define metamacro_dec(VAL) \ 139 | metamacro_at(VAL, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) 140 | 141 | /** 142 | * Increments VAL, which must be a number between zero and twenty, inclusive. 143 | * 144 | * This is primarily useful when dealing with indexes and counts in 145 | * metaprogramming. 146 | */ 147 | #define metamacro_inc(VAL) \ 148 | metamacro_at(VAL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) 149 | 150 | /** 151 | * If A is equal to B, the next argument list is expanded; otherwise, the 152 | * argument list after that is expanded. A and B must be numbers between zero 153 | * and twenty, inclusive. Additionally, B must be greater than or equal to A. 154 | * 155 | * @code 156 | 157 | // expands to true 158 | metamacro_if_eq(0, 0)(true)(false) 159 | 160 | // expands to false 161 | metamacro_if_eq(0, 1)(true)(false) 162 | 163 | * @endcode 164 | * 165 | * This is primarily useful when dealing with indexes and counts in 166 | * metaprogramming. 167 | */ 168 | #define metamacro_if_eq(A, B) \ 169 | metamacro_concat(metamacro_if_eq, A)(B) 170 | 171 | /** 172 | * Identical to #metamacro_if_eq. This can be used when the former would fail 173 | * due to recursive macro expansion. 174 | */ 175 | #define metamacro_if_eq_recursive(A, B) \ 176 | metamacro_concat(metamacro_if_eq_recursive, A)(B) 177 | 178 | /** 179 | * Returns 1 if N is an even number, or 0 otherwise. N must be between zero and 180 | * twenty, inclusive. 181 | * 182 | * For the purposes of this test, zero is considered even. 183 | */ 184 | #define metamacro_is_even(N) \ 185 | metamacro_at(N, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1) 186 | 187 | /** 188 | * Returns the logical NOT of B, which must be the number zero or one. 189 | */ 190 | #define metamacro_not(B) \ 191 | metamacro_at(B, 1, 0) 192 | 193 | // IMPLEMENTATION DETAILS FOLLOW! 194 | // Do not write code that depends on anything below this line. 195 | #define metamacro_stringify_(VALUE) # VALUE 196 | #define metamacro_concat_(A, B) A ## B 197 | #define metamacro_foreach_iter(INDEX, MACRO, ARG) MACRO(INDEX, ARG) 198 | #define metamacro_head_(FIRST, ...) FIRST 199 | #define metamacro_tail_(FIRST, ...) __VA_ARGS__ 200 | #define metamacro_consume_(...) 201 | #define metamacro_expand_(...) __VA_ARGS__ 202 | 203 | // implemented from scratch so that metamacro_concat() doesn't end up nesting 204 | #define metamacro_foreach_concat_iter(INDEX, BASE, ARG) metamacro_foreach_concat_iter_(BASE, ARG) 205 | #define metamacro_foreach_concat_iter_(BASE, ARG) BASE ## ARG 206 | 207 | // metamacro_at expansions 208 | #define metamacro_at0(...) metamacro_head(__VA_ARGS__) 209 | #define metamacro_at1(_0, ...) metamacro_head(__VA_ARGS__) 210 | #define metamacro_at2(_0, _1, ...) metamacro_head(__VA_ARGS__) 211 | #define metamacro_at3(_0, _1, _2, ...) metamacro_head(__VA_ARGS__) 212 | #define metamacro_at4(_0, _1, _2, _3, ...) metamacro_head(__VA_ARGS__) 213 | #define metamacro_at5(_0, _1, _2, _3, _4, ...) metamacro_head(__VA_ARGS__) 214 | #define metamacro_at6(_0, _1, _2, _3, _4, _5, ...) metamacro_head(__VA_ARGS__) 215 | #define metamacro_at7(_0, _1, _2, _3, _4, _5, _6, ...) metamacro_head(__VA_ARGS__) 216 | #define metamacro_at8(_0, _1, _2, _3, _4, _5, _6, _7, ...) metamacro_head(__VA_ARGS__) 217 | #define metamacro_at9(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) metamacro_head(__VA_ARGS__) 218 | #define metamacro_at10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) metamacro_head(__VA_ARGS__) 219 | #define metamacro_at11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) metamacro_head(__VA_ARGS__) 220 | #define metamacro_at12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, ...) metamacro_head(__VA_ARGS__) 221 | #define metamacro_at13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) metamacro_head(__VA_ARGS__) 222 | #define metamacro_at14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) metamacro_head(__VA_ARGS__) 223 | #define metamacro_at15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) metamacro_head(__VA_ARGS__) 224 | #define metamacro_at16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) metamacro_head(__VA_ARGS__) 225 | #define metamacro_at17(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) metamacro_head(__VA_ARGS__) 226 | #define metamacro_at18(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, ...) metamacro_head(__VA_ARGS__) 227 | #define metamacro_at19(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, ...) metamacro_head(__VA_ARGS__) 228 | #define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__) 229 | 230 | // metamacro_foreach_cxt expansions 231 | #define metamacro_foreach_cxt0(MACRO, SEP, CONTEXT) 232 | #define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0) 233 | 234 | #define metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \ 235 | metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) \ 236 | SEP \ 237 | MACRO(1, CONTEXT, _1) 238 | 239 | #define metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 240 | metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \ 241 | SEP \ 242 | MACRO(2, CONTEXT, _2) 243 | 244 | #define metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 245 | metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 246 | SEP \ 247 | MACRO(3, CONTEXT, _3) 248 | 249 | #define metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 250 | metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 251 | SEP \ 252 | MACRO(4, CONTEXT, _4) 253 | 254 | #define metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 255 | metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 256 | SEP \ 257 | MACRO(5, CONTEXT, _5) 258 | 259 | #define metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 260 | metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 261 | SEP \ 262 | MACRO(6, CONTEXT, _6) 263 | 264 | #define metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 265 | metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 266 | SEP \ 267 | MACRO(7, CONTEXT, _7) 268 | 269 | #define metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 270 | metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 271 | SEP \ 272 | MACRO(8, CONTEXT, _8) 273 | 274 | #define metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 275 | metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 276 | SEP \ 277 | MACRO(9, CONTEXT, _9) 278 | 279 | #define metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 280 | metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 281 | SEP \ 282 | MACRO(10, CONTEXT, _10) 283 | 284 | #define metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 285 | metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 286 | SEP \ 287 | MACRO(11, CONTEXT, _11) 288 | 289 | #define metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 290 | metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 291 | SEP \ 292 | MACRO(12, CONTEXT, _12) 293 | 294 | #define metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 295 | metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 296 | SEP \ 297 | MACRO(13, CONTEXT, _13) 298 | 299 | #define metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 300 | metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 301 | SEP \ 302 | MACRO(14, CONTEXT, _14) 303 | 304 | #define metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 305 | metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 306 | SEP \ 307 | MACRO(15, CONTEXT, _15) 308 | 309 | #define metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 310 | metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 311 | SEP \ 312 | MACRO(16, CONTEXT, _16) 313 | 314 | #define metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 315 | metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 316 | SEP \ 317 | MACRO(17, CONTEXT, _17) 318 | 319 | #define metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 320 | metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 321 | SEP \ 322 | MACRO(18, CONTEXT, _18) 323 | 324 | #define metamacro_foreach_cxt20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \ 325 | metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 326 | SEP \ 327 | MACRO(19, CONTEXT, _19) 328 | 329 | // metamacro_foreach_cxt_recursive expansions 330 | #define metamacro_foreach_cxt_recursive0(MACRO, SEP, CONTEXT) 331 | #define metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0) 332 | 333 | #define metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \ 334 | metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) \ 335 | SEP \ 336 | MACRO(1, CONTEXT, _1) 337 | 338 | #define metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 339 | metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \ 340 | SEP \ 341 | MACRO(2, CONTEXT, _2) 342 | 343 | #define metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 344 | metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 345 | SEP \ 346 | MACRO(3, CONTEXT, _3) 347 | 348 | #define metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 349 | metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 350 | SEP \ 351 | MACRO(4, CONTEXT, _4) 352 | 353 | #define metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 354 | metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 355 | SEP \ 356 | MACRO(5, CONTEXT, _5) 357 | 358 | #define metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 359 | metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 360 | SEP \ 361 | MACRO(6, CONTEXT, _6) 362 | 363 | #define metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 364 | metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 365 | SEP \ 366 | MACRO(7, CONTEXT, _7) 367 | 368 | #define metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 369 | metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 370 | SEP \ 371 | MACRO(8, CONTEXT, _8) 372 | 373 | #define metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 374 | metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 375 | SEP \ 376 | MACRO(9, CONTEXT, _9) 377 | 378 | #define metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 379 | metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 380 | SEP \ 381 | MACRO(10, CONTEXT, _10) 382 | 383 | #define metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 384 | metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 385 | SEP \ 386 | MACRO(11, CONTEXT, _11) 387 | 388 | #define metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 389 | metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 390 | SEP \ 391 | MACRO(12, CONTEXT, _12) 392 | 393 | #define metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 394 | metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 395 | SEP \ 396 | MACRO(13, CONTEXT, _13) 397 | 398 | #define metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 399 | metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 400 | SEP \ 401 | MACRO(14, CONTEXT, _14) 402 | 403 | #define metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 404 | metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 405 | SEP \ 406 | MACRO(15, CONTEXT, _15) 407 | 408 | #define metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 409 | metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 410 | SEP \ 411 | MACRO(16, CONTEXT, _16) 412 | 413 | #define metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 414 | metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 415 | SEP \ 416 | MACRO(17, CONTEXT, _17) 417 | 418 | #define metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 419 | metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 420 | SEP \ 421 | MACRO(18, CONTEXT, _18) 422 | 423 | #define metamacro_foreach_cxt_recursive20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \ 424 | metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 425 | SEP \ 426 | MACRO(19, CONTEXT, _19) 427 | 428 | // metamacro_for_cxt expansions 429 | #define metamacro_for_cxt0(MACRO, SEP, CONTEXT) 430 | #define metamacro_for_cxt1(MACRO, SEP, CONTEXT) MACRO(0, CONTEXT) 431 | 432 | #define metamacro_for_cxt2(MACRO, SEP, CONTEXT) \ 433 | metamacro_for_cxt1(MACRO, SEP, CONTEXT) \ 434 | SEP \ 435 | MACRO(1, CONTEXT) 436 | 437 | #define metamacro_for_cxt3(MACRO, SEP, CONTEXT) \ 438 | metamacro_for_cxt2(MACRO, SEP, CONTEXT) \ 439 | SEP \ 440 | MACRO(2, CONTEXT) 441 | 442 | #define metamacro_for_cxt4(MACRO, SEP, CONTEXT) \ 443 | metamacro_for_cxt3(MACRO, SEP, CONTEXT) \ 444 | SEP \ 445 | MACRO(3, CONTEXT) 446 | 447 | #define metamacro_for_cxt5(MACRO, SEP, CONTEXT) \ 448 | metamacro_for_cxt4(MACRO, SEP, CONTEXT) \ 449 | SEP \ 450 | MACRO(4, CONTEXT) 451 | 452 | #define metamacro_for_cxt6(MACRO, SEP, CONTEXT) \ 453 | metamacro_for_cxt5(MACRO, SEP, CONTEXT) \ 454 | SEP \ 455 | MACRO(5, CONTEXT) 456 | 457 | #define metamacro_for_cxt7(MACRO, SEP, CONTEXT) \ 458 | metamacro_for_cxt6(MACRO, SEP, CONTEXT) \ 459 | SEP \ 460 | MACRO(6, CONTEXT) 461 | 462 | #define metamacro_for_cxt8(MACRO, SEP, CONTEXT) \ 463 | metamacro_for_cxt7(MACRO, SEP, CONTEXT) \ 464 | SEP \ 465 | MACRO(7, CONTEXT) 466 | 467 | #define metamacro_for_cxt9(MACRO, SEP, CONTEXT) \ 468 | metamacro_for_cxt8(MACRO, SEP, CONTEXT) \ 469 | SEP \ 470 | MACRO(8, CONTEXT) 471 | 472 | #define metamacro_for_cxt10(MACRO, SEP, CONTEXT) \ 473 | metamacro_for_cxt9(MACRO, SEP, CONTEXT) \ 474 | SEP \ 475 | MACRO(9, CONTEXT) 476 | 477 | #define metamacro_for_cxt11(MACRO, SEP, CONTEXT) \ 478 | metamacro_for_cxt10(MACRO, SEP, CONTEXT) \ 479 | SEP \ 480 | MACRO(10, CONTEXT) 481 | 482 | #define metamacro_for_cxt12(MACRO, SEP, CONTEXT) \ 483 | metamacro_for_cxt11(MACRO, SEP, CONTEXT) \ 484 | SEP \ 485 | MACRO(11, CONTEXT) 486 | 487 | #define metamacro_for_cxt13(MACRO, SEP, CONTEXT) \ 488 | metamacro_for_cxt12(MACRO, SEP, CONTEXT) \ 489 | SEP \ 490 | MACRO(12, CONTEXT) 491 | 492 | #define metamacro_for_cxt14(MACRO, SEP, CONTEXT) \ 493 | metamacro_for_cxt13(MACRO, SEP, CONTEXT) \ 494 | SEP \ 495 | MACRO(13, CONTEXT) 496 | 497 | #define metamacro_for_cxt15(MACRO, SEP, CONTEXT) \ 498 | metamacro_for_cxt14(MACRO, SEP, CONTEXT) \ 499 | SEP \ 500 | MACRO(14, CONTEXT) 501 | 502 | #define metamacro_for_cxt16(MACRO, SEP, CONTEXT) \ 503 | metamacro_for_cxt15(MACRO, SEP, CONTEXT) \ 504 | SEP \ 505 | MACRO(15, CONTEXT) 506 | 507 | #define metamacro_for_cxt17(MACRO, SEP, CONTEXT) \ 508 | metamacro_for_cxt16(MACRO, SEP, CONTEXT) \ 509 | SEP \ 510 | MACRO(16, CONTEXT) 511 | 512 | #define metamacro_for_cxt18(MACRO, SEP, CONTEXT) \ 513 | metamacro_for_cxt17(MACRO, SEP, CONTEXT) \ 514 | SEP \ 515 | MACRO(17, CONTEXT) 516 | 517 | #define metamacro_for_cxt19(MACRO, SEP, CONTEXT) \ 518 | metamacro_for_cxt18(MACRO, SEP, CONTEXT) \ 519 | SEP \ 520 | MACRO(18, CONTEXT) 521 | 522 | #define metamacro_for_cxt20(MACRO, SEP, CONTEXT) \ 523 | metamacro_for_cxt19(MACRO, SEP, CONTEXT) \ 524 | SEP \ 525 | MACRO(19, CONTEXT) 526 | 527 | // metamacro_if_eq expansions 528 | #define metamacro_if_eq0(VALUE) \ 529 | metamacro_concat(metamacro_if_eq0_, VALUE) 530 | 531 | #define metamacro_if_eq0_0(...) __VA_ARGS__ metamacro_consume_ 532 | #define metamacro_if_eq0_1(...) metamacro_expand_ 533 | #define metamacro_if_eq0_2(...) metamacro_expand_ 534 | #define metamacro_if_eq0_3(...) metamacro_expand_ 535 | #define metamacro_if_eq0_4(...) metamacro_expand_ 536 | #define metamacro_if_eq0_5(...) metamacro_expand_ 537 | #define metamacro_if_eq0_6(...) metamacro_expand_ 538 | #define metamacro_if_eq0_7(...) metamacro_expand_ 539 | #define metamacro_if_eq0_8(...) metamacro_expand_ 540 | #define metamacro_if_eq0_9(...) metamacro_expand_ 541 | #define metamacro_if_eq0_10(...) metamacro_expand_ 542 | #define metamacro_if_eq0_11(...) metamacro_expand_ 543 | #define metamacro_if_eq0_12(...) metamacro_expand_ 544 | #define metamacro_if_eq0_13(...) metamacro_expand_ 545 | #define metamacro_if_eq0_14(...) metamacro_expand_ 546 | #define metamacro_if_eq0_15(...) metamacro_expand_ 547 | #define metamacro_if_eq0_16(...) metamacro_expand_ 548 | #define metamacro_if_eq0_17(...) metamacro_expand_ 549 | #define metamacro_if_eq0_18(...) metamacro_expand_ 550 | #define metamacro_if_eq0_19(...) metamacro_expand_ 551 | #define metamacro_if_eq0_20(...) metamacro_expand_ 552 | 553 | #define metamacro_if_eq1(VALUE) metamacro_if_eq0(metamacro_dec(VALUE)) 554 | #define metamacro_if_eq2(VALUE) metamacro_if_eq1(metamacro_dec(VALUE)) 555 | #define metamacro_if_eq3(VALUE) metamacro_if_eq2(metamacro_dec(VALUE)) 556 | #define metamacro_if_eq4(VALUE) metamacro_if_eq3(metamacro_dec(VALUE)) 557 | #define metamacro_if_eq5(VALUE) metamacro_if_eq4(metamacro_dec(VALUE)) 558 | #define metamacro_if_eq6(VALUE) metamacro_if_eq5(metamacro_dec(VALUE)) 559 | #define metamacro_if_eq7(VALUE) metamacro_if_eq6(metamacro_dec(VALUE)) 560 | #define metamacro_if_eq8(VALUE) metamacro_if_eq7(metamacro_dec(VALUE)) 561 | #define metamacro_if_eq9(VALUE) metamacro_if_eq8(metamacro_dec(VALUE)) 562 | #define metamacro_if_eq10(VALUE) metamacro_if_eq9(metamacro_dec(VALUE)) 563 | #define metamacro_if_eq11(VALUE) metamacro_if_eq10(metamacro_dec(VALUE)) 564 | #define metamacro_if_eq12(VALUE) metamacro_if_eq11(metamacro_dec(VALUE)) 565 | #define metamacro_if_eq13(VALUE) metamacro_if_eq12(metamacro_dec(VALUE)) 566 | #define metamacro_if_eq14(VALUE) metamacro_if_eq13(metamacro_dec(VALUE)) 567 | #define metamacro_if_eq15(VALUE) metamacro_if_eq14(metamacro_dec(VALUE)) 568 | #define metamacro_if_eq16(VALUE) metamacro_if_eq15(metamacro_dec(VALUE)) 569 | #define metamacro_if_eq17(VALUE) metamacro_if_eq16(metamacro_dec(VALUE)) 570 | #define metamacro_if_eq18(VALUE) metamacro_if_eq17(metamacro_dec(VALUE)) 571 | #define metamacro_if_eq19(VALUE) metamacro_if_eq18(metamacro_dec(VALUE)) 572 | #define metamacro_if_eq20(VALUE) metamacro_if_eq19(metamacro_dec(VALUE)) 573 | 574 | // metamacro_if_eq_recursive expansions 575 | #define metamacro_if_eq_recursive0(VALUE) \ 576 | metamacro_concat(metamacro_if_eq_recursive0_, VALUE) 577 | 578 | #define metamacro_if_eq_recursive0_0(...) __VA_ARGS__ metamacro_consume_ 579 | #define metamacro_if_eq_recursive0_1(...) metamacro_expand_ 580 | #define metamacro_if_eq_recursive0_2(...) metamacro_expand_ 581 | #define metamacro_if_eq_recursive0_3(...) metamacro_expand_ 582 | #define metamacro_if_eq_recursive0_4(...) metamacro_expand_ 583 | #define metamacro_if_eq_recursive0_5(...) metamacro_expand_ 584 | #define metamacro_if_eq_recursive0_6(...) metamacro_expand_ 585 | #define metamacro_if_eq_recursive0_7(...) metamacro_expand_ 586 | #define metamacro_if_eq_recursive0_8(...) metamacro_expand_ 587 | #define metamacro_if_eq_recursive0_9(...) metamacro_expand_ 588 | #define metamacro_if_eq_recursive0_10(...) metamacro_expand_ 589 | #define metamacro_if_eq_recursive0_11(...) metamacro_expand_ 590 | #define metamacro_if_eq_recursive0_12(...) metamacro_expand_ 591 | #define metamacro_if_eq_recursive0_13(...) metamacro_expand_ 592 | #define metamacro_if_eq_recursive0_14(...) metamacro_expand_ 593 | #define metamacro_if_eq_recursive0_15(...) metamacro_expand_ 594 | #define metamacro_if_eq_recursive0_16(...) metamacro_expand_ 595 | #define metamacro_if_eq_recursive0_17(...) metamacro_expand_ 596 | #define metamacro_if_eq_recursive0_18(...) metamacro_expand_ 597 | #define metamacro_if_eq_recursive0_19(...) metamacro_expand_ 598 | #define metamacro_if_eq_recursive0_20(...) metamacro_expand_ 599 | 600 | #define metamacro_if_eq_recursive1(VALUE) metamacro_if_eq_recursive0(metamacro_dec(VALUE)) 601 | #define metamacro_if_eq_recursive2(VALUE) metamacro_if_eq_recursive1(metamacro_dec(VALUE)) 602 | #define metamacro_if_eq_recursive3(VALUE) metamacro_if_eq_recursive2(metamacro_dec(VALUE)) 603 | #define metamacro_if_eq_recursive4(VALUE) metamacro_if_eq_recursive3(metamacro_dec(VALUE)) 604 | #define metamacro_if_eq_recursive5(VALUE) metamacro_if_eq_recursive4(metamacro_dec(VALUE)) 605 | #define metamacro_if_eq_recursive6(VALUE) metamacro_if_eq_recursive5(metamacro_dec(VALUE)) 606 | #define metamacro_if_eq_recursive7(VALUE) metamacro_if_eq_recursive6(metamacro_dec(VALUE)) 607 | #define metamacro_if_eq_recursive8(VALUE) metamacro_if_eq_recursive7(metamacro_dec(VALUE)) 608 | #define metamacro_if_eq_recursive9(VALUE) metamacro_if_eq_recursive8(metamacro_dec(VALUE)) 609 | #define metamacro_if_eq_recursive10(VALUE) metamacro_if_eq_recursive9(metamacro_dec(VALUE)) 610 | #define metamacro_if_eq_recursive11(VALUE) metamacro_if_eq_recursive10(metamacro_dec(VALUE)) 611 | #define metamacro_if_eq_recursive12(VALUE) metamacro_if_eq_recursive11(metamacro_dec(VALUE)) 612 | #define metamacro_if_eq_recursive13(VALUE) metamacro_if_eq_recursive12(metamacro_dec(VALUE)) 613 | #define metamacro_if_eq_recursive14(VALUE) metamacro_if_eq_recursive13(metamacro_dec(VALUE)) 614 | #define metamacro_if_eq_recursive15(VALUE) metamacro_if_eq_recursive14(metamacro_dec(VALUE)) 615 | #define metamacro_if_eq_recursive16(VALUE) metamacro_if_eq_recursive15(metamacro_dec(VALUE)) 616 | #define metamacro_if_eq_recursive17(VALUE) metamacro_if_eq_recursive16(metamacro_dec(VALUE)) 617 | #define metamacro_if_eq_recursive18(VALUE) metamacro_if_eq_recursive17(metamacro_dec(VALUE)) 618 | #define metamacro_if_eq_recursive19(VALUE) metamacro_if_eq_recursive18(metamacro_dec(VALUE)) 619 | #define metamacro_if_eq_recursive20(VALUE) metamacro_if_eq_recursive19(metamacro_dec(VALUE)) 620 | 621 | // metamacro_take expansions 622 | #define metamacro_take0(...) 623 | #define metamacro_take1(...) metamacro_head(__VA_ARGS__) 624 | #define metamacro_take2(...) metamacro_head(__VA_ARGS__), metamacro_take1(metamacro_tail(__VA_ARGS__)) 625 | #define metamacro_take3(...) metamacro_head(__VA_ARGS__), metamacro_take2(metamacro_tail(__VA_ARGS__)) 626 | #define metamacro_take4(...) metamacro_head(__VA_ARGS__), metamacro_take3(metamacro_tail(__VA_ARGS__)) 627 | #define metamacro_take5(...) metamacro_head(__VA_ARGS__), metamacro_take4(metamacro_tail(__VA_ARGS__)) 628 | #define metamacro_take6(...) metamacro_head(__VA_ARGS__), metamacro_take5(metamacro_tail(__VA_ARGS__)) 629 | #define metamacro_take7(...) metamacro_head(__VA_ARGS__), metamacro_take6(metamacro_tail(__VA_ARGS__)) 630 | #define metamacro_take8(...) metamacro_head(__VA_ARGS__), metamacro_take7(metamacro_tail(__VA_ARGS__)) 631 | #define metamacro_take9(...) metamacro_head(__VA_ARGS__), metamacro_take8(metamacro_tail(__VA_ARGS__)) 632 | #define metamacro_take10(...) metamacro_head(__VA_ARGS__), metamacro_take9(metamacro_tail(__VA_ARGS__)) 633 | #define metamacro_take11(...) metamacro_head(__VA_ARGS__), metamacro_take10(metamacro_tail(__VA_ARGS__)) 634 | #define metamacro_take12(...) metamacro_head(__VA_ARGS__), metamacro_take11(metamacro_tail(__VA_ARGS__)) 635 | #define metamacro_take13(...) metamacro_head(__VA_ARGS__), metamacro_take12(metamacro_tail(__VA_ARGS__)) 636 | #define metamacro_take14(...) metamacro_head(__VA_ARGS__), metamacro_take13(metamacro_tail(__VA_ARGS__)) 637 | #define metamacro_take15(...) metamacro_head(__VA_ARGS__), metamacro_take14(metamacro_tail(__VA_ARGS__)) 638 | #define metamacro_take16(...) metamacro_head(__VA_ARGS__), metamacro_take15(metamacro_tail(__VA_ARGS__)) 639 | #define metamacro_take17(...) metamacro_head(__VA_ARGS__), metamacro_take16(metamacro_tail(__VA_ARGS__)) 640 | #define metamacro_take18(...) metamacro_head(__VA_ARGS__), metamacro_take17(metamacro_tail(__VA_ARGS__)) 641 | #define metamacro_take19(...) metamacro_head(__VA_ARGS__), metamacro_take18(metamacro_tail(__VA_ARGS__)) 642 | #define metamacro_take20(...) metamacro_head(__VA_ARGS__), metamacro_take19(metamacro_tail(__VA_ARGS__)) 643 | 644 | // metamacro_drop expansions 645 | #define metamacro_drop0(...) __VA_ARGS__ 646 | #define metamacro_drop1(...) metamacro_tail(__VA_ARGS__) 647 | #define metamacro_drop2(...) metamacro_drop1(metamacro_tail(__VA_ARGS__)) 648 | #define metamacro_drop3(...) metamacro_drop2(metamacro_tail(__VA_ARGS__)) 649 | #define metamacro_drop4(...) metamacro_drop3(metamacro_tail(__VA_ARGS__)) 650 | #define metamacro_drop5(...) metamacro_drop4(metamacro_tail(__VA_ARGS__)) 651 | #define metamacro_drop6(...) metamacro_drop5(metamacro_tail(__VA_ARGS__)) 652 | #define metamacro_drop7(...) metamacro_drop6(metamacro_tail(__VA_ARGS__)) 653 | #define metamacro_drop8(...) metamacro_drop7(metamacro_tail(__VA_ARGS__)) 654 | #define metamacro_drop9(...) metamacro_drop8(metamacro_tail(__VA_ARGS__)) 655 | #define metamacro_drop10(...) metamacro_drop9(metamacro_tail(__VA_ARGS__)) 656 | #define metamacro_drop11(...) metamacro_drop10(metamacro_tail(__VA_ARGS__)) 657 | #define metamacro_drop12(...) metamacro_drop11(metamacro_tail(__VA_ARGS__)) 658 | #define metamacro_drop13(...) metamacro_drop12(metamacro_tail(__VA_ARGS__)) 659 | #define metamacro_drop14(...) metamacro_drop13(metamacro_tail(__VA_ARGS__)) 660 | #define metamacro_drop15(...) metamacro_drop14(metamacro_tail(__VA_ARGS__)) 661 | #define metamacro_drop16(...) metamacro_drop15(metamacro_tail(__VA_ARGS__)) 662 | #define metamacro_drop17(...) metamacro_drop16(metamacro_tail(__VA_ARGS__)) 663 | #define metamacro_drop18(...) metamacro_drop17(metamacro_tail(__VA_ARGS__)) 664 | #define metamacro_drop19(...) metamacro_drop18(metamacro_tail(__VA_ARGS__)) 665 | #define metamacro_drop20(...) metamacro_drop19(metamacro_tail(__VA_ARGS__)) 666 | 667 | #endif 668 | --------------------------------------------------------------------------------