Repository: bang590/JSPatch
Branch: master
Commit: e80a5573af22
Files: 228
Total size: 1.1 MB
Directory structure:
gitextract_5skxgrji/
├── .gitignore
├── .travis.yml
├── Demo/
│ ├── DribbbleDemo/
│ │ ├── Podfile
│ │ ├── README.md
│ │ ├── dribbbleDemo/
│ │ │ ├── AppDelegate.h
│ │ │ ├── AppDelegate.m
│ │ │ ├── Images.xcassets/
│ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage-1.launchimage/
│ │ │ │ │ └── Contents.json
│ │ │ │ └── LaunchImage.launchimage/
│ │ │ │ └── Contents.json
│ │ │ ├── Info.plist
│ │ │ ├── dribbble/
│ │ │ │ ├── CommonDefine.js
│ │ │ │ ├── DBDataSource.js
│ │ │ │ ├── DBDetailController.js
│ │ │ │ ├── DBDetailViews.js
│ │ │ │ ├── DBTimelineController.js
│ │ │ │ ├── DBTimelineViews.js
│ │ │ │ ├── DBUserController.js
│ │ │ │ ├── DBUserViews.js
│ │ │ │ ├── main.js
│ │ │ │ └── tmpData.js
│ │ │ └── main.m
│ │ ├── dribbbleDemo.xcodeproj/
│ │ │ ├── project.pbxproj
│ │ │ └── project.xcworkspace/
│ │ │ └── contents.xcworkspacedata
│ │ └── dribbbleDemoTests/
│ │ ├── Info.plist
│ │ └── dribbbleDemoTests.m
│ ├── OSXDemo/
│ │ ├── JSPatchOSXDemo/
│ │ │ ├── AppDelegate.h
│ │ │ ├── AppDelegate.m
│ │ │ ├── Base.lproj/
│ │ │ │ └── MainMenu.xib
│ │ │ ├── Info.plist
│ │ │ ├── demo.js
│ │ │ └── main.m
│ │ └── JSPatchOSXDemo.xcodeproj/
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ ├── SwiftDemo/
│ │ ├── SwiftDemo/
│ │ │ ├── AppDelegate.swift
│ │ │ ├── Assets.xcassets/
│ │ │ │ └── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ ├── Base.lproj/
│ │ │ │ ├── LaunchScreen.storyboard
│ │ │ │ └── Main.storyboard
│ │ │ ├── Info.plist
│ │ │ ├── SwiftDemo-Bridging-Header.h
│ │ │ ├── TestObject.swift
│ │ │ ├── ViewController.swift
│ │ │ └── demo.js
│ │ └── SwiftDemo.xcodeproj/
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ ├── iOSDemo/
│ │ ├── JSPatchDemo/
│ │ │ ├── AppDelegate.h
│ │ │ ├── AppDelegate.m
│ │ │ ├── JPViewController.h
│ │ │ ├── JPViewController.m
│ │ │ ├── Supporting Files/
│ │ │ │ ├── Images.xcassets/
│ │ │ │ │ └── AppIcon.appiconset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Info.plist
│ │ │ │ └── main.m
│ │ │ └── demo.js
│ │ ├── JSPatchDemo.xcodeproj/
│ │ │ ├── project.pbxproj
│ │ │ ├── project.xcworkspace/
│ │ │ │ └── contents.xcworkspacedata
│ │ │ └── xcshareddata/
│ │ │ └── xcschemes/
│ │ │ └── JSPatchDemo.xcscheme
│ │ └── JSPatchTests/
│ │ ├── Info.plist
│ │ ├── InheritTest.js
│ │ ├── JPCFunctionTest.h
│ │ ├── JPCFunctionTest.m
│ │ ├── JPInheritanceTestObjects.h
│ │ ├── JPInheritanceTestObjects.m
│ │ ├── JPJSClassTest.h
│ │ ├── JPJSClassTest.m
│ │ ├── JPMultithreadTestObject.h
│ │ ├── JPMultithreadTestObject.m
│ │ ├── JPNumberTest.h
│ │ ├── JPNumberTest.m
│ │ ├── JPPerformanceTest.h
│ │ ├── JPPerformanceTest.m
│ │ ├── JPSuperTestObject.h
│ │ ├── JPSuperTestObject.m
│ │ ├── JPTestObject.h
│ │ ├── JPTestObject.m
│ │ ├── JSPatchTests.m
│ │ ├── jsCFunctionTest.js
│ │ ├── jsClassTest.js
│ │ ├── jsNumberTest.js
│ │ ├── multithreadTest.js
│ │ ├── newBlockTest.h
│ │ ├── newBlockTest.js
│ │ ├── newBlockTest.m
│ │ ├── newProtocolTest.h
│ │ ├── newProtocolTest.js
│ │ ├── newProtocolTest.m
│ │ ├── performanceTest.js
│ │ ├── protocolTest.js
│ │ ├── superTest.js
│ │ └── test.js
│ ├── iOSPlayground/
│ │ ├── JSPatchPlayground/
│ │ │ ├── AppDelegate.h
│ │ │ ├── AppDelegate.m
│ │ │ ├── Assets.xcassets/
│ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Brand Assets.launchimage/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ └── LaunchImage.launchimage/
│ │ │ │ └── Contents.json
│ │ │ ├── Info.plist
│ │ │ ├── JPErrorMsgViewController.h
│ │ │ ├── JPErrorMsgViewController.m
│ │ │ ├── JPRootViewController.h
│ │ │ ├── JPRootViewController.m
│ │ │ ├── libs/
│ │ │ │ ├── SGDirWatchdog.h
│ │ │ │ └── SGDirWatchdog.m
│ │ │ ├── main.m
│ │ │ └── src/
│ │ │ ├── JPDemoController.js
│ │ │ └── main.js
│ │ ├── JSPatchPlayground.xcodeproj/
│ │ │ ├── project.pbxproj
│ │ │ └── project.xcworkspace/
│ │ │ └── contents.xcworkspacedata
│ │ └── README.md
│ ├── iOSPlaygroundToolDemo/
│ │ ├── JSPatchPlaygroundDemo/
│ │ │ ├── AppDelegate.h
│ │ │ ├── AppDelegate.m
│ │ │ ├── Assets.xcassets/
│ │ │ │ ├── AppIcon.appiconset/
│ │ │ │ │ └── Contents.json
│ │ │ │ ├── Contents.json
│ │ │ │ └── apple.imageset/
│ │ │ │ └── Contents.json
│ │ │ ├── Base.lproj/
│ │ │ │ ├── LaunchScreen.storyboard
│ │ │ │ └── Main.storyboard
│ │ │ ├── Info.plist
│ │ │ ├── JPRootViewController.h
│ │ │ ├── JPRootViewController.m
│ │ │ ├── js/
│ │ │ │ └── demo.js
│ │ │ └── main.m
│ │ ├── JSPatchPlaygroundDemo.xcodeproj/
│ │ │ ├── project.pbxproj
│ │ │ └── project.xcworkspace/
│ │ │ └── contents.xcworkspacedata
│ │ └── README.md
│ └── tvOSDemo/
│ ├── JSPatchDemo/
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── JPViewController.h
│ │ ├── JPViewController.m
│ │ ├── Supporting Files/
│ │ │ ├── Images.xcassets/
│ │ │ │ └── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ ├── Info.plist
│ │ │ └── main.m
│ │ └── demo.js
│ └── JSPatchDemo.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ └── contents.xcworkspacedata
├── Extensions/
│ ├── JPBlock/
│ │ ├── JPBlock.h
│ │ ├── JPBlock.m
│ │ ├── JPBlockWrapper.h
│ │ └── JPBlockWrapper.m
│ ├── JPCFunction/
│ │ ├── JPCFunction.h
│ │ ├── JPCFunction.m
│ │ ├── JPMemory.h
│ │ ├── JPMemory.m
│ │ ├── JPStructPointer.h
│ │ └── JPStructPointer.m
│ ├── JPCFunctionBinder/
│ │ ├── CoreGraphics/
│ │ │ ├── JPCGBitmapContext.h
│ │ │ ├── JPCGBitmapContext.m
│ │ │ ├── JPCGColor.h
│ │ │ ├── JPCGColor.m
│ │ │ ├── JPCGContext.h
│ │ │ ├── JPCGContext.m
│ │ │ ├── JPCGGeometry.h
│ │ │ ├── JPCGGeometry.m
│ │ │ ├── JPCGImage.h
│ │ │ ├── JPCGImage.m
│ │ │ ├── JPCGPath.h
│ │ │ ├── JPCGPath.m
│ │ │ ├── JPCGTransform.h
│ │ │ ├── JPCGTransform.m
│ │ │ ├── JPCoreGraphics.h
│ │ │ └── JPCoreGraphics.m
│ │ └── UIKit/
│ │ ├── JPUIGeometry.h
│ │ ├── JPUIGeometry.m
│ │ ├── JPUIGraphics.h
│ │ ├── JPUIGraphics.m
│ │ ├── JPUIImage.h
│ │ ├── JPUIImage.m
│ │ ├── JPUIKit.h
│ │ └── JPUIKit.m
│ ├── JPCleaner.h
│ ├── JPCleaner.m
│ ├── JPDispatch.h
│ ├── JPDispatch.m
│ ├── JPLibffi/
│ │ ├── JPMethodSignature.h
│ │ ├── JPMethodSignature.m
│ │ └── libffi/
│ │ ├── ffi.h
│ │ ├── ffi_arm.h
│ │ ├── ffi_arm64.h
│ │ ├── ffi_i386.h
│ │ ├── ffi_x86_64.h
│ │ ├── ffitarget.h
│ │ ├── ffitarget_arm.h
│ │ ├── ffitarget_arm64.h
│ │ ├── ffitarget_i386.h
│ │ ├── ffitarget_x86_64.h
│ │ └── libffi.a
│ ├── JPLocker.h
│ ├── JPLocker.m
│ ├── JPNumber.h
│ ├── JPNumber.m
│ ├── JPPlaygroundTool/
│ │ ├── JPPlayground.h
│ │ ├── JPPlayground.m
│ │ ├── JPPlaygroundModule/
│ │ │ ├── JPKeyCommands.h
│ │ │ ├── JPKeyCommands.m
│ │ │ ├── SGDirWatchdog.h
│ │ │ └── SGDirWatchdog.m
│ │ ├── JPPlaygroundView/
│ │ │ ├── JPDevErrorView.h
│ │ │ ├── JPDevErrorView.m
│ │ │ ├── JPDevMenu.h
│ │ │ ├── JPDevMenu.m
│ │ │ ├── JPDevTipView.h
│ │ │ └── JPDevTipView.m
│ │ └── README.md
│ ├── JPProtocol.h
│ ├── JPProtocol.m
│ ├── JPSpecialInit.h
│ └── JPSpecialInit.m
├── JSPatch/
│ ├── JPEngine.h
│ ├── JPEngine.m
│ └── JSPatch.js
├── JSPatch.podspec
├── LICENSE
├── Loader/
│ ├── JPLoader.h
│ ├── JPLoader.m
│ ├── libs/
│ │ ├── RSA.h
│ │ ├── RSA.m
│ │ ├── ZipArchive.h
│ │ ├── ZipArchive.m
│ │ └── minizip/
│ │ ├── crypt.h
│ │ ├── ioapi.c
│ │ ├── ioapi.h
│ │ ├── mztools.c
│ │ ├── mztools.h
│ │ ├── unzip.c
│ │ ├── unzip.h
│ │ ├── zip.c
│ │ └── zip.h
│ └── tools/
│ └── packer.php
├── README-CN.md
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# General
.DS_Store
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
================================================
FILE: .travis.yml
================================================
language: objective-c
osx_image: xcode7.3
env:
- UDID="D72029C0-E8E1-4349-B423-E458466135B3", IOS_DEVICE="iPhone 4s (8.1)"
- UDID="5752202B-E7A2-4B6C-9D7B-B211C2F54654", IOS_DEVICE="iPhone 6s (9.3)"
script:
- xcrun instruments -s devices
- open -a "simulator" --args -CurrentDeviceUDID $UDID
- xcodebuild test -project ./Demo/iOSDemo/JSPatchDemo.xcodeproj -scheme JSPatchDemo -sdk iphonesimulator -destination "platform=iOS Simulator,id=$UDID"
- osascript -e 'tell app "Simulator" to quit'
================================================
FILE: Demo/DribbbleDemo/Podfile
================================================
platform :ios, '7.0'
target 'dribbbleDemo' do
pod "AFNetworking", "~> 2.0"
pod "SDWebImage"
end
================================================
FILE: Demo/DribbbleDemo/README.md
================================================
# JSPatch Dribbble Demo

A Dribbble iOS client write in JSPatch.
Please install the cocoapods and run `pod install`.
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/AppDelegate.h
================================================
//
// AppDelegate.h
// dribbbleDemo
//
// Created by bang on 15/9/1.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import
@interface AppDelegate : UIResponder
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/AppDelegate.m
================================================
//
// AppDelegate.m
// dribbbleDemo
//
// Created by bang on 15/9/1.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import "AppDelegate.h"
#import "JPEngine.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.window makeKeyAndVisible];
[JPEngine startEngine];
NSString *sourcePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"dribbble/main.js"];
[JPEngine evaluateScriptWithPath:sourcePath];
[self initRootViewController];
return YES;
}
- (void)initRootViewController
{
}
- (void)applicationWillResignActive:(UIApplication *)application {
// 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.
// 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.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// 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.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// 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.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/LaunchImage-1.launchimage/Contents.json
================================================
{
"images" : [
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/LaunchImage.launchimage/Contents.json
================================================
{
"images" : [
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "Default-576@2x.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "Default-736@3x.png",
"minimum-system-version" : "8.0",
"orientation" : "landscape",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "667h",
"filename" : "Default-667@2x.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default@2x.png",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "retina4",
"filename" : "Default-568h@2x.png",
"minimum-system-version" : "7.0",
"orientation" : "portrait",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
com.jspatch..$(PRODUCT_NAME:rfc1034identifier)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
LSRequiresIPhoneOS
NSAppTransportSecurity
NSAllowsArbitraryLoads
UIRequiredDeviceCapabilities
armv7
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/CommonDefine.js
================================================
global.SCREEN_WIDTH = require('UIScreen').mainScreen().bounds().width;
global.SCREEN_HEIGHT = require('UIScreen').mainScreen().bounds().height;
global.UIHelper = {
bottomY: function(view) {
var f = view.frame();
return f.height + f.y;
},
rightX: function(view) {
var f = view.frame();
return f.width + f.x;
},
setWidth: function(view, width) {
var f = view.frame();
f.width = width
view.setFrame(f)
},
setHeight: function(view, height) {
var f = view.frame();
f.height = height
view.setFrame(f)
},
setX: function(view, x) {
var f = view.frame();
f.x = x
view.setFrame(f)
},
setY: function(view, y) {
var f = view.frame();
f.y = y
view.setFrame(f)
}
}
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/DBDataSource.js
================================================
var _dataSourceShareInstance;
defineJSClass('DBDataSource', {
init: function(){
this.dribbbleHost = 'https://api.dribbble.com/v1';
this.requestManager = require('AFHTTPRequestOperationManager').manager();
this.requestManager.requestSerializer().setValue_forHTTPHeaderField('Bearer deeb37c0823d3866650db12df9e36730a0453a5a7b8e6493e0ac5ece15929613', 'Authorization');
return this;
},
_get: function(path, params, succ, fail){
var url = this.dribbbleHost + path
this.requestManager.GET_parameters_success_failure(url, params,
block('AFHTTPRequestOperation *, id', function(operation, responseObject) {
if (succ) succ(responseObject);
}),
block('AFHTTPRequestOperation *, NSError *', function(operation, error) {
if (fail) fail(error);
})
);
},
loadPublicShots: function(page, per_page, succ, fail) {
var path = '/shots';
this._get(path, {page: page, per_page:per_page}, succ, fail)
},
loadComments: function(id, page, per_page, succ, fail) {
var path = '/shots/' + id + '/comments';
this._get(path, {page: page, per_page:per_page}, succ, fail)
},
loadUserShots: function(userId, page, per_page, succ, fail) {
var path = '/users/' + userId + '/shots';
this._get(path, {page: page, per_page:per_page}, succ, fail)
},
}, {
shareInstance: function(){
if (!_dataSourceShareInstance) {
_dataSourceShareInstance = DBDataSource.alloc().init();
}
return _dataSourceShareInstance;
},
})
/*item struct:
{
"id": 2619381,
"title": "Seaborn Oyster Co.",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg"
},
"views_count": 2166,
"likes_count": 235,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T17:12:41Z",
"updated_at": "2016-03-29T17:12:53Z",
"html_url": "https://dribbble.com/shots/2619381-Seaborn-Oyster-Co",
"attachments_url": "https://api.dribbble.com/v1/shots/2619381/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619381/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619381/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619381/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619381/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619381/rebounds",
"animated": false,
"tags": [
"charleston",
"company",
"ocean",
"oyster",
"sea",
"wave"
],
"user": {
"id": 52758,
"name": "Jay Fletcher",
"username": "jfletcherdesign",
"html_url": "https://dribbble.com/jfletcherdesign",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283",
"bio": "",
"location": "Charleston, SC",
"links": {
"web": "http://www.jfletcherdesign.com",
"twitter": "https://twitter.com/jfletcherdesign"
},
"buckets_count": 0,
"comments_received_count": 5239,
"followers_count": 13803,
"followings_count": 558,
"likes_count": 6531,
"likes_received_count": 104895,
"projects_count": 10,
"rebounds_received_count": 325,
"shots_count": 481,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/52758/buckets",
"followers_url": "https://api.dribbble.com/v1/users/52758/followers",
"following_url": "https://api.dribbble.com/v1/users/52758/following",
"likes_url": "https://api.dribbble.com/v1/users/52758/likes",
"projects_url": "https://api.dribbble.com/v1/users/52758/projects",
"shots_url": "https://api.dribbble.com/v1/users/52758/shots",
"teams_url": "https://api.dribbble.com/v1/users/52758/teams",
"created_at": "2011-08-13T23:30:38Z",
"updated_at": "2016-03-29T17:12:53Z"
},
"team": null
},
*/
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/DBDetailController.js
================================================
include('DBDetailViews.js')
include('DBUserController.js')
defineClass('DBDetailViewController: UITableViewController', [
'loadingView',
'isLoading',
'commentsData',
'itemData',
'currPage'
], {
initWithItem: function(item){
self = self.super().init();
if (self) {
self.tableView().setSeparatorStyle(0);
self.setTitle(item['title']);
var headerView = DBDetailHeaderView.alloc().initWithItem(item);
var slf = self;
headerView.setTapUserCallback(function(user){
slf._handleGotoUser(user);
})
self.tableView().setTableHeaderView(headerView);
var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);
loadingView.setFrame({x: (SCREEN_WIDTH - 40) / 2, y:headerView.frame().height + 30, width:40, height:40});
loadingView.startAnimating();
self.view().addSubview(loadingView);
self.setLoadingView(loadingView);
self.setCommentsData([]);
self.setItemData(item);
self.setCurrPage(1);
self._loadComment();
}
return self;
},
_loadComment: function(){
self.setIsLoading(1)
var item = self.itemData();
var perPage = 10;
var slf = self;
DBDataSource.shareInstance().loadComments(item['id'], self.currPage(), perPage, function(comments){
slf.loadingView().removeFromSuperview();
slf.setCommentsData(slf.commentsData().concat(comments));
slf.setCurrPage(slf.currPage() + 1);
slf.setIsLoading(0);
if (comments.length >= perPage) {
slf.tableView().setTableFooterView(DBLoadMoreView.alloc().init());
} else {
slf.tableView().setTableFooterView(null);
}
slf.tableView().reloadData();
}, function(){
//fail
})
},
numberOfSectionsInTableView: function(tableView) {
return 1;
},
tableView_numberOfRowsInSection: function(tableView, section) {
if (!self.commentsData()) return 0;
return self.commentsData().length;
},
tableView_cellForRowAtIndexPath: function(tableView, indexPath) {
var cell = tableView.dequeueReusableCellWithIdentifier("cell")
if (!cell) {
cell = DBCommentViewCell.alloc().initWithStyle_reuseIdentifier(0, "cell")
var slf = self;
cell.setTapUserCallback(function(user){
slf._handleGotoUser(user);
})
}
cell.renderWithComment(self.commentsData()[indexPath.row()]);
return cell
},
tableView_heightForRowAtIndexPath: function(tableView, indexPath) {
var comment = self.commentsData()[indexPath.row()];
if (!comment['contentHeight']) {
comment['contentHeight'] = DBCommentViewCell.heightWithComment(comment);
}
return comment['contentHeight'];
},
scrollViewDidScroll: function(scrollView) {
var contentOffset = scrollView.contentOffset();
var contentSize = scrollView.contentSize();
if (!self.isLoading() && self.tableView().tableFooterView() && contentOffset.y - contentSize.height > -SCREEN_HEIGHT) {
self._loadComment();
}
},
_handleGotoUser: function(user) {
var userVC = DBUserViewController.alloc().initWithUser(user);
self.navigationController().pushViewController_animated(userVC, YES);
}
})
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/DBDetailViews.js
================================================
require('UIView, UIImage')
var gap = 10;
var avatarSize = 40;
defineClass('DBDetailHeaderView: UIView', ['tapUserCallback', 'itemData'], {
initWithItem: function(item) {
self = self.super().init();
if (self) {
self.setItemData(item);
var avatarButton = require('UIButton')
.alloc()
.initWithFrame({x:gap, y:gap, width:avatarSize, height:avatarSize});
avatarButton.addTarget_action_forControlEvents(self, 'handleTapUser', 1 << 6);
var nameLabel = UILabel
.alloc()
.initWithFrame({x: gap * 2 + avatarSize, y:gap, width:SCREEN_WIDTH - avatarSize - gap * 3 , height:20});
nameLabel.setFont(UIFont.systemFontOfSize(14));
var timeLabel = UILabel
.alloc()
.initWithFrame({x: gap * 2 + avatarSize, y:gap + 20, width:SCREEN_WIDTH - avatarSize - gap * 3 , height:20});
timeLabel.setFont(UIFont.systemFontOfSize(12));
timeLabel.setTextColor(UIColor.grayColor());
var contentImageView = require('UIImageView')
.alloc()
.initWithFrame({x: gap, y:gap*2 + avatarSize, width:SCREEN_WIDTH - gap*2, height:(SCREEN_WIDTH - gap*2)*3/4});
self.addSubview(avatarButton);
self.addSubview(nameLabel);
self.addSubview(timeLabel);
self.addSubview(contentImageView);
var panelView = self._genPanelViewWithItem(item);
var panelFrame = panelView.frame();
panelFrame.x = SCREEN_WIDTH - (gap + panelFrame.width);
panelFrame.y = contentImageView.frame().y + contentImageView.frame().height + gap;
panelView.setFrame(panelFrame);
self.addSubview(panelView);
avatarButton.sd__setImageWithURL_forState(require('NSURL').URLWithString(item['user']['avatar_url']), 0);
contentImageView.sd__setImageWithURL(require('NSURL').URLWithString(item['images']['normal']));
nameLabel.setText(item['user']['name'])
var d = new Date(item['created_at']);
var dateStr = d.getFullYear() + '年' + (d.getMonth() + 1) + '月' + d.getDate() + '日' + ' ' + d.getHours() + ':' + d.getMinutes();
timeLabel.setText(dateStr);
self.setFrame({x:0, y:0, width: SCREEN_WIDTH, height:panelView.frame().y + panelView.frame().height});
}
return self;
},
handleTapUser : function(){
var cb = self.tapUserCallback();
if (cb) cb(self.itemData()['user']);
},
_genPanelViewWithItem : function(item) {
var panelView = UIView
.alloc()
.init();
var iconSize = 12;
var viewImageView = UIImageView
.alloc()
.initWithFrame({x:0, y:0, width:15, height: 15});
viewImageView.setImage(UIImage.imageWithContentsOfFile(resourcePath('imgs/view.png')));
panelView.addSubview(viewImageView);
var viewLabel = self._genPanelLabel(item['views_count'], {x: UIHelper.rightX(viewImageView) + 5, y:0, width:40, height:iconSize});
panelView.addSubview(viewLabel);
var commentImageView = UIImageView
.alloc()
.initWithFrame({x:UIHelper.rightX(viewLabel) + 10, y:3, width:iconSize, height: iconSize});
commentImageView.setImage(UIImage.imageWithContentsOfFile(resourcePath('imgs/comment.png')));
panelView.addSubview(commentImageView);
var commentLabel = self._genPanelLabel(item['comments_count'], {x: UIHelper.rightX(commentImageView) + 5, y:0, width:40, height:iconSize});
panelView.addSubview(commentLabel);
var likeImageView = UIImageView
.alloc()
.initWithFrame({x:UIHelper.rightX(commentLabel) + 10, y:3, width:iconSize, height: iconSize});
likeImageView.setImage(UIImage.imageWithContentsOfFile(resourcePath('imgs/like.png')));
panelView.addSubview(likeImageView);
var commentLabel = self._genPanelLabel(item['likes_count'], {x: UIHelper.rightX(likeImageView) + 5, y:0, width:40, height:iconSize});
panelView.addSubview(commentLabel);
panelView.setFrame({x:0, y:0, width:UIHelper.rightX(commentLabel), height:40});
return panelView;
},
_genPanelLabel: function(val, frame) {
var viewLabel = UILabel.alloc().initWithFrame(frame)
viewLabel.setText(val.toString());
viewLabel.setFont(UIFont.systemFontOfSize(14));
viewLabel.setTextColor(UIColor.colorWithWhite_alpha(.5, 1))
viewLabel.sizeToFit();
return viewLabel;
}
})
defineClass('DBCommentViewCell: UITableViewCell', [
'avatarButton',
'nameLabel',
'timeLabel',
'contentLabel',
'tapUserCallback',
'commentData',
], {
initWithStyle_reuseIdentifier: function(style, reuseIdentifier) {
self = self.super().initWithStyle_reuseIdentifier(style, reuseIdentifier);
if (self) {
self.setSelectionStyle(0);
var avatarButton = require('UIButton')
.alloc()
.initWithFrame({x:gap, y:gap, width:avatarSize, height:avatarSize});
avatarButton.addTarget_action_forControlEvents(self, 'handleTapUser', 1 << 6);
var nameLabel = UILabel
.alloc()
.initWithFrame({x: gap * 2 + avatarSize, y:gap, width:SCREEN_WIDTH - avatarSize - gap * 3 , height:20});
nameLabel.setFont(UIFont.systemFontOfSize(14));
nameLabel.setTextColor(UIColor.colorWithWhite_alpha(.5, 1))
var timeLabel = UILabel
.alloc()
.initWithFrame({x: SCREEN_WIDTH - gap - 200, y:gap, width:200 , height:20});
timeLabel.setFont(UIFont.systemFontOfSize(12));
timeLabel.setTextColor(UIColor.colorWithWhite_alpha(.7, 1));
timeLabel.setTextAlignment(2);
var contentLabel = DBCommentViewCell._genContentLabel();
self.addSubview(avatarButton);
self.addSubview(nameLabel);
self.addSubview(timeLabel);
self.addSubview(contentLabel);
self.setAvatarButton(avatarButton);
self.setNameLabel(nameLabel);
self.setTimeLabel(timeLabel);
self.setContentLabel(contentLabel);
}
return self;
},
renderWithComment: function(comment) {
self.avatarButton().sd__setImageWithURL_forState(require('NSURL').URLWithString(comment['user']['avatar_url']), 0);
self.nameLabel().setText(comment['user']['name'])
var d = new Date(comment['created_at']);
var dateStr = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + '-';// + ' ' + d.getHours() + ':' + d.getMinutes();
self.timeLabel().setText(dateStr);
DBCommentViewCell._renderContentLabel(comment, self.contentLabel());
self.setCommentData(comment);
},
handleTapUser : function(){
var cb = self.tapUserCallback();
if (cb) cb(self.commentData()['user']);
},
}, {
heightWithComment: function(comment) {
var contentLabel = self._genContentLabel();
self._renderContentLabel(comment, contentLabel);
var contentFrame = contentLabel.frame();
return contentFrame.height + contentFrame.y + gap;
},
_renderContentLabel: function(comment, contentLabel) {
if (!comment['bodyText']) {
comment['bodyText'] = comment['body'].replace('\n', '').replace('
', '\n').replace(/<[^>]+>/g,"")
}
contentLabel.setText(comment['bodyText']);
var size = contentLabel.sizeThatFits({width:contentLabel.frame().width, height:1000});
var frame = contentLabel.frame();
frame.height = size.height;
contentLabel.setFrame(frame);
},
_genContentLabel: function() {
var contentLabel = require('UILabel')
.alloc()
.initWithFrame({x:gap * 2 + avatarSize, y: gap*2 + 15, width:SCREEN_WIDTH - gap * 3 - avatarSize, height:0});
contentLabel.setFont(UIFont.systemFontOfSize(16));
contentLabel.setNumberOfLines(0);
return contentLabel;
}
})
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/DBTimelineController.js
================================================
include('DBTimelineViews.js')
include('DBDetailController.js')
defineClass('WBTimelineViewController: UITableViewController', [
'loadingView',
'isLoading',
'shots',
'currPage'
], {
init: function(){
self = self.super().init();
var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);
loadingView.setFrame({x: (SCREEN_WIDTH - 40) / 2, y:(SCREEN_HEIGHT - 40 - 64) / 2, width:40, height:40});
loadingView.startAnimating();
self.view().addSubview(loadingView);
self.setLoadingView(loadingView);
self.tableView().setBackgroundColor(UIColor.colorWithWhite_alpha(.9, 1));
self.tableView().setSeparatorStyle(0);
self.setTitle('Dribbble');
self.setShots([]);
self.setCurrPage(1);
self._loadShots();
return self;
},
_loadShots: function() {
self.setIsLoading(1)
var perPage = 20;
var slf = self;
DBDataSource.shareInstance().loadPublicShots(self.currPage(), perPage, function(shots){
slf.loadingView().removeFromSuperview();
slf.setShots(slf.shots().concat(shots));
slf.setCurrPage(slf.currPage() + 1);
slf.setIsLoading(0);
if (shots.length >= perPage) {
slf.tableView().setTableFooterView(DBLoadMoreView.alloc().init());
} else {
slf.tableView().setTableFooterView(null);
}
slf.tableView().reloadData();
}, function(){
//fail
})
},
numberOfSectionsInTableView: function(tableView) {
return 1;
},
tableView_numberOfRowsInSection: function(tableView, section) {
return self.shots().length / 2;
},
tableView_cellForRowAtIndexPath: function(tableView, indexPath) {
var cell = tableView.dequeueReusableCellWithIdentifier("cell")
if (!cell) {
cell = DBTimelineViewCell.alloc().initWithStyle_reuseIdentifier(0, "cell")
var slf = self;
cell.setTapCallback(function(item){
slf._handleGotoItem(item);
})
}
cell.renderWithItems(self.shots()[indexPath.row()*2],
self.shots()[indexPath.row()*2 + 1]);
return cell
},
tableView_heightForRowAtIndexPath: function(tableView, indexPath) {
return (SCREEN_WIDTH / 2) *3/4 + 30;
},
scrollViewDidScroll: function(scrollView) {
var contentOffset = scrollView.contentOffset();
var contentSize = scrollView.contentSize();
if (!self.isLoading() && contentOffset.y - contentSize.height > -SCREEN_HEIGHT) {
self._loadShots();
}
},
_handleGotoItem: function(item) {
var detailVC = DBDetailViewController.alloc().initWithItem(item);
self.navigationController().pushViewController_animated(detailVC, YES);
}
})
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/DBTimelineViews.js
================================================
var gap = 10;
var avatarSize = 40;
require('UILabel, UIColor, UIFont, UITextView');
defineClass('DBTimelineItemView: UIView', [
'avatarImageView',
'nameLabel',
'contentImageBtn',
'tapCallback'
], {
init: function(){
self = self.super().init();
var imgGap = 5;
var width = (SCREEN_WIDTH - 10 * 3) / 2;
self.setFrame({x: 0, y: 0, width:width, height: width * 3/4 + 30});
self.setBackgroundColor(UIColor.whiteColor());
var contentImageBtn = require('UIButton')
.alloc()
.initWithFrame({x: imgGap, y:imgGap, width:width - 2*imgGap, height:(width - 2*imgGap)*3/4});
self.addSubview(contentImageBtn);
self.setContentImageBtn(contentImageBtn);
contentImageBtn.addTarget_action_forControlEvents(self, 'handleTap', 1 << 6);
var avatarSize = 18;
var avatarImageView = require('UIImageView')
.alloc()
.initWithFrame({x:imgGap, y:contentImageBtn.frame().height + contentImageBtn.frame().y + imgGap + 2, width:avatarSize, height:avatarSize});
self.addSubview(avatarImageView);
self.setAvatarImageView(avatarImageView);
var nameLabel = UILabel
.alloc()
.initWithFrame({x: imgGap + avatarSize + 5, y:avatarImageView.frame().y, width:width - avatarSize - imgGap*2 - 5 , height:avatarSize});
nameLabel.setFont(UIFont.systemFontOfSize(12));
nameLabel.setTextColor(UIColor.grayColor());
self.addSubview(nameLabel);
self.setNameLabel(nameLabel);
return self;
},
handleTap: function() {
var cb = self.tapCallback();
if (cb) cb();
},
renderWithItem: function(item) {
self.contentImageBtn().sd__setImageWithURL_forState(require('NSURL').URLWithString(item['images']['normal']), 0);
self.avatarImageView().sd__setImageWithURL(require('NSURL').URLWithString(item['user']['avatar_url']));
self.nameLabel().setText(item['user']['name']);
},
})
defineClass('DBTimelineViewCell: UITableViewCell', [
'itemView1',
'itemView2',
'tapCallback',
], {
initWithStyle_reuseIdentifier: function(style, reuseIdentifier) {
self = self.super().initWithStyle_reuseIdentifier(style, reuseIdentifier);
if (self) {
self.setSelectionStyle(0);
self.contentView().setBackgroundColor(UIColor.colorWithWhite_alpha(.9, 1));
self._initItemView();
}
return self;
},
_initItemView: function(){
var itemView1 = DBTimelineItemView.alloc().init();
var itemView2 = DBTimelineItemView.alloc().init();
itemView1.setFrame({x:gap, y: gap, width: itemView1.frame().width, height: itemView1.frame().height});
itemView2.setFrame({x:gap*2 + itemView1.frame().width, y: gap, width: itemView2.frame().width, height: itemView2.frame().height});
self.setItemView1(itemView1);
self.setItemView2(itemView2);
self.addSubview(itemView1);
self.addSubview(itemView2);
},
renderWithItems: function(item1, item2) {
if (item1) {
self.itemView1().renderWithItem(item1);
}
if (item2) {
self.itemView2().renderWithItem(item2);
}
self.itemView1().setHidden(!item1);
self.itemView2().setHidden(!item2);
var slf = self
self.itemView1().setTapCallback(function(){
var cb = slf.tapCallback();
if (cb) cb(item1);
})
self.itemView2().setTapCallback(function(){
var cb = slf.tapCallback();
if (cb) cb(item2);
})
}
})
defineClass('DBLoadMoreView:UIView', {
init: function(){
self = self.super().init();
var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);
loadingView.startAnimating();
loadingView.setFrame({x:(SCREEN_WIDTH - 140) / 2, y: 10, width:40, height: 40});
var loadingLabel = require('UILabel').alloc().init();
loadingLabel.setText('Loading...');
loadingLabel.setFrame({x:(SCREEN_WIDTH - 140) / 2 + 40, y: 10, width:90, height: 40});
loadingLabel.setTextColor(require('UIColor').grayColor());
self.addSubview(loadingView);
self.addSubview(loadingLabel);
self.setFrame({x:0, y:0, width:SCREEN_WIDTH, height: 60});
return self;
},
})
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/DBUserController.js
================================================
include('DBTimelineViews.js')
include('DBUserViews.js')
defineClass('DBUserViewController: UITableViewController', [
'loadingView',
'isLoading',
'commentsData',
'user',
'shots',
'currPage'
], {
initWithUser: function(user){
self = self.super().init();
if (self) {
self.tableView().setSeparatorStyle(0);
self.tableView().setBackgroundColor(UIColor.colorWithWhite_alpha(.9, 1));
self.setTitle(user['name']);
var headerView = DBUserHeaderView.alloc().initWithUser(user);
self.tableView().setTableHeaderView(headerView);
var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);
loadingView.setFrame({x: (SCREEN_WIDTH - 40) / 2, y:headerView.frame().height + 30, width:40, height:40});
loadingView.startAnimating();
self.view().addSubview(loadingView);
self.setLoadingView(loadingView);
self.setShots([]);
self.setUser(user);
self.setCurrPage(1);
self._loadShots();
}
return self;
},
_loadShots: function(){
self.setIsLoading(1)
var user = self.user();
var perPage = 10;
var slf = self;
DBDataSource.shareInstance().loadUserShots(user['id'], self.currPage(), perPage, function(newShots){
slf.loadingView().removeFromSuperview();
slf.setShots(slf.shots().concat(newShots));
slf.setCurrPage(slf.currPage() + 1);
slf.setIsLoading(0);
if (newShots.length >= perPage) {
slf.tableView().setTableFooterView(DBLoadMoreView.alloc().init());
} else {
slf.tableView().setTableFooterView(null);
}
slf.tableView().reloadData();
}, function(){
//fail
})
},
numberOfSectionsInTableView: function(tableView) {
return 1;
},
tableView_numberOfRowsInSection: function(tableView, section) {
if (!self.shots()) return 0;
return self.shots().length / 2;
},
tableView_cellForRowAtIndexPath: function(tableView, indexPath) {
var cell = tableView.dequeueReusableCellWithIdentifier("cell")
if (!cell) {
cell = DBUserViewCell.alloc().initWithStyle_reuseIdentifier(0, "cell")
var slf = self;
cell.setTapCallback(function(item){
slf._handleGotoItem(item);
})
}
cell.renderWithItems(self.shots()[indexPath.row()*2],
self.shots()[indexPath.row()*2 + 1]);
return cell
},
tableView_heightForRowAtIndexPath: function(tableView, indexPath) {
return (SCREEN_WIDTH / 2) *3/4;
},
scrollViewDidScroll: function(scrollView) {
var contentOffset = scrollView.contentOffset();
var contentSize = scrollView.contentSize();
if (!self.isLoading() && self.tableView().tableFooterView() && contentOffset.y - contentSize.height > -SCREEN_HEIGHT) {
self._loadShots();
}
},
_handleGotoItem: function(item) {
if (!item.user) item.user = self.user();
var detailVC = DBDetailViewController.alloc().initWithItem(item);
self.navigationController().pushViewController_animated(detailVC, YES);
}
})
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/DBUserViews.js
================================================
var gap = 10;
defineClass('DBUserHeaderView: UIView', {
initWithUser: function(user) {
self = self.super().init();
if (self) {
var avatarSize = 100;
var avatarImageView = require('UIImageView')
.alloc()
.initWithFrame({x:(SCREEN_WIDTH - avatarSize) / 2, y:30, width:avatarSize, height:avatarSize});
var nameLabel = UILabel
.alloc()
.initWithFrame({x: 0, y:UIHelper.bottomY(avatarImageView) + 10, width:SCREEN_WIDTH, height:30});
nameLabel.setFont(UIFont.systemFontOfSize(18));
nameLabel.setTextAlignment(1);
var panelView = UIView
.alloc()
.initWithFrame({x:0, y:UIHelper.bottomY(nameLabel) + 10,width:SCREEN_WIDTH, height:80});
var followerView = self._genUserDataView('follower', user['followers_count']);
var shotsView = self._genUserDataView('shots', user['shots_count']);
var likeView = self._genUserDataView('likes', user['likes_received_count']);
UIHelper.setX(shotsView, UIHelper.rightX(followerView));
UIHelper.setX(likeView, UIHelper.rightX(shotsView));
panelView.addSubview(followerView);
panelView.addSubview(shotsView);
panelView.addSubview(likeView);
self.addSubview(avatarImageView);
self.addSubview(nameLabel);
self.addSubview(panelView);
avatarImageView.sd__setImageWithURL(require('NSURL').URLWithString(user['avatar_url']));
nameLabel.setText(user['name']);
self.setFrame({x:0, y:0, width:SCREEN_WIDTH, height: UIHelper.bottomY(panelView)});
}
return self;
},
_genUserDataView : function(name, num) {
var width = SCREEN_WIDTH / 3
var panelView = UIView
.alloc()
.initWithFrame({x:0,y:0,width:width,height:80});
var numLabel = UILabel.alloc().initWithFrame({x:0,y:0,width:width,height:40})
numLabel.setText(self._formatNum(num));
numLabel.setFont(UIFont.systemFontOfSize(22));
numLabel.setTextAlignment(1);
var nameLabel = UILabel.alloc().initWithFrame({x:0,y:35,width:width,height:30})
nameLabel.setText(name);
nameLabel.setFont(UIFont.systemFontOfSize(15));
nameLabel.setTextColor(UIColor.colorWithWhite_alpha(.5, 1))
nameLabel.setTextAlignment(1);
panelView.addSubview(numLabel);
panelView.addSubview(nameLabel);
return panelView;
},
_formatNum: function(num){
if (num >= 1000) {
return (num/1000).toFixed(1) + 'k'
}
return num ? num.toString() : 0;
}
})
defineClass('DBUserItemView: DBTimelineItemView', {
init: function() {
self = self.super().init();
self.avatarImageView().removeFromSuperview();
self.nameLabel().removeFromSuperview();
var width = (SCREEN_WIDTH - 10 * 3) / 2;
self.setFrame({x: 0, y: 0, width:width, height: width * 3/4 + 5});
return self;
},
renderWithItem: function(item) {
self.contentImageBtn().sd__setImageWithURL_forState(require('NSURL').URLWithString(item['images']['normal']), 0);
},
});
defineClass('DBUserViewCell: DBTimelineViewCell', {
_initItemView: function() {
var itemView1 = DBUserItemView.alloc().init();
var itemView2 = DBUserItemView.alloc().init();
itemView1.setFrame({x:gap, y: gap, width: itemView1.frame().width, height: itemView1.frame().height});
itemView2.setFrame({x:gap*2 + itemView1.frame().width, y: gap, width: itemView2.frame().width, height: itemView2.frame().height});
self.setItemView1(itemView1);
self.setItemView2(itemView2);
self.addSubview(itemView1);
self.addSubview(itemView2);
},
});
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/main.js
================================================
autoConvertOCType(1)
include('CommonDefine.js')
include('DBDataSource.js')
include('DBTimelineController.js')
defineClass('AppDelegate', {
initRootViewController: function() {
var tableViewCtrl = WBTimelineViewController.alloc().init()
var navCtrl = require('UINavigationController').alloc().initWithRootViewController(tableViewCtrl);
self.window().setRootViewController(navCtrl);
}
})
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/dribbble/tmpData.js
================================================
var tmpData = [
{
"id": 2619381,
"title": "Seaborn Oyster Co.",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg"
},
"views_count": 2166,
"likes_count": 235,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T17:12:41Z",
"updated_at": "2016-03-29T17:12:53Z",
"html_url": "https://dribbble.com/shots/2619381-Seaborn-Oyster-Co",
"attachments_url": "https://api.dribbble.com/v1/shots/2619381/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619381/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619381/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619381/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619381/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619381/rebounds",
"animated": false,
"tags": [
"charleston",
"company",
"ocean",
"oyster",
"sea",
"wave"
],
"user": {
"id": 52758,
"name": "Jay Fletcher",
"username": "jfletcherdesign",
"html_url": "https://dribbble.com/jfletcherdesign",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283",
"bio": "",
"location": "Charleston, SC",
"links": {
"web": "http://www.jfletcherdesign.com",
"twitter": "https://twitter.com/jfletcherdesign"
},
"buckets_count": 0,
"comments_received_count": 5239,
"followers_count": 13803,
"followings_count": 558,
"likes_count": 6531,
"likes_received_count": 104895,
"projects_count": 10,
"rebounds_received_count": 325,
"shots_count": 481,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/52758/buckets",
"followers_url": "https://api.dribbble.com/v1/users/52758/followers",
"following_url": "https://api.dribbble.com/v1/users/52758/following",
"likes_url": "https://api.dribbble.com/v1/users/52758/likes",
"projects_url": "https://api.dribbble.com/v1/users/52758/projects",
"shots_url": "https://api.dribbble.com/v1/users/52758/shots",
"teams_url": "https://api.dribbble.com/v1/users/52758/teams",
"created_at": "2011-08-13T23:30:38Z",
"updated_at": "2016-03-29T17:12:53Z"
},
"team": null
},
{
"id": 2619494,
"title": "Mystery Project 72.1",
"description": "We're excited to be onboard for a new year of Outside Lands festival branding! Stay tuned for weekly updates including Ranger Dave's new patch series, the 2016 lineup, and more!
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_teaser.jpg"
},
"views_count": 2304,
"likes_count": 252,
"comments_count": 4,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T18:05:57Z",
"updated_at": "2016-03-29T18:07:21Z",
"html_url": "https://dribbble.com/shots/2619494-Mystery-Project-72-1",
"attachments_url": "https://api.dribbble.com/v1/shots/2619494/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619494/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619494/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619494/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619494/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619494/rebounds",
"rebound_source_url": "https://api.dribbble.com/v1/shots/2454166",
"animated": false,
"tags": [
"badge",
"branding",
"bridge",
"city",
"dan kuhlken",
"dkng",
"logo",
"nathan goldman",
"patch",
"san francisco",
"vector"
],
"user": {
"id": 31348,
"name": "DKNG",
"username": "DKNG",
"html_url": "https://dribbble.com/DKNG",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/31348/avatars/original/dkng_twitter.jpg?1305140827",
"bio": "Established in 2005, DKNG is a design studio based in Los Angeles, California with a focus on the music and entertainment industries.",
"location": "Los Angeles, CA",
"links": {
"web": "http://www.dkngstudios.com",
"twitter": "https://twitter.com/DKNGstudios"
},
"buckets_count": 0,
"comments_received_count": 5274,
"followers_count": 24704,
"followings_count": 256,
"likes_count": 197,
"likes_received_count": 125646,
"projects_count": 47,
"rebounds_received_count": 324,
"shots_count": 479,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/31348/buckets",
"followers_url": "https://api.dribbble.com/v1/users/31348/followers",
"following_url": "https://api.dribbble.com/v1/users/31348/following",
"likes_url": "https://api.dribbble.com/v1/users/31348/likes",
"projects_url": "https://api.dribbble.com/v1/users/31348/projects",
"shots_url": "https://api.dribbble.com/v1/users/31348/shots",
"teams_url": "https://api.dribbble.com/v1/users/31348/teams",
"created_at": "2011-04-28T20:48:48Z",
"updated_at": "2016-03-29T18:07:21Z"
},
"team": null
},
{
"id": 2619183,
"title": "Bonsai",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_teaser.png"
},
"views_count": 2143,
"likes_count": 259,
"comments_count": 11,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 18,
"created_at": "2016-03-29T15:48:38Z",
"updated_at": "2016-03-29T15:49:04Z",
"html_url": "https://dribbble.com/shots/2619183-Bonsai",
"attachments_url": "https://api.dribbble.com/v1/shots/2619183/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619183/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619183/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619183/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619183/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619183/rebounds",
"animated": false,
"tags": [
"bonsai",
"illustration",
"nature",
"plant",
"pot",
"tree",
"zen"
],
"user": {
"id": 44323,
"name": "Zach Roszczewski",
"username": "ZachRoszczewski",
"html_url": "https://dribbble.com/ZachRoszczewski",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/44323/avatars/normal/18f509c70a25627b40d5e3499b1cba2f.png?1419195740",
"bio": "Iconographer & Illustrator. Creator of www.flaticons.co & www.mojiapp.net .",
"location": "Encinitas, California",
"links": {
"web": "http://zachroszczewski.com",
"twitter": "https://twitter.com/ZachRoszczewski"
},
"buckets_count": 10,
"comments_received_count": 1682,
"followers_count": 9067,
"followings_count": 1541,
"likes_count": 14094,
"likes_received_count": 34409,
"projects_count": 7,
"rebounds_received_count": 14,
"shots_count": 113,
"teams_count": 2,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/44323/buckets",
"followers_url": "https://api.dribbble.com/v1/users/44323/followers",
"following_url": "https://api.dribbble.com/v1/users/44323/following",
"likes_url": "https://api.dribbble.com/v1/users/44323/likes",
"projects_url": "https://api.dribbble.com/v1/users/44323/projects",
"shots_url": "https://api.dribbble.com/v1/users/44323/shots",
"teams_url": "https://api.dribbble.com/v1/users/44323/teams",
"created_at": "2011-07-07T14:49:07Z",
"updated_at": "2016-03-29T15:49:04Z"
},
"team": null
},
{
"id": 2619255,
"title": "Canvas—A new space for big ideas",
"description": "A month ago the our team launched Canvas, a product for brands to tell their story and highlight products. It's been amazing to see your excitement for the creative possibilities and we can't wait to see how you use it.
\n\nOne of the best aspects of working on ads at Facebook is striving to find the sweet spot between the goals of our advertisers and those of people browsing their feed. Canvas allows businesses to create a more compelling experience for people, and in turn provides people with an ad they actually enjoy. Stay tuned for more :)
\n\nIf your interested in learning more about Canvas, or building one, you should check out https://canvas.facebook.com/ \n To learn more about our process check out Jaime Rovira's medium post https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble.gif",
"normal": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_1x.gif",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_teaser.gif"
},
"views_count": 3502,
"likes_count": 262,
"comments_count": 9,
"attachments_count": 2,
"rebounds_count": 0,
"buckets_count": 12,
"created_at": "2016-03-29T16:18:33Z",
"updated_at": "2016-03-29T16:19:50Z",
"html_url": "https://dribbble.com/shots/2619255-Canvas-A-new-space-for-big-ideas",
"attachments_url": "https://api.dribbble.com/v1/shots/2619255/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619255/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619255/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619255/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619255/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619255/rebounds",
"animated": true,
"tags": [
"android",
"animation",
"creative",
"illustration",
"ios",
"mobile",
"tool"
],
"user": {
"id": 476251,
"name": "ali griffin",
"username": "aligdanger",
"html_url": "https://dribbble.com/aligdanger",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/476251/avatars/normal/ali.png?1404762398",
"bio": "Designing product @Facebook ",
"location": "San Francisco, CA",
"links": {
"twitter": "https://twitter.com/aligdanger"
},
"buckets_count": 0,
"comments_received_count": 203,
"followers_count": 513,
"followings_count": 289,
"likes_count": 1302,
"likes_received_count": 2487,
"projects_count": 3,
"rebounds_received_count": 9,
"shots_count": 22,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/476251/buckets",
"followers_url": "https://api.dribbble.com/v1/users/476251/followers",
"following_url": "https://api.dribbble.com/v1/users/476251/following",
"likes_url": "https://api.dribbble.com/v1/users/476251/likes",
"projects_url": "https://api.dribbble.com/v1/users/476251/projects",
"shots_url": "https://api.dribbble.com/v1/users/476251/shots",
"teams_url": "https://api.dribbble.com/v1/users/476251/teams",
"created_at": "2014-01-10T18:37:14Z",
"updated_at": "2016-03-30T04:07:49Z"
},
"team": {
"id": 333588,
"name": "Facebook",
"username": "Facebook",
"html_url": "https://dribbble.com/Facebook",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/333588/avatars/normal/9a9d5301e289975fa16abd070f1615c0.png?1440610176",
"bio": "",
"location": "1 Hacker Way, Menlo Park, CA",
"links": {
"web": "https://www.facebook.com/design",
"twitter": "https://twitter.com/facebookdesign"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 14039,
"followings_count": 0,
"likes_count": 2,
"likes_received_count": 0,
"projects_count": 0,
"rebounds_received_count": 0,
"shots_count": 121,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/333588/buckets",
"followers_url": "https://api.dribbble.com/v1/users/333588/followers",
"following_url": "https://api.dribbble.com/v1/users/333588/following",
"likes_url": "https://api.dribbble.com/v1/users/333588/likes",
"projects_url": "https://api.dribbble.com/v1/users/333588/projects",
"shots_url": "https://api.dribbble.com/v1/users/333588/shots",
"created_at": "2013-05-15T23:13:37Z",
"updated_at": "2016-03-30T04:07:49Z",
"members_count": 39,
"members_url": "https://api.dribbble.com/v1/teams/333588/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/333588/shots"
}
},
{
"id": 2619346,
"title": "Sunset",
"description": "Baker Beach sunset from this weekend.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_teaser.png"
},
"views_count": 2897,
"likes_count": 231,
"comments_count": 3,
"attachments_count": 1,
"rebounds_count": 0,
"buckets_count": 6,
"created_at": "2016-03-29T16:55:27Z",
"updated_at": "2016-03-29T16:56:47Z",
"html_url": "https://dribbble.com/shots/2619346-Sunset",
"attachments_url": "https://api.dribbble.com/v1/shots/2619346/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619346/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619346/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619346/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619346/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619346/rebounds",
"animated": false,
"tags": [
"beach",
"cartoon",
"comics",
"hand-darwn",
"illustration",
"nature",
"sketch",
"sunset"
],
"user": {
"id": 3460,
"name": "Ryan Putnam",
"username": "RypeArts",
"html_url": "https://dribbble.com/RypeArts",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/3460/avatars/normal/4ed7a7a4737e971e3fa37f0705f5cc51.png?1457564367",
"bio": "designer, illustrator, potter, and father",
"location": "San Francisco, CA",
"links": {
"web": "http://ryanputn.am",
"twitter": "https://twitter.com/RypeArts"
},
"buckets_count": 3,
"comments_received_count": 9722,
"followers_count": 46667,
"followings_count": 518,
"likes_count": 10207,
"likes_received_count": 211321,
"projects_count": 34,
"rebounds_received_count": 373,
"shots_count": 589,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/3460/buckets",
"followers_url": "https://api.dribbble.com/v1/users/3460/followers",
"following_url": "https://api.dribbble.com/v1/users/3460/following",
"likes_url": "https://api.dribbble.com/v1/users/3460/likes",
"projects_url": "https://api.dribbble.com/v1/users/3460/projects",
"shots_url": "https://api.dribbble.com/v1/users/3460/shots",
"teams_url": "https://api.dribbble.com/v1/users/3460/teams",
"created_at": "2010-07-16T12:48:16Z",
"updated_at": "2016-03-29T16:56:47Z"
},
"team": null
},
{
"id": 2619340,
"title": "Skies Like These ",
"description": "In anticipation for their release of the paperback version of the book, Skies Like These, Macmillan commissioned us to redesign the cover artwork.
\n\nThe story is about a twelve-year-old girl name Jade who is sent to spend the summer with her aunt in Wyoming by her parents. She meets a rebellious boy who called himself Roy Parker, after the legendary Butch Cassidy. Jade tries to be a good friend Roy, but worries about the trouble he might get her into while he tries to plan stunts worthy of Butch Cassidy himself.\n
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_teaser.png"
},
"views_count": 1548,
"likes_count": 177,
"comments_count": 5,
"attachments_count": 1,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T16:50:48Z",
"updated_at": "2016-03-29T16:53:16Z",
"html_url": "https://dribbble.com/shots/2619340-Skies-Like-These",
"attachments_url": "https://api.dribbble.com/v1/shots/2619340/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619340/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619340/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619340/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619340/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619340/rebounds",
"animated": false,
"tags": [
"book",
"book cover",
"cover artwork",
"cover design",
"cowboy hat",
"illustration",
"mountain",
"planets",
"sky",
"stars"
],
"user": {
"id": 44585,
"name": "Brad Woodard",
"username": "bradwwoodard",
"html_url": "https://dribbble.com/bradwwoodard",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/44585/avatars/normal/593686b9b9c0d2b6a496d8404f24ce1f.png?1444862250",
"bio": "Designer • Illustrator • Braver of the Woods",
"location": "Austin, TX",
"links": {
"web": "http://www.bravethewoods.com/",
"twitter": "https://twitter.com/brave_the_woods"
},
"buckets_count": 1,
"comments_received_count": 2598,
"followers_count": 8556,
"followings_count": 412,
"likes_count": 2285,
"likes_received_count": 45938,
"projects_count": 21,
"rebounds_received_count": 16,
"shots_count": 324,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/44585/buckets",
"followers_url": "https://api.dribbble.com/v1/users/44585/followers",
"following_url": "https://api.dribbble.com/v1/users/44585/following",
"likes_url": "https://api.dribbble.com/v1/users/44585/likes",
"projects_url": "https://api.dribbble.com/v1/users/44585/projects",
"shots_url": "https://api.dribbble.com/v1/users/44585/shots",
"teams_url": "https://api.dribbble.com/v1/users/44585/teams",
"created_at": "2011-07-08T15:47:58Z",
"updated_at": "2016-03-29T16:53:16Z"
},
"team": null
},
{
"id": 2619544,
"title": "Robinhood",
"description": "Robinhood integrations illustration.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_teaser.png"
},
"views_count": 1530,
"likes_count": 177,
"comments_count": 6,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T18:24:59Z",
"updated_at": "2016-03-29T18:26:47Z",
"html_url": "https://dribbble.com/shots/2619544-Robinhood",
"attachments_url": "https://api.dribbble.com/v1/shots/2619544/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619544/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619544/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619544/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619544/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619544/rebounds",
"animated": false,
"tags": [
"chart",
"finance",
"illustration",
"money",
"stock"
],
"user": {
"id": 4598,
"name": "Ty Wilkins",
"username": "tywilkins",
"html_url": "https://dribbble.com/tywilkins",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/4598/avatars/normal/fox2.jpg?1391573055",
"bio": "hello@tywilkins.com",
"location": "San Francisco, CA",
"links": {
"web": "http://www.tywilkins.com",
"twitter": "https://twitter.com/tywilkins"
},
"buckets_count": 0,
"comments_received_count": 1080,
"followers_count": 8222,
"followings_count": 527,
"likes_count": 0,
"likes_received_count": 21359,
"projects_count": 8,
"rebounds_received_count": 0,
"shots_count": 97,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/4598/buckets",
"followers_url": "https://api.dribbble.com/v1/users/4598/followers",
"following_url": "https://api.dribbble.com/v1/users/4598/following",
"likes_url": "https://api.dribbble.com/v1/users/4598/likes",
"projects_url": "https://api.dribbble.com/v1/users/4598/projects",
"shots_url": "https://api.dribbble.com/v1/users/4598/shots",
"teams_url": "https://api.dribbble.com/v1/users/4598/teams",
"created_at": "2010-09-30T20:31:02Z",
"updated_at": "2016-03-29T18:27:54Z"
},
"team": null
},
{
"id": 2619187,
"title": "Confidential iPad App part #2",
"description": "Over the holidays, Rally built an iPad app for a confidential client and conference. This is video directly from interacting with the native iOS app.
\n\nMyself, @Geof Crowl , and Wes tackled the project in just 15 days. It was intense but fun. Geof and I did the design and helped with layout in Xcode using Nibs. Wes built the globe and the data visualizations from a json file using our own Open GL globe library we've been building on an off for the past year.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally.gif",
"normal": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_1x.gif",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_teaser.gif"
},
"views_count": 3205,
"likes_count": 183,
"comments_count": 9,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 20,
"created_at": "2016-03-29T15:50:05Z",
"updated_at": "2016-03-29T15:51:33Z",
"html_url": "https://dribbble.com/shots/2619187-Confidential-iPad-App-part-2",
"attachments_url": "https://api.dribbble.com/v1/shots/2619187/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619187/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619187/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619187/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619187/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619187/rebounds",
"animated": true,
"tags": [
],
"user": {
"id": 3816,
"name": "Ben Cline",
"username": "letsgorally",
"html_url": "https://dribbble.com/letsgorally",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/3816/avatars/normal/bb00fd14001a8cdd5e0e354df52a7fa4.png?1450769044",
"bio": "@RALLY Co-Founder / Designer",
"location": "Salt Lake City",
"links": {
"web": "http://beta.rallyinteractive.com",
"twitter": "https://twitter.com/yocline"
},
"buckets_count": 3,
"comments_received_count": 4525,
"followers_count": 30105,
"followings_count": 241,
"likes_count": 6878,
"likes_received_count": 87892,
"projects_count": 10,
"rebounds_received_count": 28,
"shots_count": 257,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/3816/buckets",
"followers_url": "https://api.dribbble.com/v1/users/3816/followers",
"following_url": "https://api.dribbble.com/v1/users/3816/following",
"likes_url": "https://api.dribbble.com/v1/users/3816/likes",
"projects_url": "https://api.dribbble.com/v1/users/3816/projects",
"shots_url": "https://api.dribbble.com/v1/users/3816/shots",
"teams_url": "https://api.dribbble.com/v1/users/3816/teams",
"created_at": "2010-07-30T17:30:31Z",
"updated_at": "2016-03-29T15:51:33Z"
},
"team": {
"id": 559317,
"name": "RALLY",
"username": "rally",
"html_url": "https://dribbble.com/rally",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/559317/avatars/normal/rally_logo.png?1398641637",
"bio": "Interactive Studio. Design & Development",
"location": "Salt Lake City",
"links": {
"web": "http://beta.rallyinteractive.com",
"twitter": "https://twitter.com/letsgorally"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 8281,
"followings_count": 6,
"likes_count": 73,
"likes_received_count": 0,
"projects_count": 14,
"rebounds_received_count": 0,
"shots_count": 273,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/559317/buckets",
"followers_url": "https://api.dribbble.com/v1/users/559317/followers",
"following_url": "https://api.dribbble.com/v1/users/559317/following",
"likes_url": "https://api.dribbble.com/v1/users/559317/likes",
"projects_url": "https://api.dribbble.com/v1/users/559317/projects",
"shots_url": "https://api.dribbble.com/v1/users/559317/shots",
"created_at": "2014-04-27T23:31:42Z",
"updated_at": "2016-03-29T15:51:33Z",
"members_count": 5,
"members_url": "https://api.dribbble.com/v1/teams/559317/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/559317/shots"
}
},
{
"id": 2619200,
"title": "Eilean Donan Castle",
"description": "Day 209/365
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_teaser.jpg"
},
"views_count": 1434,
"likes_count": 162,
"comments_count": 4,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T15:54:42Z",
"updated_at": "2016-03-29T15:55:23Z",
"html_url": "https://dribbble.com/shots/2619200-Eilean-Donan-Castle",
"attachments_url": "https://api.dribbble.com/v1/shots/2619200/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619200/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619200/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619200/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619200/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619200/rebounds",
"rebound_source_url": "https://api.dribbble.com/v1/shots/2614735",
"animated": false,
"tags": [
"icon",
"illustration",
"lake",
"scotland",
"vector"
],
"user": {
"id": 283823,
"name": "Scott Tusk",
"username": "Tusk",
"html_url": "https://dribbble.com/Tusk",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/283823/avatars/normal/c71f583fd2f781e48da28697c6ec2211.jpg?1456193406",
"bio": "",
"location": "Chicago",
"links": {
},
"buckets_count": 0,
"comments_received_count": 1118,
"followers_count": 5013,
"followings_count": 812,
"likes_count": 2295,
"likes_received_count": 45133,
"projects_count": 1,
"rebounds_received_count": 214,
"shots_count": 282,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/283823/buckets",
"followers_url": "https://api.dribbble.com/v1/users/283823/followers",
"following_url": "https://api.dribbble.com/v1/users/283823/following",
"likes_url": "https://api.dribbble.com/v1/users/283823/likes",
"projects_url": "https://api.dribbble.com/v1/users/283823/projects",
"shots_url": "https://api.dribbble.com/v1/users/283823/shots",
"teams_url": "https://api.dribbble.com/v1/users/283823/teams",
"created_at": "2013-02-17T16:32:29Z",
"updated_at": "2016-03-29T15:55:23Z"
},
"team": null
},
{
"id": 2619378,
"title": "Infinite Coffee",
"description": "It's Monday, I need coffee. Forever.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_teaser.jpg"
},
"views_count": 1301,
"likes_count": 146,
"comments_count": 6,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 2,
"created_at": "2016-03-29T17:11:50Z",
"updated_at": "2016-03-29T17:18:17Z",
"html_url": "https://dribbble.com/shots/2619378-Infinite-Coffee",
"attachments_url": "https://api.dribbble.com/v1/shots/2619378/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619378/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619378/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619378/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619378/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619378/rebounds",
"animated": false,
"tags": [
"8",
"coffee",
"cup",
"food",
"geometric",
"illustration",
"infinite",
"kite",
"liquid",
"mug",
"stroke"
],
"user": {
"id": 60266,
"name": "Gustavo Zambelli",
"username": "zamax",
"html_url": "https://dribbble.com/zamax",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/60266/avatars/normal/83d4ac61d50bf5b2fedc9f9cc45a62d9.png?1453312126",
"bio": "Hi, I'm Lead of illustration at @aerolab & Superman at @RicosQuesos ",
"location": "Neuquén, Argentina.",
"links": {
"web": "http://zamax.tumblr.com",
"twitter": "https://twitter.com/zamax4"
},
"buckets_count": 19,
"comments_received_count": 1645,
"followers_count": 4198,
"followings_count": 1253,
"likes_count": 8828,
"likes_received_count": 36018,
"projects_count": 4,
"rebounds_received_count": 133,
"shots_count": 305,
"teams_count": 4,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/60266/buckets",
"followers_url": "https://api.dribbble.com/v1/users/60266/followers",
"following_url": "https://api.dribbble.com/v1/users/60266/following",
"likes_url": "https://api.dribbble.com/v1/users/60266/likes",
"projects_url": "https://api.dribbble.com/v1/users/60266/projects",
"shots_url": "https://api.dribbble.com/v1/users/60266/shots",
"teams_url": "https://api.dribbble.com/v1/users/60266/teams",
"created_at": "2011-09-07T19:27:31Z",
"updated_at": "2016-03-29T17:18:17Z"
},
"team": {
"id": 171431,
"name": "Aerolab",
"username": "aerolab",
"html_url": "https://dribbble.com/aerolab",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/171431/avatars/normal/1283d5fbcd21a809d0cdc2f96a560096.png?1458077891",
"bio": "We design and develop beautiful digital products for startups and leading brands.",
"location": "Buenos Aires - San Francisco",
"links": {
"web": "http://aerolab.co",
"twitter": "https://twitter.com/aerolab"
},
"buckets_count": 5,
"comments_received_count": 157,
"followers_count": 3845,
"followings_count": 128,
"likes_count": 4228,
"likes_received_count": 2121,
"projects_count": 24,
"rebounds_received_count": 2,
"shots_count": 579,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/171431/buckets",
"followers_url": "https://api.dribbble.com/v1/users/171431/followers",
"following_url": "https://api.dribbble.com/v1/users/171431/following",
"likes_url": "https://api.dribbble.com/v1/users/171431/likes",
"projects_url": "https://api.dribbble.com/v1/users/171431/projects",
"shots_url": "https://api.dribbble.com/v1/users/171431/shots",
"created_at": "2012-07-04T02:31:07Z",
"updated_at": "2016-03-29T17:18:17Z",
"members_count": 21,
"members_url": "https://api.dribbble.com/v1/teams/171431/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/171431/shots"
}
},
{
"id": 2619645,
"title": "Hello, Is It Me You're Looking For?",
"description": "I had the privilege of getting to collaborate with @Jordan Wade on a hero illustration for his SVG post. And let me tell you, watching your work come alive with CSS and JS is pretty much the jam.
\n\nCheck it out all alive n' stuff!
\n\nGo read about why you should learn more about SVG for the web .
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_teaser.png"
},
"views_count": 1771,
"likes_count": 146,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 1,
"buckets_count": 2,
"created_at": "2016-03-29T19:12:57Z",
"updated_at": "2016-03-29T20:26:49Z",
"html_url": "https://dribbble.com/shots/2619645-Hello-Is-It-Me-You-re-Looking-For",
"attachments_url": "https://api.dribbble.com/v1/shots/2619645/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619645/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619645/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619645/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619645/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619645/rebounds",
"animated": false,
"tags": [
"hello"
],
"user": {
"id": 13774,
"name": "Justin Mezzell",
"username": "JustinMezzell",
"html_url": "https://dribbble.com/JustinMezzell",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/13774/avatars/normal/Me_Web.jpg?1380768479",
"bio": "Designer? Illustrator? Why not. Directing Art at @codeschool .",
"location": "Orlando, FL",
"links": {
"web": "http://justinmezzell.com/",
"twitter": "https://twitter.com/JustinMezzell"
},
"buckets_count": 0,
"comments_received_count": 5736,
"followers_count": 31449,
"followings_count": 713,
"likes_count": 5548,
"likes_received_count": 113425,
"projects_count": 0,
"rebounds_received_count": 55,
"shots_count": 312,
"teams_count": 4,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/13774/buckets",
"followers_url": "https://api.dribbble.com/v1/users/13774/followers",
"following_url": "https://api.dribbble.com/v1/users/13774/following",
"likes_url": "https://api.dribbble.com/v1/users/13774/likes",
"projects_url": "https://api.dribbble.com/v1/users/13774/projects",
"shots_url": "https://api.dribbble.com/v1/users/13774/shots",
"teams_url": "https://api.dribbble.com/v1/users/13774/teams",
"created_at": "2011-01-26T06:58:50Z",
"updated_at": "2016-03-29T20:26:49Z"
},
"team": {
"id": 333539,
"name": "Code School",
"username": "codeschool",
"html_url": "https://dribbble.com/codeschool",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/333539/avatars/normal/329ac818d30ca1a7b900c09b105ce277.jpg?1410890340",
"bio": "Code School teaches web technologies in the comfort of your browser with video lessons, coding challenges, and screencasts.",
"location": "Orlando, FL",
"links": {
"web": "http://codeschool.com",
"twitter": "https://twitter.com/codeschool"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 3057,
"followings_count": 13,
"likes_count": 1,
"likes_received_count": 0,
"projects_count": 0,
"rebounds_received_count": 0,
"shots_count": 154,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/333539/buckets",
"followers_url": "https://api.dribbble.com/v1/users/333539/followers",
"following_url": "https://api.dribbble.com/v1/users/333539/following",
"likes_url": "https://api.dribbble.com/v1/users/333539/likes",
"projects_url": "https://api.dribbble.com/v1/users/333539/projects",
"shots_url": "https://api.dribbble.com/v1/users/333539/shots",
"created_at": "2013-05-15T21:37:44Z",
"updated_at": "2016-03-29T20:26:49Z",
"members_count": 10,
"members_url": "https://api.dribbble.com/v1/teams/333539/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/333539/shots"
}
},
{
"id": 2619181,
"title": "Costa Rica",
"description": "Shirt graphic for offsite meeting in Costa Rica.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_teaser.png"
},
"views_count": 1261,
"likes_count": 136,
"comments_count": 7,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T15:48:25Z",
"updated_at": "2016-03-29T15:49:13Z",
"html_url": "https://dribbble.com/shots/2619181-Costa-Rica",
"attachments_url": "https://api.dribbble.com/v1/shots/2619181/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619181/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619181/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619181/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619181/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619181/rebounds",
"animated": false,
"tags": [
"bird",
"costa rica",
"design",
"illustration",
"leaf",
"toucan",
"tropical"
],
"user": {
"id": 21030,
"name": "Trevor Basset",
"username": "trevorbasset",
"html_url": "https://dribbble.com/trevorbasset",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/21030/avatars/normal/e9907b8b54ea842b30c5787ef95acc3a.png?1426787498",
"bio": "Design, art direction, illustration, birds. ",
"location": "Seattle, WA",
"links": {
"web": "http://www.trevorbasset.com",
"twitter": "https://twitter.com/trevorbasset"
},
"buckets_count": 0,
"comments_received_count": 244,
"followers_count": 1169,
"followings_count": 367,
"likes_count": 1204,
"likes_received_count": 3660,
"projects_count": 0,
"rebounds_received_count": 4,
"shots_count": 85,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/21030/buckets",
"followers_url": "https://api.dribbble.com/v1/users/21030/followers",
"following_url": "https://api.dribbble.com/v1/users/21030/following",
"likes_url": "https://api.dribbble.com/v1/users/21030/likes",
"projects_url": "https://api.dribbble.com/v1/users/21030/projects",
"shots_url": "https://api.dribbble.com/v1/users/21030/shots",
"teams_url": "https://api.dribbble.com/v1/users/21030/teams",
"created_at": "2011-03-03T20:05:14Z",
"updated_at": "2016-03-30T04:08:03Z"
},
"team": null
},
{
"id": 2619381,
"title": "Seaborn Oyster Co.",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg"
},
"views_count": 2166,
"likes_count": 235,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T17:12:41Z",
"updated_at": "2016-03-29T17:12:53Z",
"html_url": "https://dribbble.com/shots/2619381-Seaborn-Oyster-Co",
"attachments_url": "https://api.dribbble.com/v1/shots/2619381/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619381/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619381/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619381/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619381/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619381/rebounds",
"animated": false,
"tags": [
"charleston",
"company",
"ocean",
"oyster",
"sea",
"wave"
],
"user": {
"id": 52758,
"name": "Jay Fletcher",
"username": "jfletcherdesign",
"html_url": "https://dribbble.com/jfletcherdesign",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283",
"bio": "",
"location": "Charleston, SC",
"links": {
"web": "http://www.jfletcherdesign.com",
"twitter": "https://twitter.com/jfletcherdesign"
},
"buckets_count": 0,
"comments_received_count": 5239,
"followers_count": 13803,
"followings_count": 558,
"likes_count": 6531,
"likes_received_count": 104895,
"projects_count": 10,
"rebounds_received_count": 325,
"shots_count": 481,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/52758/buckets",
"followers_url": "https://api.dribbble.com/v1/users/52758/followers",
"following_url": "https://api.dribbble.com/v1/users/52758/following",
"likes_url": "https://api.dribbble.com/v1/users/52758/likes",
"projects_url": "https://api.dribbble.com/v1/users/52758/projects",
"shots_url": "https://api.dribbble.com/v1/users/52758/shots",
"teams_url": "https://api.dribbble.com/v1/users/52758/teams",
"created_at": "2011-08-13T23:30:38Z",
"updated_at": "2016-03-29T17:12:53Z"
},
"team": null
},
{
"id": 2619494,
"title": "Mystery Project 72.1",
"description": "We're excited to be onboard for a new year of Outside Lands festival branding! Stay tuned for weekly updates including Ranger Dave's new patch series, the 2016 lineup, and more!
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_teaser.jpg"
},
"views_count": 2304,
"likes_count": 252,
"comments_count": 4,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T18:05:57Z",
"updated_at": "2016-03-29T18:07:21Z",
"html_url": "https://dribbble.com/shots/2619494-Mystery-Project-72-1",
"attachments_url": "https://api.dribbble.com/v1/shots/2619494/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619494/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619494/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619494/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619494/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619494/rebounds",
"rebound_source_url": "https://api.dribbble.com/v1/shots/2454166",
"animated": false,
"tags": [
"badge",
"branding",
"bridge",
"city",
"dan kuhlken",
"dkng",
"logo",
"nathan goldman",
"patch",
"san francisco",
"vector"
],
"user": {
"id": 31348,
"name": "DKNG",
"username": "DKNG",
"html_url": "https://dribbble.com/DKNG",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/31348/avatars/original/dkng_twitter.jpg?1305140827",
"bio": "Established in 2005, DKNG is a design studio based in Los Angeles, California with a focus on the music and entertainment industries.",
"location": "Los Angeles, CA",
"links": {
"web": "http://www.dkngstudios.com",
"twitter": "https://twitter.com/DKNGstudios"
},
"buckets_count": 0,
"comments_received_count": 5274,
"followers_count": 24704,
"followings_count": 256,
"likes_count": 197,
"likes_received_count": 125646,
"projects_count": 47,
"rebounds_received_count": 324,
"shots_count": 479,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/31348/buckets",
"followers_url": "https://api.dribbble.com/v1/users/31348/followers",
"following_url": "https://api.dribbble.com/v1/users/31348/following",
"likes_url": "https://api.dribbble.com/v1/users/31348/likes",
"projects_url": "https://api.dribbble.com/v1/users/31348/projects",
"shots_url": "https://api.dribbble.com/v1/users/31348/shots",
"teams_url": "https://api.dribbble.com/v1/users/31348/teams",
"created_at": "2011-04-28T20:48:48Z",
"updated_at": "2016-03-29T18:07:21Z"
},
"team": null
},
{
"id": 2619183,
"title": "Bonsai",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_teaser.png"
},
"views_count": 2143,
"likes_count": 259,
"comments_count": 11,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 18,
"created_at": "2016-03-29T15:48:38Z",
"updated_at": "2016-03-29T15:49:04Z",
"html_url": "https://dribbble.com/shots/2619183-Bonsai",
"attachments_url": "https://api.dribbble.com/v1/shots/2619183/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619183/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619183/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619183/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619183/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619183/rebounds",
"animated": false,
"tags": [
"bonsai",
"illustration",
"nature",
"plant",
"pot",
"tree",
"zen"
],
"user": {
"id": 44323,
"name": "Zach Roszczewski",
"username": "ZachRoszczewski",
"html_url": "https://dribbble.com/ZachRoszczewski",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/44323/avatars/normal/18f509c70a25627b40d5e3499b1cba2f.png?1419195740",
"bio": "Iconographer & Illustrator. Creator of www.flaticons.co & www.mojiapp.net .",
"location": "Encinitas, California",
"links": {
"web": "http://zachroszczewski.com",
"twitter": "https://twitter.com/ZachRoszczewski"
},
"buckets_count": 10,
"comments_received_count": 1682,
"followers_count": 9067,
"followings_count": 1541,
"likes_count": 14094,
"likes_received_count": 34409,
"projects_count": 7,
"rebounds_received_count": 14,
"shots_count": 113,
"teams_count": 2,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/44323/buckets",
"followers_url": "https://api.dribbble.com/v1/users/44323/followers",
"following_url": "https://api.dribbble.com/v1/users/44323/following",
"likes_url": "https://api.dribbble.com/v1/users/44323/likes",
"projects_url": "https://api.dribbble.com/v1/users/44323/projects",
"shots_url": "https://api.dribbble.com/v1/users/44323/shots",
"teams_url": "https://api.dribbble.com/v1/users/44323/teams",
"created_at": "2011-07-07T14:49:07Z",
"updated_at": "2016-03-29T15:49:04Z"
},
"team": null
},
{
"id": 2619255,
"title": "Canvas—A new space for big ideas",
"description": "A month ago the our team launched Canvas, a product for brands to tell their story and highlight products. It's been amazing to see your excitement for the creative possibilities and we can't wait to see how you use it.
\n\nOne of the best aspects of working on ads at Facebook is striving to find the sweet spot between the goals of our advertisers and those of people browsing their feed. Canvas allows businesses to create a more compelling experience for people, and in turn provides people with an ad they actually enjoy. Stay tuned for more :)
\n\nIf your interested in learning more about Canvas, or building one, you should check out https://canvas.facebook.com/ \n To learn more about our process check out Jaime Rovira's medium post https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble.gif",
"normal": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_1x.gif",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_teaser.gif"
},
"views_count": 3502,
"likes_count": 262,
"comments_count": 9,
"attachments_count": 2,
"rebounds_count": 0,
"buckets_count": 12,
"created_at": "2016-03-29T16:18:33Z",
"updated_at": "2016-03-29T16:19:50Z",
"html_url": "https://dribbble.com/shots/2619255-Canvas-A-new-space-for-big-ideas",
"attachments_url": "https://api.dribbble.com/v1/shots/2619255/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619255/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619255/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619255/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619255/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619255/rebounds",
"animated": true,
"tags": [
"android",
"animation",
"creative",
"illustration",
"ios",
"mobile",
"tool"
],
"user": {
"id": 476251,
"name": "ali griffin",
"username": "aligdanger",
"html_url": "https://dribbble.com/aligdanger",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/476251/avatars/normal/ali.png?1404762398",
"bio": "Designing product @Facebook ",
"location": "San Francisco, CA",
"links": {
"twitter": "https://twitter.com/aligdanger"
},
"buckets_count": 0,
"comments_received_count": 203,
"followers_count": 513,
"followings_count": 289,
"likes_count": 1302,
"likes_received_count": 2487,
"projects_count": 3,
"rebounds_received_count": 9,
"shots_count": 22,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/476251/buckets",
"followers_url": "https://api.dribbble.com/v1/users/476251/followers",
"following_url": "https://api.dribbble.com/v1/users/476251/following",
"likes_url": "https://api.dribbble.com/v1/users/476251/likes",
"projects_url": "https://api.dribbble.com/v1/users/476251/projects",
"shots_url": "https://api.dribbble.com/v1/users/476251/shots",
"teams_url": "https://api.dribbble.com/v1/users/476251/teams",
"created_at": "2014-01-10T18:37:14Z",
"updated_at": "2016-03-30T04:07:49Z"
},
"team": {
"id": 333588,
"name": "Facebook",
"username": "Facebook",
"html_url": "https://dribbble.com/Facebook",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/333588/avatars/normal/9a9d5301e289975fa16abd070f1615c0.png?1440610176",
"bio": "",
"location": "1 Hacker Way, Menlo Park, CA",
"links": {
"web": "https://www.facebook.com/design",
"twitter": "https://twitter.com/facebookdesign"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 14039,
"followings_count": 0,
"likes_count": 2,
"likes_received_count": 0,
"projects_count": 0,
"rebounds_received_count": 0,
"shots_count": 121,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/333588/buckets",
"followers_url": "https://api.dribbble.com/v1/users/333588/followers",
"following_url": "https://api.dribbble.com/v1/users/333588/following",
"likes_url": "https://api.dribbble.com/v1/users/333588/likes",
"projects_url": "https://api.dribbble.com/v1/users/333588/projects",
"shots_url": "https://api.dribbble.com/v1/users/333588/shots",
"created_at": "2013-05-15T23:13:37Z",
"updated_at": "2016-03-30T04:07:49Z",
"members_count": 39,
"members_url": "https://api.dribbble.com/v1/teams/333588/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/333588/shots"
}
},
{
"id": 2619346,
"title": "Sunset",
"description": "Baker Beach sunset from this weekend.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_teaser.png"
},
"views_count": 2897,
"likes_count": 231,
"comments_count": 3,
"attachments_count": 1,
"rebounds_count": 0,
"buckets_count": 6,
"created_at": "2016-03-29T16:55:27Z",
"updated_at": "2016-03-29T16:56:47Z",
"html_url": "https://dribbble.com/shots/2619346-Sunset",
"attachments_url": "https://api.dribbble.com/v1/shots/2619346/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619346/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619346/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619346/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619346/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619346/rebounds",
"animated": false,
"tags": [
"beach",
"cartoon",
"comics",
"hand-darwn",
"illustration",
"nature",
"sketch",
"sunset"
],
"user": {
"id": 3460,
"name": "Ryan Putnam",
"username": "RypeArts",
"html_url": "https://dribbble.com/RypeArts",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/3460/avatars/normal/4ed7a7a4737e971e3fa37f0705f5cc51.png?1457564367",
"bio": "designer, illustrator, potter, and father",
"location": "San Francisco, CA",
"links": {
"web": "http://ryanputn.am",
"twitter": "https://twitter.com/RypeArts"
},
"buckets_count": 3,
"comments_received_count": 9722,
"followers_count": 46667,
"followings_count": 518,
"likes_count": 10207,
"likes_received_count": 211321,
"projects_count": 34,
"rebounds_received_count": 373,
"shots_count": 589,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/3460/buckets",
"followers_url": "https://api.dribbble.com/v1/users/3460/followers",
"following_url": "https://api.dribbble.com/v1/users/3460/following",
"likes_url": "https://api.dribbble.com/v1/users/3460/likes",
"projects_url": "https://api.dribbble.com/v1/users/3460/projects",
"shots_url": "https://api.dribbble.com/v1/users/3460/shots",
"teams_url": "https://api.dribbble.com/v1/users/3460/teams",
"created_at": "2010-07-16T12:48:16Z",
"updated_at": "2016-03-29T16:56:47Z"
},
"team": null
},
{
"id": 2619340,
"title": "Skies Like These ",
"description": "In anticipation for their release of the paperback version of the book, Skies Like These, Macmillan commissioned us to redesign the cover artwork.
\n\nThe story is about a twelve-year-old girl name Jade who is sent to spend the summer with her aunt in Wyoming by her parents. She meets a rebellious boy who called himself Roy Parker, after the legendary Butch Cassidy. Jade tries to be a good friend Roy, but worries about the trouble he might get her into while he tries to plan stunts worthy of Butch Cassidy himself.\n
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_teaser.png"
},
"views_count": 1548,
"likes_count": 177,
"comments_count": 5,
"attachments_count": 1,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T16:50:48Z",
"updated_at": "2016-03-29T16:53:16Z",
"html_url": "https://dribbble.com/shots/2619340-Skies-Like-These",
"attachments_url": "https://api.dribbble.com/v1/shots/2619340/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619340/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619340/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619340/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619340/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619340/rebounds",
"animated": false,
"tags": [
"book",
"book cover",
"cover artwork",
"cover design",
"cowboy hat",
"illustration",
"mountain",
"planets",
"sky",
"stars"
],
"user": {
"id": 44585,
"name": "Brad Woodard",
"username": "bradwwoodard",
"html_url": "https://dribbble.com/bradwwoodard",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/44585/avatars/normal/593686b9b9c0d2b6a496d8404f24ce1f.png?1444862250",
"bio": "Designer • Illustrator • Braver of the Woods",
"location": "Austin, TX",
"links": {
"web": "http://www.bravethewoods.com/",
"twitter": "https://twitter.com/brave_the_woods"
},
"buckets_count": 1,
"comments_received_count": 2598,
"followers_count": 8556,
"followings_count": 412,
"likes_count": 2285,
"likes_received_count": 45938,
"projects_count": 21,
"rebounds_received_count": 16,
"shots_count": 324,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/44585/buckets",
"followers_url": "https://api.dribbble.com/v1/users/44585/followers",
"following_url": "https://api.dribbble.com/v1/users/44585/following",
"likes_url": "https://api.dribbble.com/v1/users/44585/likes",
"projects_url": "https://api.dribbble.com/v1/users/44585/projects",
"shots_url": "https://api.dribbble.com/v1/users/44585/shots",
"teams_url": "https://api.dribbble.com/v1/users/44585/teams",
"created_at": "2011-07-08T15:47:58Z",
"updated_at": "2016-03-29T16:53:16Z"
},
"team": null
},
{
"id": 2619544,
"title": "Robinhood",
"description": "Robinhood integrations illustration.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_teaser.png"
},
"views_count": 1530,
"likes_count": 177,
"comments_count": 6,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T18:24:59Z",
"updated_at": "2016-03-29T18:26:47Z",
"html_url": "https://dribbble.com/shots/2619544-Robinhood",
"attachments_url": "https://api.dribbble.com/v1/shots/2619544/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619544/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619544/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619544/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619544/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619544/rebounds",
"animated": false,
"tags": [
"chart",
"finance",
"illustration",
"money",
"stock"
],
"user": {
"id": 4598,
"name": "Ty Wilkins",
"username": "tywilkins",
"html_url": "https://dribbble.com/tywilkins",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/4598/avatars/normal/fox2.jpg?1391573055",
"bio": "hello@tywilkins.com",
"location": "San Francisco, CA",
"links": {
"web": "http://www.tywilkins.com",
"twitter": "https://twitter.com/tywilkins"
},
"buckets_count": 0,
"comments_received_count": 1080,
"followers_count": 8222,
"followings_count": 527,
"likes_count": 0,
"likes_received_count": 21359,
"projects_count": 8,
"rebounds_received_count": 0,
"shots_count": 97,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/4598/buckets",
"followers_url": "https://api.dribbble.com/v1/users/4598/followers",
"following_url": "https://api.dribbble.com/v1/users/4598/following",
"likes_url": "https://api.dribbble.com/v1/users/4598/likes",
"projects_url": "https://api.dribbble.com/v1/users/4598/projects",
"shots_url": "https://api.dribbble.com/v1/users/4598/shots",
"teams_url": "https://api.dribbble.com/v1/users/4598/teams",
"created_at": "2010-09-30T20:31:02Z",
"updated_at": "2016-03-29T18:27:54Z"
},
"team": null
},
{
"id": 2619187,
"title": "Confidential iPad App part #2",
"description": "Over the holidays, Rally built an iPad app for a confidential client and conference. This is video directly from interacting with the native iOS app.
\n\nMyself, @Geof Crowl , and Wes tackled the project in just 15 days. It was intense but fun. Geof and I did the design and helped with layout in Xcode using Nibs. Wes built the globe and the data visualizations from a json file using our own Open GL globe library we've been building on an off for the past year.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally.gif",
"normal": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_1x.gif",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_teaser.gif"
},
"views_count": 3205,
"likes_count": 183,
"comments_count": 9,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 20,
"created_at": "2016-03-29T15:50:05Z",
"updated_at": "2016-03-29T15:51:33Z",
"html_url": "https://dribbble.com/shots/2619187-Confidential-iPad-App-part-2",
"attachments_url": "https://api.dribbble.com/v1/shots/2619187/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619187/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619187/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619187/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619187/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619187/rebounds",
"animated": true,
"tags": [
],
"user": {
"id": 3816,
"name": "Ben Cline",
"username": "letsgorally",
"html_url": "https://dribbble.com/letsgorally",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/3816/avatars/normal/bb00fd14001a8cdd5e0e354df52a7fa4.png?1450769044",
"bio": "@RALLY Co-Founder / Designer",
"location": "Salt Lake City",
"links": {
"web": "http://beta.rallyinteractive.com",
"twitter": "https://twitter.com/yocline"
},
"buckets_count": 3,
"comments_received_count": 4525,
"followers_count": 30105,
"followings_count": 241,
"likes_count": 6878,
"likes_received_count": 87892,
"projects_count": 10,
"rebounds_received_count": 28,
"shots_count": 257,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/3816/buckets",
"followers_url": "https://api.dribbble.com/v1/users/3816/followers",
"following_url": "https://api.dribbble.com/v1/users/3816/following",
"likes_url": "https://api.dribbble.com/v1/users/3816/likes",
"projects_url": "https://api.dribbble.com/v1/users/3816/projects",
"shots_url": "https://api.dribbble.com/v1/users/3816/shots",
"teams_url": "https://api.dribbble.com/v1/users/3816/teams",
"created_at": "2010-07-30T17:30:31Z",
"updated_at": "2016-03-29T15:51:33Z"
},
"team": {
"id": 559317,
"name": "RALLY",
"username": "rally",
"html_url": "https://dribbble.com/rally",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/559317/avatars/normal/rally_logo.png?1398641637",
"bio": "Interactive Studio. Design & Development",
"location": "Salt Lake City",
"links": {
"web": "http://beta.rallyinteractive.com",
"twitter": "https://twitter.com/letsgorally"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 8281,
"followings_count": 6,
"likes_count": 73,
"likes_received_count": 0,
"projects_count": 14,
"rebounds_received_count": 0,
"shots_count": 273,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/559317/buckets",
"followers_url": "https://api.dribbble.com/v1/users/559317/followers",
"following_url": "https://api.dribbble.com/v1/users/559317/following",
"likes_url": "https://api.dribbble.com/v1/users/559317/likes",
"projects_url": "https://api.dribbble.com/v1/users/559317/projects",
"shots_url": "https://api.dribbble.com/v1/users/559317/shots",
"created_at": "2014-04-27T23:31:42Z",
"updated_at": "2016-03-29T15:51:33Z",
"members_count": 5,
"members_url": "https://api.dribbble.com/v1/teams/559317/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/559317/shots"
}
},
{
"id": 2619200,
"title": "Eilean Donan Castle",
"description": "Day 209/365
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_teaser.jpg"
},
"views_count": 1434,
"likes_count": 162,
"comments_count": 4,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T15:54:42Z",
"updated_at": "2016-03-29T15:55:23Z",
"html_url": "https://dribbble.com/shots/2619200-Eilean-Donan-Castle",
"attachments_url": "https://api.dribbble.com/v1/shots/2619200/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619200/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619200/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619200/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619200/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619200/rebounds",
"rebound_source_url": "https://api.dribbble.com/v1/shots/2614735",
"animated": false,
"tags": [
"icon",
"illustration",
"lake",
"scotland",
"vector"
],
"user": {
"id": 283823,
"name": "Scott Tusk",
"username": "Tusk",
"html_url": "https://dribbble.com/Tusk",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/283823/avatars/normal/c71f583fd2f781e48da28697c6ec2211.jpg?1456193406",
"bio": "",
"location": "Chicago",
"links": {
},
"buckets_count": 0,
"comments_received_count": 1118,
"followers_count": 5013,
"followings_count": 812,
"likes_count": 2295,
"likes_received_count": 45133,
"projects_count": 1,
"rebounds_received_count": 214,
"shots_count": 282,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/283823/buckets",
"followers_url": "https://api.dribbble.com/v1/users/283823/followers",
"following_url": "https://api.dribbble.com/v1/users/283823/following",
"likes_url": "https://api.dribbble.com/v1/users/283823/likes",
"projects_url": "https://api.dribbble.com/v1/users/283823/projects",
"shots_url": "https://api.dribbble.com/v1/users/283823/shots",
"teams_url": "https://api.dribbble.com/v1/users/283823/teams",
"created_at": "2013-02-17T16:32:29Z",
"updated_at": "2016-03-29T15:55:23Z"
},
"team": null
},
{
"id": 2619378,
"title": "Infinite Coffee",
"description": "It's Monday, I need coffee. Forever.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_teaser.jpg"
},
"views_count": 1301,
"likes_count": 146,
"comments_count": 6,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 2,
"created_at": "2016-03-29T17:11:50Z",
"updated_at": "2016-03-29T17:18:17Z",
"html_url": "https://dribbble.com/shots/2619378-Infinite-Coffee",
"attachments_url": "https://api.dribbble.com/v1/shots/2619378/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619378/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619378/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619378/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619378/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619378/rebounds",
"animated": false,
"tags": [
"8",
"coffee",
"cup",
"food",
"geometric",
"illustration",
"infinite",
"kite",
"liquid",
"mug",
"stroke"
],
"user": {
"id": 60266,
"name": "Gustavo Zambelli",
"username": "zamax",
"html_url": "https://dribbble.com/zamax",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/60266/avatars/normal/83d4ac61d50bf5b2fedc9f9cc45a62d9.png?1453312126",
"bio": "Hi, I'm Lead of illustration at @aerolab & Superman at @RicosQuesos ",
"location": "Neuquén, Argentina.",
"links": {
"web": "http://zamax.tumblr.com",
"twitter": "https://twitter.com/zamax4"
},
"buckets_count": 19,
"comments_received_count": 1645,
"followers_count": 4198,
"followings_count": 1253,
"likes_count": 8828,
"likes_received_count": 36018,
"projects_count": 4,
"rebounds_received_count": 133,
"shots_count": 305,
"teams_count": 4,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/60266/buckets",
"followers_url": "https://api.dribbble.com/v1/users/60266/followers",
"following_url": "https://api.dribbble.com/v1/users/60266/following",
"likes_url": "https://api.dribbble.com/v1/users/60266/likes",
"projects_url": "https://api.dribbble.com/v1/users/60266/projects",
"shots_url": "https://api.dribbble.com/v1/users/60266/shots",
"teams_url": "https://api.dribbble.com/v1/users/60266/teams",
"created_at": "2011-09-07T19:27:31Z",
"updated_at": "2016-03-29T17:18:17Z"
},
"team": {
"id": 171431,
"name": "Aerolab",
"username": "aerolab",
"html_url": "https://dribbble.com/aerolab",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/171431/avatars/normal/1283d5fbcd21a809d0cdc2f96a560096.png?1458077891",
"bio": "We design and develop beautiful digital products for startups and leading brands.",
"location": "Buenos Aires - San Francisco",
"links": {
"web": "http://aerolab.co",
"twitter": "https://twitter.com/aerolab"
},
"buckets_count": 5,
"comments_received_count": 157,
"followers_count": 3845,
"followings_count": 128,
"likes_count": 4228,
"likes_received_count": 2121,
"projects_count": 24,
"rebounds_received_count": 2,
"shots_count": 579,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/171431/buckets",
"followers_url": "https://api.dribbble.com/v1/users/171431/followers",
"following_url": "https://api.dribbble.com/v1/users/171431/following",
"likes_url": "https://api.dribbble.com/v1/users/171431/likes",
"projects_url": "https://api.dribbble.com/v1/users/171431/projects",
"shots_url": "https://api.dribbble.com/v1/users/171431/shots",
"created_at": "2012-07-04T02:31:07Z",
"updated_at": "2016-03-29T17:18:17Z",
"members_count": 21,
"members_url": "https://api.dribbble.com/v1/teams/171431/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/171431/shots"
}
},
{
"id": 2619645,
"title": "Hello, Is It Me You're Looking For?",
"description": "I had the privilege of getting to collaborate with @Jordan Wade on a hero illustration for his SVG post. And let me tell you, watching your work come alive with CSS and JS is pretty much the jam.
\n\nCheck it out all alive n' stuff!
\n\nGo read about why you should learn more about SVG for the web .
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_teaser.png"
},
"views_count": 1771,
"likes_count": 146,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 1,
"buckets_count": 2,
"created_at": "2016-03-29T19:12:57Z",
"updated_at": "2016-03-29T20:26:49Z",
"html_url": "https://dribbble.com/shots/2619645-Hello-Is-It-Me-You-re-Looking-For",
"attachments_url": "https://api.dribbble.com/v1/shots/2619645/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619645/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619645/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619645/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619645/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619645/rebounds",
"animated": false,
"tags": [
"hello"
],
"user": {
"id": 13774,
"name": "Justin Mezzell",
"username": "JustinMezzell",
"html_url": "https://dribbble.com/JustinMezzell",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/13774/avatars/normal/Me_Web.jpg?1380768479",
"bio": "Designer? Illustrator? Why not. Directing Art at @codeschool .",
"location": "Orlando, FL",
"links": {
"web": "http://justinmezzell.com/",
"twitter": "https://twitter.com/JustinMezzell"
},
"buckets_count": 0,
"comments_received_count": 5736,
"followers_count": 31449,
"followings_count": 713,
"likes_count": 5548,
"likes_received_count": 113425,
"projects_count": 0,
"rebounds_received_count": 55,
"shots_count": 312,
"teams_count": 4,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/13774/buckets",
"followers_url": "https://api.dribbble.com/v1/users/13774/followers",
"following_url": "https://api.dribbble.com/v1/users/13774/following",
"likes_url": "https://api.dribbble.com/v1/users/13774/likes",
"projects_url": "https://api.dribbble.com/v1/users/13774/projects",
"shots_url": "https://api.dribbble.com/v1/users/13774/shots",
"teams_url": "https://api.dribbble.com/v1/users/13774/teams",
"created_at": "2011-01-26T06:58:50Z",
"updated_at": "2016-03-29T20:26:49Z"
},
"team": {
"id": 333539,
"name": "Code School",
"username": "codeschool",
"html_url": "https://dribbble.com/codeschool",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/333539/avatars/normal/329ac818d30ca1a7b900c09b105ce277.jpg?1410890340",
"bio": "Code School teaches web technologies in the comfort of your browser with video lessons, coding challenges, and screencasts.",
"location": "Orlando, FL",
"links": {
"web": "http://codeschool.com",
"twitter": "https://twitter.com/codeschool"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 3057,
"followings_count": 13,
"likes_count": 1,
"likes_received_count": 0,
"projects_count": 0,
"rebounds_received_count": 0,
"shots_count": 154,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/333539/buckets",
"followers_url": "https://api.dribbble.com/v1/users/333539/followers",
"following_url": "https://api.dribbble.com/v1/users/333539/following",
"likes_url": "https://api.dribbble.com/v1/users/333539/likes",
"projects_url": "https://api.dribbble.com/v1/users/333539/projects",
"shots_url": "https://api.dribbble.com/v1/users/333539/shots",
"created_at": "2013-05-15T21:37:44Z",
"updated_at": "2016-03-29T20:26:49Z",
"members_count": 10,
"members_url": "https://api.dribbble.com/v1/teams/333539/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/333539/shots"
}
},
{
"id": 2619181,
"title": "Costa Rica",
"description": "Shirt graphic for offsite meeting in Costa Rica.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_teaser.png"
},
"views_count": 1261,
"likes_count": 136,
"comments_count": 7,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T15:48:25Z",
"updated_at": "2016-03-29T15:49:13Z",
"html_url": "https://dribbble.com/shots/2619181-Costa-Rica",
"attachments_url": "https://api.dribbble.com/v1/shots/2619181/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619181/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619181/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619181/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619181/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619181/rebounds",
"animated": false,
"tags": [
"bird",
"costa rica",
"design",
"illustration",
"leaf",
"toucan",
"tropical"
],
"user": {
"id": 21030,
"name": "Trevor Basset",
"username": "trevorbasset",
"html_url": "https://dribbble.com/trevorbasset",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/21030/avatars/normal/e9907b8b54ea842b30c5787ef95acc3a.png?1426787498",
"bio": "Design, art direction, illustration, birds. ",
"location": "Seattle, WA",
"links": {
"web": "http://www.trevorbasset.com",
"twitter": "https://twitter.com/trevorbasset"
},
"buckets_count": 0,
"comments_received_count": 244,
"followers_count": 1169,
"followings_count": 367,
"likes_count": 1204,
"likes_received_count": 3660,
"projects_count": 0,
"rebounds_received_count": 4,
"shots_count": 85,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/21030/buckets",
"followers_url": "https://api.dribbble.com/v1/users/21030/followers",
"following_url": "https://api.dribbble.com/v1/users/21030/following",
"likes_url": "https://api.dribbble.com/v1/users/21030/likes",
"projects_url": "https://api.dribbble.com/v1/users/21030/projects",
"shots_url": "https://api.dribbble.com/v1/users/21030/shots",
"teams_url": "https://api.dribbble.com/v1/users/21030/teams",
"created_at": "2011-03-03T20:05:14Z",
"updated_at": "2016-03-30T04:08:03Z"
},
"team": null
},
{
"id": 2619381,
"title": "Seaborn Oyster Co.",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg"
},
"views_count": 2166,
"likes_count": 235,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T17:12:41Z",
"updated_at": "2016-03-29T17:12:53Z",
"html_url": "https://dribbble.com/shots/2619381-Seaborn-Oyster-Co",
"attachments_url": "https://api.dribbble.com/v1/shots/2619381/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619381/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619381/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619381/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619381/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619381/rebounds",
"animated": false,
"tags": [
"charleston",
"company",
"ocean",
"oyster",
"sea",
"wave"
],
"user": {
"id": 52758,
"name": "Jay Fletcher",
"username": "jfletcherdesign",
"html_url": "https://dribbble.com/jfletcherdesign",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283",
"bio": "",
"location": "Charleston, SC",
"links": {
"web": "http://www.jfletcherdesign.com",
"twitter": "https://twitter.com/jfletcherdesign"
},
"buckets_count": 0,
"comments_received_count": 5239,
"followers_count": 13803,
"followings_count": 558,
"likes_count": 6531,
"likes_received_count": 104895,
"projects_count": 10,
"rebounds_received_count": 325,
"shots_count": 481,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/52758/buckets",
"followers_url": "https://api.dribbble.com/v1/users/52758/followers",
"following_url": "https://api.dribbble.com/v1/users/52758/following",
"likes_url": "https://api.dribbble.com/v1/users/52758/likes",
"projects_url": "https://api.dribbble.com/v1/users/52758/projects",
"shots_url": "https://api.dribbble.com/v1/users/52758/shots",
"teams_url": "https://api.dribbble.com/v1/users/52758/teams",
"created_at": "2011-08-13T23:30:38Z",
"updated_at": "2016-03-29T17:12:53Z"
},
"team": null
},
{
"id": 2619494,
"title": "Mystery Project 72.1",
"description": "We're excited to be onboard for a new year of Outside Lands festival branding! Stay tuned for weekly updates including Ranger Dave's new patch series, the 2016 lineup, and more!
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_teaser.jpg"
},
"views_count": 2304,
"likes_count": 252,
"comments_count": 4,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T18:05:57Z",
"updated_at": "2016-03-29T18:07:21Z",
"html_url": "https://dribbble.com/shots/2619494-Mystery-Project-72-1",
"attachments_url": "https://api.dribbble.com/v1/shots/2619494/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619494/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619494/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619494/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619494/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619494/rebounds",
"rebound_source_url": "https://api.dribbble.com/v1/shots/2454166",
"animated": false,
"tags": [
"badge",
"branding",
"bridge",
"city",
"dan kuhlken",
"dkng",
"logo",
"nathan goldman",
"patch",
"san francisco",
"vector"
],
"user": {
"id": 31348,
"name": "DKNG",
"username": "DKNG",
"html_url": "https://dribbble.com/DKNG",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/31348/avatars/original/dkng_twitter.jpg?1305140827",
"bio": "Established in 2005, DKNG is a design studio based in Los Angeles, California with a focus on the music and entertainment industries.",
"location": "Los Angeles, CA",
"links": {
"web": "http://www.dkngstudios.com",
"twitter": "https://twitter.com/DKNGstudios"
},
"buckets_count": 0,
"comments_received_count": 5274,
"followers_count": 24704,
"followings_count": 256,
"likes_count": 197,
"likes_received_count": 125646,
"projects_count": 47,
"rebounds_received_count": 324,
"shots_count": 479,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/31348/buckets",
"followers_url": "https://api.dribbble.com/v1/users/31348/followers",
"following_url": "https://api.dribbble.com/v1/users/31348/following",
"likes_url": "https://api.dribbble.com/v1/users/31348/likes",
"projects_url": "https://api.dribbble.com/v1/users/31348/projects",
"shots_url": "https://api.dribbble.com/v1/users/31348/shots",
"teams_url": "https://api.dribbble.com/v1/users/31348/teams",
"created_at": "2011-04-28T20:48:48Z",
"updated_at": "2016-03-29T18:07:21Z"
},
"team": null
},
{
"id": 2619183,
"title": "Bonsai",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_teaser.png"
},
"views_count": 2143,
"likes_count": 259,
"comments_count": 11,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 18,
"created_at": "2016-03-29T15:48:38Z",
"updated_at": "2016-03-29T15:49:04Z",
"html_url": "https://dribbble.com/shots/2619183-Bonsai",
"attachments_url": "https://api.dribbble.com/v1/shots/2619183/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619183/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619183/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619183/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619183/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619183/rebounds",
"animated": false,
"tags": [
"bonsai",
"illustration",
"nature",
"plant",
"pot",
"tree",
"zen"
],
"user": {
"id": 44323,
"name": "Zach Roszczewski",
"username": "ZachRoszczewski",
"html_url": "https://dribbble.com/ZachRoszczewski",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/44323/avatars/normal/18f509c70a25627b40d5e3499b1cba2f.png?1419195740",
"bio": "Iconographer & Illustrator. Creator of www.flaticons.co & www.mojiapp.net .",
"location": "Encinitas, California",
"links": {
"web": "http://zachroszczewski.com",
"twitter": "https://twitter.com/ZachRoszczewski"
},
"buckets_count": 10,
"comments_received_count": 1682,
"followers_count": 9067,
"followings_count": 1541,
"likes_count": 14094,
"likes_received_count": 34409,
"projects_count": 7,
"rebounds_received_count": 14,
"shots_count": 113,
"teams_count": 2,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/44323/buckets",
"followers_url": "https://api.dribbble.com/v1/users/44323/followers",
"following_url": "https://api.dribbble.com/v1/users/44323/following",
"likes_url": "https://api.dribbble.com/v1/users/44323/likes",
"projects_url": "https://api.dribbble.com/v1/users/44323/projects",
"shots_url": "https://api.dribbble.com/v1/users/44323/shots",
"teams_url": "https://api.dribbble.com/v1/users/44323/teams",
"created_at": "2011-07-07T14:49:07Z",
"updated_at": "2016-03-29T15:49:04Z"
},
"team": null
},
{
"id": 2619255,
"title": "Canvas—A new space for big ideas",
"description": "A month ago the our team launched Canvas, a product for brands to tell their story and highlight products. It's been amazing to see your excitement for the creative possibilities and we can't wait to see how you use it.
\n\nOne of the best aspects of working on ads at Facebook is striving to find the sweet spot between the goals of our advertisers and those of people browsing their feed. Canvas allows businesses to create a more compelling experience for people, and in turn provides people with an ad they actually enjoy. Stay tuned for more :)
\n\nIf your interested in learning more about Canvas, or building one, you should check out https://canvas.facebook.com/ \n To learn more about our process check out Jaime Rovira's medium post https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble.gif",
"normal": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_1x.gif",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_teaser.gif"
},
"views_count": 3502,
"likes_count": 262,
"comments_count": 9,
"attachments_count": 2,
"rebounds_count": 0,
"buckets_count": 12,
"created_at": "2016-03-29T16:18:33Z",
"updated_at": "2016-03-29T16:19:50Z",
"html_url": "https://dribbble.com/shots/2619255-Canvas-A-new-space-for-big-ideas",
"attachments_url": "https://api.dribbble.com/v1/shots/2619255/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619255/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619255/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619255/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619255/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619255/rebounds",
"animated": true,
"tags": [
"android",
"animation",
"creative",
"illustration",
"ios",
"mobile",
"tool"
],
"user": {
"id": 476251,
"name": "ali griffin",
"username": "aligdanger",
"html_url": "https://dribbble.com/aligdanger",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/476251/avatars/normal/ali.png?1404762398",
"bio": "Designing product @Facebook ",
"location": "San Francisco, CA",
"links": {
"twitter": "https://twitter.com/aligdanger"
},
"buckets_count": 0,
"comments_received_count": 203,
"followers_count": 513,
"followings_count": 289,
"likes_count": 1302,
"likes_received_count": 2487,
"projects_count": 3,
"rebounds_received_count": 9,
"shots_count": 22,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/476251/buckets",
"followers_url": "https://api.dribbble.com/v1/users/476251/followers",
"following_url": "https://api.dribbble.com/v1/users/476251/following",
"likes_url": "https://api.dribbble.com/v1/users/476251/likes",
"projects_url": "https://api.dribbble.com/v1/users/476251/projects",
"shots_url": "https://api.dribbble.com/v1/users/476251/shots",
"teams_url": "https://api.dribbble.com/v1/users/476251/teams",
"created_at": "2014-01-10T18:37:14Z",
"updated_at": "2016-03-30T04:07:49Z"
},
"team": {
"id": 333588,
"name": "Facebook",
"username": "Facebook",
"html_url": "https://dribbble.com/Facebook",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/333588/avatars/normal/9a9d5301e289975fa16abd070f1615c0.png?1440610176",
"bio": "",
"location": "1 Hacker Way, Menlo Park, CA",
"links": {
"web": "https://www.facebook.com/design",
"twitter": "https://twitter.com/facebookdesign"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 14039,
"followings_count": 0,
"likes_count": 2,
"likes_received_count": 0,
"projects_count": 0,
"rebounds_received_count": 0,
"shots_count": 121,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/333588/buckets",
"followers_url": "https://api.dribbble.com/v1/users/333588/followers",
"following_url": "https://api.dribbble.com/v1/users/333588/following",
"likes_url": "https://api.dribbble.com/v1/users/333588/likes",
"projects_url": "https://api.dribbble.com/v1/users/333588/projects",
"shots_url": "https://api.dribbble.com/v1/users/333588/shots",
"created_at": "2013-05-15T23:13:37Z",
"updated_at": "2016-03-30T04:07:49Z",
"members_count": 39,
"members_url": "https://api.dribbble.com/v1/teams/333588/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/333588/shots"
}
},
{
"id": 2619346,
"title": "Sunset",
"description": "Baker Beach sunset from this weekend.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_teaser.png"
},
"views_count": 2897,
"likes_count": 231,
"comments_count": 3,
"attachments_count": 1,
"rebounds_count": 0,
"buckets_count": 6,
"created_at": "2016-03-29T16:55:27Z",
"updated_at": "2016-03-29T16:56:47Z",
"html_url": "https://dribbble.com/shots/2619346-Sunset",
"attachments_url": "https://api.dribbble.com/v1/shots/2619346/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619346/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619346/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619346/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619346/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619346/rebounds",
"animated": false,
"tags": [
"beach",
"cartoon",
"comics",
"hand-darwn",
"illustration",
"nature",
"sketch",
"sunset"
],
"user": {
"id": 3460,
"name": "Ryan Putnam",
"username": "RypeArts",
"html_url": "https://dribbble.com/RypeArts",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/3460/avatars/normal/4ed7a7a4737e971e3fa37f0705f5cc51.png?1457564367",
"bio": "designer, illustrator, potter, and father",
"location": "San Francisco, CA",
"links": {
"web": "http://ryanputn.am",
"twitter": "https://twitter.com/RypeArts"
},
"buckets_count": 3,
"comments_received_count": 9722,
"followers_count": 46667,
"followings_count": 518,
"likes_count": 10207,
"likes_received_count": 211321,
"projects_count": 34,
"rebounds_received_count": 373,
"shots_count": 589,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/3460/buckets",
"followers_url": "https://api.dribbble.com/v1/users/3460/followers",
"following_url": "https://api.dribbble.com/v1/users/3460/following",
"likes_url": "https://api.dribbble.com/v1/users/3460/likes",
"projects_url": "https://api.dribbble.com/v1/users/3460/projects",
"shots_url": "https://api.dribbble.com/v1/users/3460/shots",
"teams_url": "https://api.dribbble.com/v1/users/3460/teams",
"created_at": "2010-07-16T12:48:16Z",
"updated_at": "2016-03-29T16:56:47Z"
},
"team": null
},
{
"id": 2619340,
"title": "Skies Like These ",
"description": "In anticipation for their release of the paperback version of the book, Skies Like These, Macmillan commissioned us to redesign the cover artwork.
\n\nThe story is about a twelve-year-old girl name Jade who is sent to spend the summer with her aunt in Wyoming by her parents. She meets a rebellious boy who called himself Roy Parker, after the legendary Butch Cassidy. Jade tries to be a good friend Roy, but worries about the trouble he might get her into while he tries to plan stunts worthy of Butch Cassidy himself.\n
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_teaser.png"
},
"views_count": 1548,
"likes_count": 177,
"comments_count": 5,
"attachments_count": 1,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T16:50:48Z",
"updated_at": "2016-03-29T16:53:16Z",
"html_url": "https://dribbble.com/shots/2619340-Skies-Like-These",
"attachments_url": "https://api.dribbble.com/v1/shots/2619340/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619340/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619340/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619340/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619340/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619340/rebounds",
"animated": false,
"tags": [
"book",
"book cover",
"cover artwork",
"cover design",
"cowboy hat",
"illustration",
"mountain",
"planets",
"sky",
"stars"
],
"user": {
"id": 44585,
"name": "Brad Woodard",
"username": "bradwwoodard",
"html_url": "https://dribbble.com/bradwwoodard",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/44585/avatars/normal/593686b9b9c0d2b6a496d8404f24ce1f.png?1444862250",
"bio": "Designer • Illustrator • Braver of the Woods",
"location": "Austin, TX",
"links": {
"web": "http://www.bravethewoods.com/",
"twitter": "https://twitter.com/brave_the_woods"
},
"buckets_count": 1,
"comments_received_count": 2598,
"followers_count": 8556,
"followings_count": 412,
"likes_count": 2285,
"likes_received_count": 45938,
"projects_count": 21,
"rebounds_received_count": 16,
"shots_count": 324,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/44585/buckets",
"followers_url": "https://api.dribbble.com/v1/users/44585/followers",
"following_url": "https://api.dribbble.com/v1/users/44585/following",
"likes_url": "https://api.dribbble.com/v1/users/44585/likes",
"projects_url": "https://api.dribbble.com/v1/users/44585/projects",
"shots_url": "https://api.dribbble.com/v1/users/44585/shots",
"teams_url": "https://api.dribbble.com/v1/users/44585/teams",
"created_at": "2011-07-08T15:47:58Z",
"updated_at": "2016-03-29T16:53:16Z"
},
"team": null
},
{
"id": 2619544,
"title": "Robinhood",
"description": "Robinhood integrations illustration.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_teaser.png"
},
"views_count": 1530,
"likes_count": 177,
"comments_count": 6,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T18:24:59Z",
"updated_at": "2016-03-29T18:26:47Z",
"html_url": "https://dribbble.com/shots/2619544-Robinhood",
"attachments_url": "https://api.dribbble.com/v1/shots/2619544/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619544/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619544/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619544/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619544/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619544/rebounds",
"animated": false,
"tags": [
"chart",
"finance",
"illustration",
"money",
"stock"
],
"user": {
"id": 4598,
"name": "Ty Wilkins",
"username": "tywilkins",
"html_url": "https://dribbble.com/tywilkins",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/4598/avatars/normal/fox2.jpg?1391573055",
"bio": "hello@tywilkins.com",
"location": "San Francisco, CA",
"links": {
"web": "http://www.tywilkins.com",
"twitter": "https://twitter.com/tywilkins"
},
"buckets_count": 0,
"comments_received_count": 1080,
"followers_count": 8222,
"followings_count": 527,
"likes_count": 0,
"likes_received_count": 21359,
"projects_count": 8,
"rebounds_received_count": 0,
"shots_count": 97,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/4598/buckets",
"followers_url": "https://api.dribbble.com/v1/users/4598/followers",
"following_url": "https://api.dribbble.com/v1/users/4598/following",
"likes_url": "https://api.dribbble.com/v1/users/4598/likes",
"projects_url": "https://api.dribbble.com/v1/users/4598/projects",
"shots_url": "https://api.dribbble.com/v1/users/4598/shots",
"teams_url": "https://api.dribbble.com/v1/users/4598/teams",
"created_at": "2010-09-30T20:31:02Z",
"updated_at": "2016-03-29T18:27:54Z"
},
"team": null
},
{
"id": 2619187,
"title": "Confidential iPad App part #2",
"description": "Over the holidays, Rally built an iPad app for a confidential client and conference. This is video directly from interacting with the native iOS app.
\n\nMyself, @Geof Crowl , and Wes tackled the project in just 15 days. It was intense but fun. Geof and I did the design and helped with layout in Xcode using Nibs. Wes built the globe and the data visualizations from a json file using our own Open GL globe library we've been building on an off for the past year.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally.gif",
"normal": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_1x.gif",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_teaser.gif"
},
"views_count": 3205,
"likes_count": 183,
"comments_count": 9,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 20,
"created_at": "2016-03-29T15:50:05Z",
"updated_at": "2016-03-29T15:51:33Z",
"html_url": "https://dribbble.com/shots/2619187-Confidential-iPad-App-part-2",
"attachments_url": "https://api.dribbble.com/v1/shots/2619187/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619187/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619187/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619187/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619187/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619187/rebounds",
"animated": true,
"tags": [
],
"user": {
"id": 3816,
"name": "Ben Cline",
"username": "letsgorally",
"html_url": "https://dribbble.com/letsgorally",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/3816/avatars/normal/bb00fd14001a8cdd5e0e354df52a7fa4.png?1450769044",
"bio": "@RALLY Co-Founder / Designer",
"location": "Salt Lake City",
"links": {
"web": "http://beta.rallyinteractive.com",
"twitter": "https://twitter.com/yocline"
},
"buckets_count": 3,
"comments_received_count": 4525,
"followers_count": 30105,
"followings_count": 241,
"likes_count": 6878,
"likes_received_count": 87892,
"projects_count": 10,
"rebounds_received_count": 28,
"shots_count": 257,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/3816/buckets",
"followers_url": "https://api.dribbble.com/v1/users/3816/followers",
"following_url": "https://api.dribbble.com/v1/users/3816/following",
"likes_url": "https://api.dribbble.com/v1/users/3816/likes",
"projects_url": "https://api.dribbble.com/v1/users/3816/projects",
"shots_url": "https://api.dribbble.com/v1/users/3816/shots",
"teams_url": "https://api.dribbble.com/v1/users/3816/teams",
"created_at": "2010-07-30T17:30:31Z",
"updated_at": "2016-03-29T15:51:33Z"
},
"team": {
"id": 559317,
"name": "RALLY",
"username": "rally",
"html_url": "https://dribbble.com/rally",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/559317/avatars/normal/rally_logo.png?1398641637",
"bio": "Interactive Studio. Design & Development",
"location": "Salt Lake City",
"links": {
"web": "http://beta.rallyinteractive.com",
"twitter": "https://twitter.com/letsgorally"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 8281,
"followings_count": 6,
"likes_count": 73,
"likes_received_count": 0,
"projects_count": 14,
"rebounds_received_count": 0,
"shots_count": 273,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/559317/buckets",
"followers_url": "https://api.dribbble.com/v1/users/559317/followers",
"following_url": "https://api.dribbble.com/v1/users/559317/following",
"likes_url": "https://api.dribbble.com/v1/users/559317/likes",
"projects_url": "https://api.dribbble.com/v1/users/559317/projects",
"shots_url": "https://api.dribbble.com/v1/users/559317/shots",
"created_at": "2014-04-27T23:31:42Z",
"updated_at": "2016-03-29T15:51:33Z",
"members_count": 5,
"members_url": "https://api.dribbble.com/v1/teams/559317/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/559317/shots"
}
},
{
"id": 2619200,
"title": "Eilean Donan Castle",
"description": "Day 209/365
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_teaser.jpg"
},
"views_count": 1434,
"likes_count": 162,
"comments_count": 4,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T15:54:42Z",
"updated_at": "2016-03-29T15:55:23Z",
"html_url": "https://dribbble.com/shots/2619200-Eilean-Donan-Castle",
"attachments_url": "https://api.dribbble.com/v1/shots/2619200/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619200/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619200/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619200/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619200/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619200/rebounds",
"rebound_source_url": "https://api.dribbble.com/v1/shots/2614735",
"animated": false,
"tags": [
"icon",
"illustration",
"lake",
"scotland",
"vector"
],
"user": {
"id": 283823,
"name": "Scott Tusk",
"username": "Tusk",
"html_url": "https://dribbble.com/Tusk",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/283823/avatars/normal/c71f583fd2f781e48da28697c6ec2211.jpg?1456193406",
"bio": "",
"location": "Chicago",
"links": {
},
"buckets_count": 0,
"comments_received_count": 1118,
"followers_count": 5013,
"followings_count": 812,
"likes_count": 2295,
"likes_received_count": 45133,
"projects_count": 1,
"rebounds_received_count": 214,
"shots_count": 282,
"teams_count": 1,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/283823/buckets",
"followers_url": "https://api.dribbble.com/v1/users/283823/followers",
"following_url": "https://api.dribbble.com/v1/users/283823/following",
"likes_url": "https://api.dribbble.com/v1/users/283823/likes",
"projects_url": "https://api.dribbble.com/v1/users/283823/projects",
"shots_url": "https://api.dribbble.com/v1/users/283823/shots",
"teams_url": "https://api.dribbble.com/v1/users/283823/teams",
"created_at": "2013-02-17T16:32:29Z",
"updated_at": "2016-03-29T15:55:23Z"
},
"team": null
},
{
"id": 2619378,
"title": "Infinite Coffee",
"description": "It's Monday, I need coffee. Forever.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_teaser.jpg"
},
"views_count": 1301,
"likes_count": 146,
"comments_count": 6,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 2,
"created_at": "2016-03-29T17:11:50Z",
"updated_at": "2016-03-29T17:18:17Z",
"html_url": "https://dribbble.com/shots/2619378-Infinite-Coffee",
"attachments_url": "https://api.dribbble.com/v1/shots/2619378/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619378/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619378/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619378/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619378/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619378/rebounds",
"animated": false,
"tags": [
"8",
"coffee",
"cup",
"food",
"geometric",
"illustration",
"infinite",
"kite",
"liquid",
"mug",
"stroke"
],
"user": {
"id": 60266,
"name": "Gustavo Zambelli",
"username": "zamax",
"html_url": "https://dribbble.com/zamax",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/60266/avatars/normal/83d4ac61d50bf5b2fedc9f9cc45a62d9.png?1453312126",
"bio": "Hi, I'm Lead of illustration at @aerolab & Superman at @RicosQuesos ",
"location": "Neuquén, Argentina.",
"links": {
"web": "http://zamax.tumblr.com",
"twitter": "https://twitter.com/zamax4"
},
"buckets_count": 19,
"comments_received_count": 1645,
"followers_count": 4198,
"followings_count": 1253,
"likes_count": 8828,
"likes_received_count": 36018,
"projects_count": 4,
"rebounds_received_count": 133,
"shots_count": 305,
"teams_count": 4,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/60266/buckets",
"followers_url": "https://api.dribbble.com/v1/users/60266/followers",
"following_url": "https://api.dribbble.com/v1/users/60266/following",
"likes_url": "https://api.dribbble.com/v1/users/60266/likes",
"projects_url": "https://api.dribbble.com/v1/users/60266/projects",
"shots_url": "https://api.dribbble.com/v1/users/60266/shots",
"teams_url": "https://api.dribbble.com/v1/users/60266/teams",
"created_at": "2011-09-07T19:27:31Z",
"updated_at": "2016-03-29T17:18:17Z"
},
"team": {
"id": 171431,
"name": "Aerolab",
"username": "aerolab",
"html_url": "https://dribbble.com/aerolab",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/171431/avatars/normal/1283d5fbcd21a809d0cdc2f96a560096.png?1458077891",
"bio": "We design and develop beautiful digital products for startups and leading brands.",
"location": "Buenos Aires - San Francisco",
"links": {
"web": "http://aerolab.co",
"twitter": "https://twitter.com/aerolab"
},
"buckets_count": 5,
"comments_received_count": 157,
"followers_count": 3845,
"followings_count": 128,
"likes_count": 4228,
"likes_received_count": 2121,
"projects_count": 24,
"rebounds_received_count": 2,
"shots_count": 579,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/171431/buckets",
"followers_url": "https://api.dribbble.com/v1/users/171431/followers",
"following_url": "https://api.dribbble.com/v1/users/171431/following",
"likes_url": "https://api.dribbble.com/v1/users/171431/likes",
"projects_url": "https://api.dribbble.com/v1/users/171431/projects",
"shots_url": "https://api.dribbble.com/v1/users/171431/shots",
"created_at": "2012-07-04T02:31:07Z",
"updated_at": "2016-03-29T17:18:17Z",
"members_count": 21,
"members_url": "https://api.dribbble.com/v1/teams/171431/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/171431/shots"
}
},
{
"id": 2619645,
"title": "Hello, Is It Me You're Looking For?",
"description": "I had the privilege of getting to collaborate with @Jordan Wade on a hero illustration for his SVG post. And let me tell you, watching your work come alive with CSS and JS is pretty much the jam.
\n\nCheck it out all alive n' stuff!
\n\nGo read about why you should learn more about SVG for the web .
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_teaser.png"
},
"views_count": 1771,
"likes_count": 146,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 1,
"buckets_count": 2,
"created_at": "2016-03-29T19:12:57Z",
"updated_at": "2016-03-29T20:26:49Z",
"html_url": "https://dribbble.com/shots/2619645-Hello-Is-It-Me-You-re-Looking-For",
"attachments_url": "https://api.dribbble.com/v1/shots/2619645/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619645/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619645/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619645/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619645/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619645/rebounds",
"animated": false,
"tags": [
"hello"
],
"user": {
"id": 13774,
"name": "Justin Mezzell",
"username": "JustinMezzell",
"html_url": "https://dribbble.com/JustinMezzell",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/13774/avatars/normal/Me_Web.jpg?1380768479",
"bio": "Designer? Illustrator? Why not. Directing Art at @codeschool .",
"location": "Orlando, FL",
"links": {
"web": "http://justinmezzell.com/",
"twitter": "https://twitter.com/JustinMezzell"
},
"buckets_count": 0,
"comments_received_count": 5736,
"followers_count": 31449,
"followings_count": 713,
"likes_count": 5548,
"likes_received_count": 113425,
"projects_count": 0,
"rebounds_received_count": 55,
"shots_count": 312,
"teams_count": 4,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/13774/buckets",
"followers_url": "https://api.dribbble.com/v1/users/13774/followers",
"following_url": "https://api.dribbble.com/v1/users/13774/following",
"likes_url": "https://api.dribbble.com/v1/users/13774/likes",
"projects_url": "https://api.dribbble.com/v1/users/13774/projects",
"shots_url": "https://api.dribbble.com/v1/users/13774/shots",
"teams_url": "https://api.dribbble.com/v1/users/13774/teams",
"created_at": "2011-01-26T06:58:50Z",
"updated_at": "2016-03-29T20:26:49Z"
},
"team": {
"id": 333539,
"name": "Code School",
"username": "codeschool",
"html_url": "https://dribbble.com/codeschool",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/333539/avatars/normal/329ac818d30ca1a7b900c09b105ce277.jpg?1410890340",
"bio": "Code School teaches web technologies in the comfort of your browser with video lessons, coding challenges, and screencasts.",
"location": "Orlando, FL",
"links": {
"web": "http://codeschool.com",
"twitter": "https://twitter.com/codeschool"
},
"buckets_count": 0,
"comments_received_count": 0,
"followers_count": 3057,
"followings_count": 13,
"likes_count": 1,
"likes_received_count": 0,
"projects_count": 0,
"rebounds_received_count": 0,
"shots_count": 154,
"can_upload_shot": true,
"type": "Team",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/333539/buckets",
"followers_url": "https://api.dribbble.com/v1/users/333539/followers",
"following_url": "https://api.dribbble.com/v1/users/333539/following",
"likes_url": "https://api.dribbble.com/v1/users/333539/likes",
"projects_url": "https://api.dribbble.com/v1/users/333539/projects",
"shots_url": "https://api.dribbble.com/v1/users/333539/shots",
"created_at": "2013-05-15T21:37:44Z",
"updated_at": "2016-03-29T20:26:49Z",
"members_count": 10,
"members_url": "https://api.dribbble.com/v1/teams/333539/members",
"team_shots_url": "https://api.dribbble.com/v1/teams/333539/shots"
}
},
{
"id": 2619181,
"title": "Costa Rica",
"description": "Shirt graphic for offsite meeting in Costa Rica.
",
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa.png",
"normal": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_1x.png",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_teaser.png"
},
"views_count": 1261,
"likes_count": 136,
"comments_count": 7,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 7,
"created_at": "2016-03-29T15:48:25Z",
"updated_at": "2016-03-29T15:49:13Z",
"html_url": "https://dribbble.com/shots/2619181-Costa-Rica",
"attachments_url": "https://api.dribbble.com/v1/shots/2619181/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619181/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619181/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619181/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619181/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619181/rebounds",
"animated": false,
"tags": [
"bird",
"costa rica",
"design",
"illustration",
"leaf",
"toucan",
"tropical"
],
"user": {
"id": 21030,
"name": "Trevor Basset",
"username": "trevorbasset",
"html_url": "https://dribbble.com/trevorbasset",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/21030/avatars/normal/e9907b8b54ea842b30c5787ef95acc3a.png?1426787498",
"bio": "Design, art direction, illustration, birds. ",
"location": "Seattle, WA",
"links": {
"web": "http://www.trevorbasset.com",
"twitter": "https://twitter.com/trevorbasset"
},
"buckets_count": 0,
"comments_received_count": 244,
"followers_count": 1169,
"followings_count": 367,
"likes_count": 1204,
"likes_received_count": 3660,
"projects_count": 0,
"rebounds_received_count": 4,
"shots_count": 85,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": false,
"buckets_url": "https://api.dribbble.com/v1/users/21030/buckets",
"followers_url": "https://api.dribbble.com/v1/users/21030/followers",
"following_url": "https://api.dribbble.com/v1/users/21030/following",
"likes_url": "https://api.dribbble.com/v1/users/21030/likes",
"projects_url": "https://api.dribbble.com/v1/users/21030/projects",
"shots_url": "https://api.dribbble.com/v1/users/21030/shots",
"teams_url": "https://api.dribbble.com/v1/users/21030/teams",
"created_at": "2011-03-03T20:05:14Z",
"updated_at": "2016-03-30T04:08:03Z"
},
"team": null
}
];
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo/main.m
================================================
//
// main.m
// dribbbleDemo
//
// Created by bang on 15/9/1.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
36091A1B1CAAA2830012490F /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A191CAAA2830012490F /* JPEngine.m */; };
36091A1C1CAAA2830012490F /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 36091A1A1CAAA2830012490F /* JSPatch.js */; };
36091A771CAB91990012490F /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A5B1CAB91980012490F /* JPCleaner.m */; };
36091A791CAB91990012490F /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A5F1CAB91980012490F /* JPLocker.m */; };
36091A7B1CAB91990012490F /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A631CAB91980012490F /* JPSpecialInit.m */; };
36CE19221CB17D6A007D73AC /* dribbble in Resources */ = {isa = PBXBuildFile; fileRef = 36CE19211CB17D6A007D73AC /* dribbble */; };
DEBA57DF1B95D5A200B4DC66 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBA57DE1B95D5A200B4DC66 /* main.m */; };
DEBA57E21B95D5A300B4DC66 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBA57E11B95D5A300B4DC66 /* AppDelegate.m */; };
DEBA57EA1B95D5A300B4DC66 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DEBA57E91B95D5A300B4DC66 /* Images.xcassets */; };
DEBA57F91B95D5A300B4DC66 /* dribbbleDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBA57F81B95D5A300B4DC66 /* dribbbleDemoTests.m */; };
DEBA58531B95DA6E00B4DC66 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBA58521B95DA6E00B4DC66 /* UIKit.framework */; };
DEBA58551B95DA7C00B4DC66 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBA58541B95DA7C00B4DC66 /* Security.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
DEBA57F31B95D5A300B4DC66 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DEBA57D11B95D5A200B4DC66 /* Project object */;
proxyType = 1;
remoteGlobalIDString = DEBA57D81B95D5A200B4DC66;
remoteInfo = dribbbleDemo;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
0A8B1CDBA40FFAD086BA1A15 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; };
15903DAE6B51ADB1AEC38472 /* libPods-dribbbleDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-dribbbleDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
36091A181CAAA2830012490F /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = ""; };
36091A191CAAA2830012490F /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = ""; };
36091A1A1CAAA2830012490F /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = ""; };
36091A5A1CAB91980012490F /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = ""; };
36091A5B1CAB91980012490F /* JPCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCleaner.m; sourceTree = ""; };
36091A5E1CAB91980012490F /* JPLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLocker.h; sourceTree = ""; };
36091A5F1CAB91980012490F /* JPLocker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLocker.m; sourceTree = ""; };
36091A621CAB91980012490F /* JPSpecialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSpecialInit.h; sourceTree = ""; };
36091A631CAB91980012490F /* JPSpecialInit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSpecialInit.m; sourceTree = ""; };
36CE19211CB17D6A007D73AC /* dribbble */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dribbble; sourceTree = ""; };
4E9FF79023501B4C7B8780E6 /* Pods-dribbbleDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dribbbleDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo.debug.xcconfig"; sourceTree = ""; };
5B21F30B82AD2BCFBD981366 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; };
A354BF41D400455B098BBF0B /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
C74009A42925FAD86E7D36C0 /* Pods-dribbbleDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dribbbleDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo.release.xcconfig"; sourceTree = ""; };
DEBA57D91B95D5A200B4DC66 /* dribbbleDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dribbbleDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
DEBA57DD1B95D5A200B4DC66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
DEBA57DE1B95D5A200B4DC66 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
DEBA57E01B95D5A300B4DC66 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
DEBA57E11B95D5A300B4DC66 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
DEBA57E91B95D5A300B4DC66 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
DEBA57F21B95D5A300B4DC66 /* dribbbleDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = dribbbleDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DEBA57F71B95D5A300B4DC66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
DEBA57F81B95D5A300B4DC66 /* dribbbleDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = dribbbleDemoTests.m; sourceTree = ""; };
DEBA58521B95DA6E00B4DC66 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
DEBA58541B95DA7C00B4DC66 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
DEBA57D61B95D5A200B4DC66 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DEBA58551B95DA7C00B4DC66 /* Security.framework in Frameworks */,
DEBA58531B95DA6E00B4DC66 /* UIKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DEBA57EF1B95D5A300B4DC66 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
31AAE1067DD5D5B8CB52EAD4 /* Pods */ = {
isa = PBXGroup;
children = (
5B21F30B82AD2BCFBD981366 /* Pods.debug.xcconfig */,
0A8B1CDBA40FFAD086BA1A15 /* Pods.release.xcconfig */,
4E9FF79023501B4C7B8780E6 /* Pods-dribbbleDemo.debug.xcconfig */,
C74009A42925FAD86E7D36C0 /* Pods-dribbbleDemo.release.xcconfig */,
);
name = Pods;
sourceTree = "";
};
36091A171CAAA2830012490F /* JSPatch */ = {
isa = PBXGroup;
children = (
36091A481CAB91980012490F /* Extensions */,
36091A181CAAA2830012490F /* JPEngine.h */,
36091A191CAAA2830012490F /* JPEngine.m */,
36091A1A1CAAA2830012490F /* JSPatch.js */,
);
name = JSPatch;
path = ../../../JSPatch;
sourceTree = "";
};
36091A481CAB91980012490F /* Extensions */ = {
isa = PBXGroup;
children = (
36091A5A1CAB91980012490F /* JPCleaner.h */,
36091A5B1CAB91980012490F /* JPCleaner.m */,
36091A5E1CAB91980012490F /* JPLocker.h */,
36091A5F1CAB91980012490F /* JPLocker.m */,
36091A621CAB91980012490F /* JPSpecialInit.h */,
36091A631CAB91980012490F /* JPSpecialInit.m */,
);
name = Extensions;
path = ../Extensions;
sourceTree = "";
};
DEBA57D01B95D5A200B4DC66 = {
isa = PBXGroup;
children = (
DEBA58541B95DA7C00B4DC66 /* Security.framework */,
DEBA58521B95DA6E00B4DC66 /* UIKit.framework */,
DEBA57DB1B95D5A200B4DC66 /* dribbbleDemo */,
DEBA57F51B95D5A300B4DC66 /* dribbbleDemoTests */,
DEBA57DA1B95D5A200B4DC66 /* Products */,
31AAE1067DD5D5B8CB52EAD4 /* Pods */,
FF293541306D58FD4BDAA5CD /* Frameworks */,
);
sourceTree = "";
};
DEBA57DA1B95D5A200B4DC66 /* Products */ = {
isa = PBXGroup;
children = (
DEBA57D91B95D5A200B4DC66 /* dribbbleDemo.app */,
DEBA57F21B95D5A300B4DC66 /* dribbbleDemoTests.xctest */,
);
name = Products;
sourceTree = "";
};
DEBA57DB1B95D5A200B4DC66 /* dribbbleDemo */ = {
isa = PBXGroup;
children = (
36091A171CAAA2830012490F /* JSPatch */,
DEBA57E01B95D5A300B4DC66 /* AppDelegate.h */,
DEBA57E11B95D5A300B4DC66 /* AppDelegate.m */,
36CE19211CB17D6A007D73AC /* dribbble */,
DEBA57E91B95D5A300B4DC66 /* Images.xcassets */,
DEBA57DC1B95D5A200B4DC66 /* Supporting Files */,
);
path = dribbbleDemo;
sourceTree = "";
};
DEBA57DC1B95D5A200B4DC66 /* Supporting Files */ = {
isa = PBXGroup;
children = (
DEBA57DD1B95D5A200B4DC66 /* Info.plist */,
DEBA57DE1B95D5A200B4DC66 /* main.m */,
);
name = "Supporting Files";
sourceTree = "";
};
DEBA57F51B95D5A300B4DC66 /* dribbbleDemoTests */ = {
isa = PBXGroup;
children = (
DEBA57F81B95D5A300B4DC66 /* dribbbleDemoTests.m */,
DEBA57F61B95D5A300B4DC66 /* Supporting Files */,
);
path = dribbbleDemoTests;
sourceTree = "";
};
DEBA57F61B95D5A300B4DC66 /* Supporting Files */ = {
isa = PBXGroup;
children = (
DEBA57F71B95D5A300B4DC66 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "";
};
FF293541306D58FD4BDAA5CD /* Frameworks */ = {
isa = PBXGroup;
children = (
A354BF41D400455B098BBF0B /* libPods.a */,
15903DAE6B51ADB1AEC38472 /* libPods-dribbbleDemo.a */,
);
name = Frameworks;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
DEBA57D81B95D5A200B4DC66 /* dribbbleDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = DEBA57FC1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget "dribbbleDemo" */;
buildPhases = (
379F843EA00F8D428B9036AE /* 📦 Check Pods Manifest.lock */,
DEBA57D51B95D5A200B4DC66 /* Sources */,
DEBA57D61B95D5A200B4DC66 /* Frameworks */,
DEBA57D71B95D5A200B4DC66 /* Resources */,
5051F1B8E1BE3F57F4085EA8 /* 📦 Copy Pods Resources */,
3E10562C003A078AFFFB76ED /* 📦 Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = dribbbleDemo;
productName = dribbbleDemo;
productReference = DEBA57D91B95D5A200B4DC66 /* dribbbleDemo.app */;
productType = "com.apple.product-type.application";
};
DEBA57F11B95D5A300B4DC66 /* dribbbleDemoTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = DEBA57FF1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget "dribbbleDemoTests" */;
buildPhases = (
DEBA57EE1B95D5A300B4DC66 /* Sources */,
DEBA57EF1B95D5A300B4DC66 /* Frameworks */,
DEBA57F01B95D5A300B4DC66 /* Resources */,
);
buildRules = (
);
dependencies = (
DEBA57F41B95D5A300B4DC66 /* PBXTargetDependency */,
);
name = dribbbleDemoTests;
productName = dribbbleDemoTests;
productReference = DEBA57F21B95D5A300B4DC66 /* dribbbleDemoTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
DEBA57D11B95D5A200B4DC66 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0640;
ORGANIZATIONNAME = bang;
TargetAttributes = {
DEBA57D81B95D5A200B4DC66 = {
CreatedOnToolsVersion = 6.4;
};
DEBA57F11B95D5A300B4DC66 = {
CreatedOnToolsVersion = 6.4;
TestTargetID = DEBA57D81B95D5A200B4DC66;
};
};
};
buildConfigurationList = DEBA57D41B95D5A200B4DC66 /* Build configuration list for PBXProject "dribbbleDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = DEBA57D01B95D5A200B4DC66;
productRefGroup = DEBA57DA1B95D5A200B4DC66 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
DEBA57D81B95D5A200B4DC66 /* dribbbleDemo */,
DEBA57F11B95D5A300B4DC66 /* dribbbleDemoTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
DEBA57D71B95D5A200B4DC66 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
36091A1C1CAAA2830012490F /* JSPatch.js in Resources */,
DEBA57EA1B95D5A300B4DC66 /* Images.xcassets in Resources */,
36CE19221CB17D6A007D73AC /* dribbble in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DEBA57F01B95D5A300B4DC66 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
379F843EA00F8D428B9036AE /* 📦 Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "📦 Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n 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";
showEnvVarsInLog = 0;
};
3E10562C003A078AFFFB76ED /* 📦 Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "📦 Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
5051F1B8E1BE3F57F4085EA8 /* 📦 Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "📦 Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
DEBA57D51B95D5A200B4DC66 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
36091A791CAB91990012490F /* JPLocker.m in Sources */,
36091A771CAB91990012490F /* JPCleaner.m in Sources */,
36091A1B1CAAA2830012490F /* JPEngine.m in Sources */,
36091A7B1CAB91990012490F /* JPSpecialInit.m in Sources */,
DEBA57E21B95D5A300B4DC66 /* AppDelegate.m in Sources */,
DEBA57DF1B95D5A200B4DC66 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DEBA57EE1B95D5A300B4DC66 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DEBA57F91B95D5A300B4DC66 /* dribbbleDemoTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
DEBA57F41B95D5A300B4DC66 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DEBA57D81B95D5A200B4DC66 /* dribbbleDemo */;
targetProxy = DEBA57F31B95D5A300B4DC66 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
DEBA57FA1B95D5A300B4DC66 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
DEBA57FB1B95D5A300B4DC66 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
DEBA57FD1B95D5A300B4DC66 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4E9FF79023501B4C7B8780E6 /* Pods-dribbbleDemo.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
INFOPLIST_FILE = dribbbleDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
DEBA57FE1B95D5A300B4DC66 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C74009A42925FAD86E7D36C0 /* Pods-dribbbleDemo.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
INFOPLIST_FILE = dribbbleDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
DEBA58001B95D5A300B4DC66 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = dribbbleDemoTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/dribbbleDemo.app/dribbbleDemo";
};
name = Debug;
};
DEBA58011B95D5A300B4DC66 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = dribbbleDemoTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/dribbbleDemo.app/dribbbleDemo";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
DEBA57D41B95D5A200B4DC66 /* Build configuration list for PBXProject "dribbbleDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DEBA57FA1B95D5A300B4DC66 /* Debug */,
DEBA57FB1B95D5A300B4DC66 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DEBA57FC1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget "dribbbleDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DEBA57FD1B95D5A300B4DC66 /* Debug */,
DEBA57FE1B95D5A300B4DC66 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DEBA57FF1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget "dribbbleDemoTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DEBA58001B95D5A300B4DC66 /* Debug */,
DEBA58011B95D5A300B4DC66 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = DEBA57D11B95D5A200B4DC66 /* Project object */;
}
================================================
FILE: Demo/DribbbleDemo/dribbbleDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Demo/DribbbleDemo/dribbbleDemoTests/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
com.jspatch..$(PRODUCT_NAME:rfc1034identifier)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
================================================
FILE: Demo/DribbbleDemo/dribbbleDemoTests/dribbbleDemoTests.m
================================================
//
// dribbbleDemoTests.m
// dribbbleDemoTests
//
// Created by bang on 15/9/1.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import
#import
@interface dribbbleDemoTests : XCTestCase
@end
@implementation dribbbleDemoTests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
XCTAssert(YES, @"Pass");
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
@end
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo/AppDelegate.h
================================================
//
// AppDelegate.h
// JSPatchOSXDemo
//
// Created by Felix Deimel on 26.05.15.
// Copyright (c) 2015 Lemon Mojo. All rights reserved.
//
#import
@interface AppDelegate : NSObject
@property (nonatomic, readwrite) int clickCount;
@property (weak) IBOutlet NSTableView *tableView;
@end
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo/AppDelegate.m
================================================
//
// AppDelegate.m
// JSPatchOSXDemo
//
// Created by Felix Deimel on 26.05.15.
// Copyright (c) 2015 Lemon Mojo. All rights reserved.
//
#import "AppDelegate.h"
#import "JPEngine.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[JPEngine startEngine];
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
[JPEngine evaluateScript:script];
}
// Implemented in demo.js
- (IBAction)buttonJavaScriptTestAction:(id)sender { }
- (IBAction)buttonObjectiveCTestAction:(id)sender
{
self.clickCount++;
[(NSButton*)sender setTitle:[NSString stringWithFormat:@"Clicked %i times", self.clickCount]];
[self.tableView reloadData];
}
// Implemented in demo.js
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return 0; }
// Implemented in demo.js
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { return nil; }
@end
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo/Base.lproj/MainMenu.xib
================================================
Default
Left to Right
Right to Left
Default
Left to Right
Right to Left
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIconFile
CFBundleIdentifier
com.lemonmojo.$(PRODUCT_NAME:rfc1034identifier)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
LSMinimumSystemVersion
$(MACOSX_DEPLOYMENT_TARGET)
NSHumanReadableCopyright
Copyright © 2015 Lemon Mojo. All rights reserved.
NSMainNibFile
MainMenu
NSPrincipalClass
NSApplication
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo/demo.js
================================================
defineClass('AppDelegate', {
buttonJavaScriptTestAction: function(sender) {
self.setClickCount(self.clickCount() + 1);
sender.setTitle("Clicked " + self.clickCount() + " times");
self.tableView().reloadData();
},
numberOfRowsInTableView: function(tableView) {
return self.clickCount();
},
tableView_viewForTableColumn_row: function(tableView, tableColumn, row) {
var view = tableView.makeViewWithIdentifier_owner("TABLEVIEW_CELL", self);
view.textField().setStringValue("Clicked " + (row + 1) + " times");
return view;
}
});
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo/main.m
================================================
//
// main.m
// JSPatchOSXDemo
//
// Created by Felix Deimel on 26.05.15.
// Copyright (c) 2015 Lemon Mojo. All rights reserved.
//
#import
int main(int argc, const char * argv[]) {
return NSApplicationMain(argc, argv);
}
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
3613C3941C632A3E00E915CB /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3921C632A3E00E915CB /* JPEngine.m */; };
3613C3951C632A3E00E915CB /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3931C632A3E00E915CB /* JSPatch.js */; };
E7E413DB1B14853E008E10DC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E413DA1B14853E008E10DC /* AppDelegate.m */; };
E7E413DD1B14853E008E10DC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E413DC1B14853E008E10DC /* main.m */; };
E7E413E21B14853E008E10DC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E7E413E01B14853E008E10DC /* MainMenu.xib */; };
E7E413FE1B1486AD008E10DC /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = E7E413FD1B1486AD008E10DC /* demo.js */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
3613C3911C632A3E00E915CB /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = ""; };
3613C3921C632A3E00E915CB /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = ""; };
3613C3931C632A3E00E915CB /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = ""; };
E7E413D41B14853E008E10DC /* JSPatchOSXDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSPatchOSXDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
E7E413D81B14853E008E10DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
E7E413D91B14853E008E10DC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
E7E413DA1B14853E008E10DC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
E7E413DC1B14853E008E10DC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
E7E413E11B14853E008E10DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
E7E413FD1B1486AD008E10DC /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E7E413D11B14853E008E10DC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3613C3901C632A3E00E915CB /* JSPatch */ = {
isa = PBXGroup;
children = (
3613C3911C632A3E00E915CB /* JPEngine.h */,
3613C3921C632A3E00E915CB /* JPEngine.m */,
3613C3931C632A3E00E915CB /* JSPatch.js */,
);
name = JSPatch;
path = ../../../JSPatch;
sourceTree = "";
};
E7E413CB1B14853E008E10DC = {
isa = PBXGroup;
children = (
E7E413D61B14853E008E10DC /* JSPatchOSXDemo */,
E7E413D51B14853E008E10DC /* Products */,
);
sourceTree = "";
};
E7E413D51B14853E008E10DC /* Products */ = {
isa = PBXGroup;
children = (
E7E413D41B14853E008E10DC /* JSPatchOSXDemo.app */,
);
name = Products;
sourceTree = "";
};
E7E413D61B14853E008E10DC /* JSPatchOSXDemo */ = {
isa = PBXGroup;
children = (
3613C3901C632A3E00E915CB /* JSPatch */,
E7E413D91B14853E008E10DC /* AppDelegate.h */,
E7E413DA1B14853E008E10DC /* AppDelegate.m */,
E7E413FD1B1486AD008E10DC /* demo.js */,
E7E413E01B14853E008E10DC /* MainMenu.xib */,
E7E413D71B14853E008E10DC /* Supporting Files */,
);
path = JSPatchOSXDemo;
sourceTree = "";
};
E7E413D71B14853E008E10DC /* Supporting Files */ = {
isa = PBXGroup;
children = (
E7E413D81B14853E008E10DC /* Info.plist */,
E7E413DC1B14853E008E10DC /* main.m */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
E7E413D31B14853E008E10DC /* JSPatchOSXDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = E7E413F11B14853E008E10DC /* Build configuration list for PBXNativeTarget "JSPatchOSXDemo" */;
buildPhases = (
E7E413D01B14853E008E10DC /* Sources */,
E7E413D11B14853E008E10DC /* Frameworks */,
E7E413D21B14853E008E10DC /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = JSPatchOSXDemo;
productName = JSPatchOSXDemo;
productReference = E7E413D41B14853E008E10DC /* JSPatchOSXDemo.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E7E413CC1B14853E008E10DC /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0630;
ORGANIZATIONNAME = "Lemon Mojo";
TargetAttributes = {
E7E413D31B14853E008E10DC = {
CreatedOnToolsVersion = 6.3.2;
};
};
};
buildConfigurationList = E7E413CF1B14853E008E10DC /* Build configuration list for PBXProject "JSPatchOSXDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = E7E413CB1B14853E008E10DC;
productRefGroup = E7E413D51B14853E008E10DC /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E7E413D31B14853E008E10DC /* JSPatchOSXDemo */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
E7E413D21B14853E008E10DC /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3613C3951C632A3E00E915CB /* JSPatch.js in Resources */,
E7E413E21B14853E008E10DC /* MainMenu.xib in Resources */,
E7E413FE1B1486AD008E10DC /* demo.js in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
E7E413D01B14853E008E10DC /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3613C3941C632A3E00E915CB /* JPEngine.m in Sources */,
E7E413DD1B14853E008E10DC /* main.m in Sources */,
E7E413DB1B14853E008E10DC /* AppDelegate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
E7E413E01B14853E008E10DC /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
E7E413E11B14853E008E10DC /* Base */,
);
name = MainMenu.xib;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
E7E413EF1B14853E008E10DC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
E7E413F01B14853E008E10DC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
E7E413F21B14853E008E10DC /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = JSPatchOSXDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E7E413F31B14853E008E10DC /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COMBINE_HIDPI_IMAGES = YES;
INFOPLIST_FILE = JSPatchOSXDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E7E413CF1B14853E008E10DC /* Build configuration list for PBXProject "JSPatchOSXDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E7E413EF1B14853E008E10DC /* Debug */,
E7E413F01B14853E008E10DC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E7E413F11B14853E008E10DC /* Build configuration list for PBXNativeTarget "JSPatchOSXDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E7E413F21B14853E008E10DC /* Debug */,
E7E413F31B14853E008E10DC /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = E7E413CC1B14853E008E10DC /* Project object */;
}
================================================
FILE: Demo/OSXDemo/JSPatchOSXDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Demo/SwiftDemo/SwiftDemo/AppDelegate.swift
================================================
//
// AppDelegate.swift
// SwiftDemo
//
// Created by jspatch on 16/2/3.
// Copyright © 2016年 Arlen. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let aClass: AnyClass? = NSClassFromString("SwiftDemo.ViewController")
if (aClass != nil) {
let clsName = NSStringFromClass(aClass!)
print(clsName)
} else {
print("error ViewController not found")
}
let bClass: AnyClass? = NSClassFromString("SwiftDemo.TestObject")
if (bClass != nil) {
let clsName = NSStringFromClass(bClass!)
print(clsName)
} else {
print("error TestObject not found")
}
let path = Bundle.main.path(forResource: "demo", ofType: "js")
do {
let patch = try String(contentsOfFile: path!)
JPEngine.start()
JPEngine.evaluateScript(patch)
} catch {}
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// 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.
// 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.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// 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.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// 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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
================================================
FILE: Demo/SwiftDemo/SwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/SwiftDemo/SwiftDemo/Base.lproj/LaunchScreen.storyboard
================================================
================================================
FILE: Demo/SwiftDemo/SwiftDemo/Base.lproj/Main.storyboard
================================================
================================================
FILE: Demo/SwiftDemo/SwiftDemo/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
LSRequiresIPhoneOS
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
Main
UIRequiredDeviceCapabilities
armv7
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
================================================
FILE: Demo/SwiftDemo/SwiftDemo/SwiftDemo-Bridging-Header.h
================================================
//
// SwiftDemo-Bridging-Header.h
// SwiftDemo
//
// Created by bang on 2/4/16.
// Copyright © 2016 Arlen. All rights reserved.
//
#ifndef SwiftDemo_Bridging_Header_h
#define SwiftDemo_Bridging_Header_h
#import "JPEngine.h"
#endif /* SwiftDemo_Bridging_Header_h */
================================================
FILE: Demo/SwiftDemo/SwiftDemo/TestObject.swift
================================================
//
// TestObject.swift
// SwiftDemo
//
// Created by jspatch on 16/2/3.
// Copyright © 2016年 Arlen. All rights reserved.
//
import Foundation
/**
After XCode 7.0(could be Swift 2.2), the Swift Class can not be marked using @objc,
and it can't be use in objc rumtime directly.
So if you want to use JSPatch in your project,
you should declare all your Swift Classes inherited from NSObject
https://forums.developer.apple.com/thread/11867
*/
open class TestObject: NSObject {
/**
if your patch doesn't take effect, you should consider adding the dynamic attribute to the function
http://stackoverflow.com/questions/25651081/method-swizzling-in-swift
In production environment, I advise you to add the dynamic attribute to all your Custom Functions.
But you must know, this operation will reduce efficiency.
*/
dynamic func testLog() {
print("TestObject orig testLog")
}
}
================================================
FILE: Demo/SwiftDemo/SwiftDemo/ViewController.swift
================================================
//
// ViewController.swift
// SwiftDemo
//
// Created by jspatch on 16/2/3.
// Copyright © 2016年 Arlen. All rights reserved.
//
import UIKit
//@objc(ViewController)
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TableViewCell")
let testObject = TestObject()
testObject.testLog()
self.testLog()
}
/**
if your patch doesn't take effect, you should consider adding the dynamic attribute to the function
http://stackoverflow.com/questions/25651081/method-swizzling-in-swift
In production environment, I advise you to add the dynamic attribute to all your Custom Functions.
But you must know, this operation will reduce efficiency.
*/
dynamic func testLog() {
print("ViewController orig testLog")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)
cell.textLabel?.text = NSString(format: "cell%d", indexPath.row) as String;
return cell
}
}
================================================
FILE: Demo/SwiftDemo/SwiftDemo/demo.js
================================================
defineClass('SwiftDemo.ViewController', {
viewDidLoad: function() {
console.log('js viewDidLoad begin')
self.ORIGviewDidLoad()
console.log('js viewDidLoad end')
},
testLog: function() {
console.log('js ViewController testlog')
},
tableView_numberOfRowsInSection: function(tableView, section) {
return 10
}
})
defineClass('SwiftDemo.TestObject', {
testLog: function() {
console.log('js TestObject testlog')
}
})
================================================
FILE: Demo/SwiftDemo/SwiftDemo.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
3613C39A1C632AB400E915CB /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3981C632AB400E915CB /* JPEngine.m */; };
3613C39B1C632AB400E915CB /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3991C632AB400E915CB /* JSPatch.js */; };
3613C39E1C63387900E915CB /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3613C39D1C63387900E915CB /* JavaScriptCore.framework */; };
DC5FA8C31C61F242007F1AA0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5FA8C21C61F242007F1AA0 /* AppDelegate.swift */; };
DC5FA8C51C61F242007F1AA0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5FA8C41C61F242007F1AA0 /* ViewController.swift */; };
DC5FA8C81C61F242007F1AA0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8C61C61F242007F1AA0 /* Main.storyboard */; };
DC5FA8CA1C61F242007F1AA0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8C91C61F242007F1AA0 /* Assets.xcassets */; };
DC5FA8CD1C61F242007F1AA0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8CB1C61F242007F1AA0 /* LaunchScreen.storyboard */; };
DC5FA8D51C61F732007F1AA0 /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8D41C61F732007F1AA0 /* demo.js */; };
DC5FA8D71C61FD74007F1AA0 /* TestObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5FA8D61C61FD74007F1AA0 /* TestObject.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
3613C3971C632AB400E915CB /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = ""; };
3613C3981C632AB400E915CB /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = ""; };
3613C3991C632AB400E915CB /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = ""; };
3613C39C1C63344D00E915CB /* SwiftDemo-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SwiftDemo-Bridging-Header.h"; sourceTree = ""; };
3613C39D1C63387900E915CB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
DC5FA8BF1C61F242007F1AA0 /* SwiftDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
DC5FA8C21C61F242007F1AA0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
DC5FA8C41C61F242007F1AA0 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
DC5FA8C71C61F242007F1AA0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
DC5FA8C91C61F242007F1AA0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
DC5FA8CC1C61F242007F1AA0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
DC5FA8CE1C61F242007F1AA0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
DC5FA8D41C61F732007F1AA0 /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = ""; };
DC5FA8D61C61FD74007F1AA0 /* TestObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestObject.swift; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
DC5FA8BC1C61F242007F1AA0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3613C39E1C63387900E915CB /* JavaScriptCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1559087F26CA089030BE8522 /* Frameworks */ = {
isa = PBXGroup;
children = (
3613C39D1C63387900E915CB /* JavaScriptCore.framework */,
);
name = Frameworks;
sourceTree = "";
};
3613C3961C632AB400E915CB /* JSPatch */ = {
isa = PBXGroup;
children = (
3613C3971C632AB400E915CB /* JPEngine.h */,
3613C3981C632AB400E915CB /* JPEngine.m */,
3613C3991C632AB400E915CB /* JSPatch.js */,
);
name = JSPatch;
path = ../../../JSPatch;
sourceTree = "";
};
DC5FA8B61C61F242007F1AA0 = {
isa = PBXGroup;
children = (
DC5FA8C11C61F242007F1AA0 /* SwiftDemo */,
DC5FA8C01C61F242007F1AA0 /* Products */,
1559087F26CA089030BE8522 /* Frameworks */,
);
sourceTree = "";
};
DC5FA8C01C61F242007F1AA0 /* Products */ = {
isa = PBXGroup;
children = (
DC5FA8BF1C61F242007F1AA0 /* SwiftDemo.app */,
);
name = Products;
sourceTree = "";
};
DC5FA8C11C61F242007F1AA0 /* SwiftDemo */ = {
isa = PBXGroup;
children = (
3613C3961C632AB400E915CB /* JSPatch */,
DC5FA8C21C61F242007F1AA0 /* AppDelegate.swift */,
DC5FA8C41C61F242007F1AA0 /* ViewController.swift */,
DC5FA8C61C61F242007F1AA0 /* Main.storyboard */,
DC5FA8C91C61F242007F1AA0 /* Assets.xcassets */,
DC5FA8CB1C61F242007F1AA0 /* LaunchScreen.storyboard */,
DC5FA8CE1C61F242007F1AA0 /* Info.plist */,
DC5FA8D41C61F732007F1AA0 /* demo.js */,
DC5FA8D61C61FD74007F1AA0 /* TestObject.swift */,
3613C39C1C63344D00E915CB /* SwiftDemo-Bridging-Header.h */,
);
path = SwiftDemo;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
DC5FA8BE1C61F242007F1AA0 /* SwiftDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = DC5FA8D11C61F242007F1AA0 /* Build configuration list for PBXNativeTarget "SwiftDemo" */;
buildPhases = (
DC5FA8BB1C61F242007F1AA0 /* Sources */,
DC5FA8BC1C61F242007F1AA0 /* Frameworks */,
DC5FA8BD1C61F242007F1AA0 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = SwiftDemo;
productName = SwiftDemo;
productReference = DC5FA8BF1C61F242007F1AA0 /* SwiftDemo.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
DC5FA8B71C61F242007F1AA0 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0720;
LastUpgradeCheck = 0720;
ORGANIZATIONNAME = Arlen;
TargetAttributes = {
DC5FA8BE1C61F242007F1AA0 = {
CreatedOnToolsVersion = 7.2.1;
LastSwiftMigration = 0820;
};
};
};
buildConfigurationList = DC5FA8BA1C61F242007F1AA0 /* Build configuration list for PBXProject "SwiftDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = DC5FA8B61C61F242007F1AA0;
productRefGroup = DC5FA8C01C61F242007F1AA0 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
DC5FA8BE1C61F242007F1AA0 /* SwiftDemo */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
DC5FA8BD1C61F242007F1AA0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DC5FA8CD1C61F242007F1AA0 /* LaunchScreen.storyboard in Resources */,
3613C39B1C632AB400E915CB /* JSPatch.js in Resources */,
DC5FA8CA1C61F242007F1AA0 /* Assets.xcassets in Resources */,
DC5FA8C81C61F242007F1AA0 /* Main.storyboard in Resources */,
DC5FA8D51C61F732007F1AA0 /* demo.js in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
DC5FA8BB1C61F242007F1AA0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DC5FA8D71C61FD74007F1AA0 /* TestObject.swift in Sources */,
3613C39A1C632AB400E915CB /* JPEngine.m in Sources */,
DC5FA8C51C61F242007F1AA0 /* ViewController.swift in Sources */,
DC5FA8C31C61F242007F1AA0 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
DC5FA8C61C61F242007F1AA0 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
DC5FA8C71C61F242007F1AA0 /* Base */,
);
name = Main.storyboard;
sourceTree = "";
};
DC5FA8CB1C61F242007F1AA0 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
DC5FA8CC1C61F242007F1AA0 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
DC5FA8CF1C61F242007F1AA0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
DC5FA8D01C61F242007F1AA0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
DC5FA8D21C61F242007F1AA0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = SwiftDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.jspatch.SwiftDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SwiftDemo/SwiftDemo-Bridging-Header.h";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
DC5FA8D31C61F242007F1AA0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = SwiftDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.jspatch.SwiftDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SwiftDemo/SwiftDemo-Bridging-Header.h";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
DC5FA8BA1C61F242007F1AA0 /* Build configuration list for PBXProject "SwiftDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DC5FA8CF1C61F242007F1AA0 /* Debug */,
DC5FA8D01C61F242007F1AA0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DC5FA8D11C61F242007F1AA0 /* Build configuration list for PBXNativeTarget "SwiftDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DC5FA8D21C61F242007F1AA0 /* Debug */,
DC5FA8D31C61F242007F1AA0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = DC5FA8B71C61F242007F1AA0 /* Project object */;
}
================================================
FILE: Demo/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Demo/iOSDemo/JSPatchDemo/AppDelegate.h
================================================
//
// AppDelegate.h
// JSPatch
//
// Created by bang on 15/4/30.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import
@interface AppDelegate : UIResponder
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: Demo/iOSDemo/JSPatchDemo/AppDelegate.m
================================================
//
// AppDelegate.m
// JSPatch
//
// Created by bang on 15/4/30.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import "AppDelegate.h"
#import "JPEngine.h"
#import "JPViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[JPEngine startEngine];
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"demo" ofType:@"js"];
NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];
[JPEngine evaluateScript:script];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
JPViewController *rootViewController = [[JPViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
[[UINavigationBar appearance] setBackgroundImage:nil forBarMetrics:UIBarMetricsCompact];
return YES;
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchDemo/JPViewController.h
================================================
//
// JPViewController.h
// JSPatch
//
// Created by bang on 15/5/2.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import
@interface JPViewController : UIViewController
@end
================================================
FILE: Demo/iOSDemo/JSPatchDemo/JPViewController.m
================================================
//
// JPViewController.m
// JSPatch
//
// Created by bang on 15/5/2.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import "JPViewController.h"
@implementation JPViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];
[btn setTitle:@"Push JPTableViewController" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(handleBtn:) forControlEvents:UIControlEventTouchUpInside];
[btn setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:btn];
}
- (void)handleBtn:(id)sender
{
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchDemo/Supporting Files/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/iOSDemo/JSPatchDemo/Supporting Files/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
net.cnbang.$(PRODUCT_NAME:rfc1034identifier)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
LSRequiresIPhoneOS
NSAppTransportSecurity
NSAllowsArbitraryLoads
UIRequiredDeviceCapabilities
armv7
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
================================================
FILE: Demo/iOSDemo/JSPatchDemo/Supporting Files/main.m
================================================
//
// main.m
// JSPatch
//
// Created by bang on 15/4/30.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: Demo/iOSDemo/JSPatchDemo/demo.js
================================================
defineClass('JPViewController', {
handleBtn: function(sender) {
var tableViewCtrl = JPTableViewController.alloc().init()
self.navigationController().pushViewController_animated(tableViewCtrl, YES)
}
})
defineClass('JPTableViewController : UITableViewController ', ['data'], {
dataSource: function() {
var data = self.data();
if (data) return data;
var data = [];
for (var i = 0; i < 20; i ++) {
data.push("cell from js " + i);
}
self.setData(data)
return data;
},
numberOfSectionsInTableView: function(tableView) {
return 1;
},
tableView_numberOfRowsInSection: function(tableView, section) {
return self.dataSource().length;
},
tableView_cellForRowAtIndexPath: function(tableView, indexPath) {
var cell = tableView.dequeueReusableCellWithIdentifier("cell")
if (!cell) {
cell = require('UITableViewCell').alloc().initWithStyle_reuseIdentifier(0, "cell")
}
cell.textLabel().setText(self.dataSource()[indexPath.row()])
return cell
},
tableView_heightForRowAtIndexPath: function(tableView, indexPath) {
return 60
},
tableView_didSelectRowAtIndexPath: function(tableView, indexPath) {
var alertView = require('UIAlertView').alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles("Alert",self.dataSource()[indexPath.row()], self, "OK", null);
alertView.show()
},
alertView_willDismissWithButtonIndex: function(alertView, idx) {
console.log('click btn ' + alertView.buttonTitleAtIndex(idx).toJS())
}
})
================================================
FILE: Demo/iOSDemo/JSPatchDemo.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
2D0DF7071B22F75C005695DA /* inheritTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 2D0DF7061B22F75C005695DA /* inheritTest.js */; };
2D5D89211B0B8BFF009382EC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D5D89181B0B8BFF009382EC /* AppDelegate.m */; };
2D5D89251B0B8BFF009382EC /* JPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D5D891E1B0B8BFF009382EC /* JPViewController.m */; };
2D6D12FD1B0B8CF20095A435 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2D6D12FA1B0B8CF20095A435 /* Images.xcassets */; };
2D6D12FF1B0B8CF20095A435 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D6D12FC1B0B8CF20095A435 /* main.m */; };
2D6D13011B0B8CFF0095A435 /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = 2D6D13001B0B8CFF0095A435 /* demo.js */; };
2DA3C42B206A1892005877CB /* newBlockTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DA3C42A206A1892005877CB /* newBlockTest.m */; };
2DA3C434206B5569005877CB /* newBlockTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 2DA3C433206B5569005877CB /* newBlockTest.js */; };
360BCF4E1D82DCFC00202977 /* JPDispatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 360BCF4D1D82DCFC00202977 /* JPDispatch.m */; };
360BCF541D82EFCD00202977 /* JPProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 360BCF531D82EFCD00202977 /* JPProtocol.m */; };
3613C3861C6329F300E915CB /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3611C6329F300E915CB /* JPEngine.m */; };
3613C3871C6329F300E915CB /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3621C6329F300E915CB /* JSPatch.js */; };
3613C3881C6329F300E915CB /* JPLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3651C6329F300E915CB /* JPLoader.m */; };
3613C3891C6329F300E915CB /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3691C6329F300E915CB /* ioapi.c */; };
3613C38A1C6329F300E915CB /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36B1C6329F300E915CB /* mztools.c */; };
3613C38B1C6329F300E915CB /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36D1C6329F300E915CB /* unzip.c */; };
3613C38C1C6329F300E915CB /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36F1C6329F300E915CB /* zip.c */; };
3613C38D1C6329F300E915CB /* RSA.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3721C6329F300E915CB /* RSA.m */; };
3613C38E1C6329F300E915CB /* ZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3741C6329F300E915CB /* ZipArchive.m */; };
3613C38F1C6329F300E915CB /* packer.php in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3761C6329F300E915CB /* packer.php */; };
3613C3AF1C6346F500E915CB /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3AE1C6346F500E915CB /* JPCleaner.m */; };
3646F8B41CA0F89C00E10774 /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3646F8B31CA0F89C00E10774 /* JPLocker.m */; };
3660BC2D1E2634C900DB3765 /* JPBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660BC2C1E2634C900DB3765 /* JPBlock.m */; };
367650481E2CC3BD00828E12 /* JPBlockWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 367650471E2CC3BD00828E12 /* JPBlockWrapper.m */; };
3694925F1CFEFE42003F44CA /* JPCFunctionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3694925D1CFEFE42003F44CA /* JPCFunctionTest.m */; };
369492601CFEFE42003F44CA /* jsCFunctionTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 3694925E1CFEFE42003F44CA /* jsCFunctionTest.js */; };
369EC2971C9925A400334A64 /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 369EC2961C9925A400334A64 /* JPSpecialInit.m */; };
36B3252D1E290D0C006945DF /* JPMethodSignature.m in Sources */ = {isa = PBXBuildFile; fileRef = 36B3252C1E290D0C006945DF /* JPMethodSignature.m */; };
36C59D611E4B517B00A40835 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 36C59D601E4B517B00A40835 /* libffi.a */; };
36CC3A4B1CFEE6A80001465B /* JPCFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A151CFEE6A80001465B /* JPCFunction.m */; };
36CC3A4C1CFEE6A80001465B /* JPMemory.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A171CFEE6A80001465B /* JPMemory.m */; };
36CC3A4D1CFEE6A80001465B /* JPStructPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A191CFEE6A80001465B /* JPStructPointer.m */; };
36CC3A4F1CFEE6A80001465B /* JPCGBitmapContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A331CFEE6A80001465B /* JPCGBitmapContext.m */; };
36CC3A501CFEE6A80001465B /* JPCGColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A351CFEE6A80001465B /* JPCGColor.m */; };
36CC3A511CFEE6A80001465B /* JPCGContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A371CFEE6A80001465B /* JPCGContext.m */; };
36CC3A521CFEE6A80001465B /* JPCGGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A391CFEE6A80001465B /* JPCGGeometry.m */; };
36CC3A531CFEE6A80001465B /* JPCGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A3B1CFEE6A80001465B /* JPCGImage.m */; };
36CC3A541CFEE6A80001465B /* JPCGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A3D1CFEE6A80001465B /* JPCGPath.m */; };
36CC3A551CFEE6A80001465B /* JPCGTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A3F1CFEE6A80001465B /* JPCGTransform.m */; };
36CC3A561CFEE6A80001465B /* JPCoreGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A411CFEE6A80001465B /* JPCoreGraphics.m */; };
36CC3A571CFEE6A80001465B /* JPUIGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A441CFEE6A80001465B /* JPUIGeometry.m */; };
36CC3A581CFEE6A80001465B /* JPUIGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A461CFEE6A80001465B /* JPUIGraphics.m */; };
36CC3A591CFEE6A80001465B /* JPUIImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A481CFEE6A80001465B /* JPUIImage.m */; };
36CC3A5A1CFEE6A80001465B /* JPUIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A4A1CFEE6A80001465B /* JPUIKit.m */; };
36CE191B1CAEA179007D73AC /* jsClassTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 36CE191A1CAEA179007D73AC /* jsClassTest.js */; };
36CE191E1CAEA1DE007D73AC /* JPJSClassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CE191D1CAEA1DE007D73AC /* JPJSClassTest.m */; };
36CE19251CB3E709007D73AC /* JPPerformanceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CE19241CB3E709007D73AC /* JPPerformanceTest.m */; };
36CE19271CB3E72B007D73AC /* performanceTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 36CE19261CB3E72B007D73AC /* performanceTest.js */; };
36F0DCC61BFAF41C0090EA4A /* libz.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */; };
4F9EBFC51D50745200EC72C1 /* JPNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F9EBFC41D50745200EC72C1 /* JPNumber.m */; };
4F9EBFC91D50749200EC72C1 /* JPNumberTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F9EBFC71D50749200EC72C1 /* JPNumberTest.m */; };
4F9EBFCA1D50749200EC72C1 /* jsNumberTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 4F9EBFC81D50749200EC72C1 /* jsNumberTest.js */; };
6C6CAC741C5F0BCA00444348 /* superTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C6CAC721C5F0BCA00444348 /* superTest.js */; };
6C6CAC751C5F0BCA00444348 /* JPSuperTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6CAC731C5F0BCA00444348 /* JPSuperTestObject.m */; };
6C72B7961C352BA80086C98D /* newProtocolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C72B7951C352BA80086C98D /* newProtocolTest.m */; };
6C9C0EE41C25A7C700FCAAC5 /* newProtocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */; };
6C9C0EE51C25A7DA00FCAAC5 /* newProtocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */; };
DE58B6481B7C312800F64C63 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE58B6471B7C312800F64C63 /* JavaScriptCore.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
DE6FFF031B42B01C0005EE83 /* protocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = DE6FFF021B42B01C0005EE83 /* protocolTest.js */; };
DE6FFF051B42C25D0005EE83 /* protocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = DE6FFF021B42B01C0005EE83 /* protocolTest.js */; };
DE94AE2B1AF246C000E461D4 /* JSPatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE94AE2A1AF246C000E461D4 /* JSPatchTests.m */; };
DE94AE461AF2480000E461D4 /* JPTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = DE94AE441AF2480000E461D4 /* JPTestObject.m */; };
DE94AE471AF2480000E461D4 /* test.js in Resources */ = {isa = PBXBuildFile; fileRef = DE94AE451AF2480000E461D4 /* test.js */; };
E1B89EA01B203482000645C2 /* JPMultithreadTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B89E9F1B203482000645C2 /* JPMultithreadTestObject.m */; };
E1B89EA31B218986000645C2 /* JPInheritanceTestObjects.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B89EA21B218986000645C2 /* JPInheritanceTestObjects.m */; };
E1B89EAE1B228818000645C2 /* multithreadTest.js in Resources */ = {isa = PBXBuildFile; fileRef = E1B89EAD1B228818000645C2 /* multithreadTest.js */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
DE94AE251AF246C000E461D4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DE94AE031AF246BF00E461D4 /* Project object */;
proxyType = 1;
remoteGlobalIDString = DE94AE0A1AF246BF00E461D4;
remoteInfo = JSPatch;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
2D0DF7061B22F75C005695DA /* inheritTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = inheritTest.js; sourceTree = ""; };
2D5D89171B0B8BFF009382EC /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
2D5D89181B0B8BFF009382EC /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
2D5D891D1B0B8BFF009382EC /* JPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPViewController.h; sourceTree = ""; };
2D5D891E1B0B8BFF009382EC /* JPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPViewController.m; sourceTree = ""; };
2D6D12FA1B0B8CF20095A435 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
2D6D12FB1B0B8CF20095A435 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
2D6D12FC1B0B8CF20095A435 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
2D6D13001B0B8CFF0095A435 /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = ""; };
2DA3C429206A1892005877CB /* newBlockTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = newBlockTest.h; sourceTree = ""; };
2DA3C42A206A1892005877CB /* newBlockTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = newBlockTest.m; sourceTree = ""; };
2DA3C433206B5569005877CB /* newBlockTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = newBlockTest.js; sourceTree = ""; };
360BCF4C1D82DCFC00202977 /* JPDispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPDispatch.h; sourceTree = ""; };
360BCF4D1D82DCFC00202977 /* JPDispatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPDispatch.m; sourceTree = ""; };
360BCF521D82EFCD00202977 /* JPProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPProtocol.h; sourceTree = ""; };
360BCF531D82EFCD00202977 /* JPProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPProtocol.m; sourceTree = ""; };
3613C3601C6329F300E915CB /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = ""; };
3613C3611C6329F300E915CB /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = ""; };
3613C3621C6329F300E915CB /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = ""; };
3613C3641C6329F300E915CB /* JPLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLoader.h; sourceTree = ""; };
3613C3651C6329F300E915CB /* JPLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLoader.m; sourceTree = ""; };
3613C3681C6329F300E915CB /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = ""; };
3613C3691C6329F300E915CB /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = ""; };
3613C36A1C6329F300E915CB /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; };
3613C36B1C6329F300E915CB /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = ""; };
3613C36C1C6329F300E915CB /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = ""; };
3613C36D1C6329F300E915CB /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = ""; };
3613C36E1C6329F300E915CB /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = ""; };
3613C36F1C6329F300E915CB /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = ""; };
3613C3701C6329F300E915CB /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = ""; };
3613C3711C6329F300E915CB /* RSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSA.h; sourceTree = ""; };
3613C3721C6329F300E915CB /* RSA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSA.m; sourceTree = ""; };
3613C3731C6329F300E915CB /* ZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipArchive.h; sourceTree = ""; };
3613C3741C6329F300E915CB /* ZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipArchive.m; sourceTree = ""; };
3613C3761C6329F300E915CB /* packer.php */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.php; path = packer.php; sourceTree = ""; };
3613C3AD1C6346F500E915CB /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = ""; };
3613C3AE1C6346F500E915CB /* JPCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCleaner.m; sourceTree = ""; };
3646F8B21CA0F89C00E10774 /* JPLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLocker.h; sourceTree = ""; };
3646F8B31CA0F89C00E10774 /* JPLocker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLocker.m; sourceTree = ""; };
3660BC2B1E2634C900DB3765 /* JPBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPBlock.h; sourceTree = ""; };
3660BC2C1E2634C900DB3765 /* JPBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPBlock.m; sourceTree = ""; };
367650461E2CC3BD00828E12 /* JPBlockWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPBlockWrapper.h; sourceTree = ""; };
367650471E2CC3BD00828E12 /* JPBlockWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPBlockWrapper.m; sourceTree = ""; };
3694925C1CFEFE42003F44CA /* JPCFunctionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCFunctionTest.h; sourceTree = ""; };
3694925D1CFEFE42003F44CA /* JPCFunctionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCFunctionTest.m; sourceTree = ""; };
3694925E1CFEFE42003F44CA /* jsCFunctionTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jsCFunctionTest.js; sourceTree = ""; };
369EC2951C9925A400334A64 /* JPSpecialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSpecialInit.h; sourceTree = ""; };
369EC2961C9925A400334A64 /* JPSpecialInit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSpecialInit.m; sourceTree = ""; };
36B3252B1E290D0C006945DF /* JPMethodSignature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMethodSignature.h; sourceTree = ""; };
36B3252C1E290D0C006945DF /* JPMethodSignature.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMethodSignature.m; sourceTree = ""; };
36C59D561E4B517B00A40835 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = ""; };
36C59D571E4B517B00A40835 /* ffi_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm.h; sourceTree = ""; };
36C59D581E4B517B00A40835 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = ""; };
36C59D591E4B517B00A40835 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = ""; };
36C59D5A1E4B517B00A40835 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = ""; };
36C59D5B1E4B517B00A40835 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = ""; };
36C59D5C1E4B517B00A40835 /* ffitarget_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm.h; sourceTree = ""; };
36C59D5D1E4B517B00A40835 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = ""; };
36C59D5E1E4B517B00A40835 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = ""; };
36C59D5F1E4B517B00A40835 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = ""; };
36C59D601E4B517B00A40835 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; };
36CC3A141CFEE6A80001465B /* JPCFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCFunction.h; sourceTree = ""; };
36CC3A151CFEE6A80001465B /* JPCFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCFunction.m; sourceTree = ""; };
36CC3A161CFEE6A80001465B /* JPMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMemory.h; sourceTree = ""; };
36CC3A171CFEE6A80001465B /* JPMemory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMemory.m; sourceTree = ""; };
36CC3A181CFEE6A80001465B /* JPStructPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPStructPointer.h; sourceTree = ""; };
36CC3A191CFEE6A80001465B /* JPStructPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPStructPointer.m; sourceTree = ""; };
36CC3A321CFEE6A80001465B /* JPCGBitmapContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGBitmapContext.h; sourceTree = ""; };
36CC3A331CFEE6A80001465B /* JPCGBitmapContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGBitmapContext.m; sourceTree = ""; };
36CC3A341CFEE6A80001465B /* JPCGColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGColor.h; sourceTree = ""; };
36CC3A351CFEE6A80001465B /* JPCGColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGColor.m; sourceTree = ""; };
36CC3A361CFEE6A80001465B /* JPCGContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGContext.h; sourceTree = ""; };
36CC3A371CFEE6A80001465B /* JPCGContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGContext.m; sourceTree = ""; };
36CC3A381CFEE6A80001465B /* JPCGGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGGeometry.h; sourceTree = ""; };
36CC3A391CFEE6A80001465B /* JPCGGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGGeometry.m; sourceTree = ""; };
36CC3A3A1CFEE6A80001465B /* JPCGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGImage.h; sourceTree = ""; };
36CC3A3B1CFEE6A80001465B /* JPCGImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGImage.m; sourceTree = ""; };
36CC3A3C1CFEE6A80001465B /* JPCGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGPath.h; sourceTree = ""; };
36CC3A3D1CFEE6A80001465B /* JPCGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGPath.m; sourceTree = ""; };
36CC3A3E1CFEE6A80001465B /* JPCGTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGTransform.h; sourceTree = ""; };
36CC3A3F1CFEE6A80001465B /* JPCGTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGTransform.m; sourceTree = ""; };
36CC3A401CFEE6A80001465B /* JPCoreGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCoreGraphics.h; sourceTree = ""; };
36CC3A411CFEE6A80001465B /* JPCoreGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCoreGraphics.m; sourceTree = ""; };
36CC3A431CFEE6A80001465B /* JPUIGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGeometry.h; sourceTree = ""; };
36CC3A441CFEE6A80001465B /* JPUIGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGeometry.m; sourceTree = ""; };
36CC3A451CFEE6A80001465B /* JPUIGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGraphics.h; sourceTree = ""; };
36CC3A461CFEE6A80001465B /* JPUIGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGraphics.m; sourceTree = ""; };
36CC3A471CFEE6A80001465B /* JPUIImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIImage.h; sourceTree = ""; };
36CC3A481CFEE6A80001465B /* JPUIImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIImage.m; sourceTree = ""; };
36CC3A491CFEE6A80001465B /* JPUIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIKit.h; sourceTree = ""; };
36CC3A4A1CFEE6A80001465B /* JPUIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIKit.m; sourceTree = ""; };
36CE191A1CAEA179007D73AC /* jsClassTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jsClassTest.js; sourceTree = ""; };
36CE191C1CAEA1DE007D73AC /* JPJSClassTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPJSClassTest.h; sourceTree = ""; };
36CE191D1CAEA1DE007D73AC /* JPJSClassTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPJSClassTest.m; sourceTree = ""; };
36CE19231CB3E709007D73AC /* JPPerformanceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPPerformanceTest.h; sourceTree = ""; };
36CE19241CB3E709007D73AC /* JPPerformanceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPPerformanceTest.m; sourceTree = ""; };
36CE19261CB3E72B007D73AC /* performanceTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = performanceTest.js; sourceTree = ""; };
36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.dylib; path = ../../../../../../usr/lib/libz.1.dylib; sourceTree = ""; };
4F9EBFC31D50745200EC72C1 /* JPNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPNumber.h; sourceTree = ""; };
4F9EBFC41D50745200EC72C1 /* JPNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPNumber.m; sourceTree = ""; };
4F9EBFC61D50749200EC72C1 /* JPNumberTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPNumberTest.h; sourceTree = ""; };
4F9EBFC71D50749200EC72C1 /* JPNumberTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPNumberTest.m; sourceTree = ""; };
4F9EBFC81D50749200EC72C1 /* jsNumberTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jsNumberTest.js; sourceTree = ""; };
6C6CAC711C5F0BCA00444348 /* JPSuperTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSuperTestObject.h; sourceTree = ""; };
6C6CAC721C5F0BCA00444348 /* superTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = superTest.js; sourceTree = ""; };
6C6CAC731C5F0BCA00444348 /* JPSuperTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSuperTestObject.m; sourceTree = ""; };
6C72B7941C352BA80086C98D /* newProtocolTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = newProtocolTest.h; sourceTree = ""; };
6C72B7951C352BA80086C98D /* newProtocolTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = newProtocolTest.m; sourceTree = ""; };
6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = newProtocolTest.js; sourceTree = ""; };
DE58B6471B7C312800F64C63 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
DE6FFF021B42B01C0005EE83 /* protocolTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = protocolTest.js; sourceTree = ""; };
DE94AE0B1AF246BF00E461D4 /* JSPatchDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSPatchDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
DE94AE241AF246C000E461D4 /* JSPatchDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JSPatchDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DE94AE291AF246C000E461D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
DE94AE2A1AF246C000E461D4 /* JSPatchTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JSPatchTests.m; sourceTree = ""; };
DE94AE431AF2480000E461D4 /* JPTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPTestObject.h; sourceTree = ""; };
DE94AE441AF2480000E461D4 /* JPTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPTestObject.m; sourceTree = ""; };
DE94AE451AF2480000E461D4 /* test.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = test.js; sourceTree = ""; };
E1B89E9E1B203482000645C2 /* JPMultithreadTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMultithreadTestObject.h; sourceTree = ""; };
E1B89E9F1B203482000645C2 /* JPMultithreadTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMultithreadTestObject.m; sourceTree = ""; };
E1B89EA11B218986000645C2 /* JPInheritanceTestObjects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPInheritanceTestObjects.h; sourceTree = ""; };
E1B89EA21B218986000645C2 /* JPInheritanceTestObjects.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPInheritanceTestObjects.m; sourceTree = ""; };
E1B89EAD1B228818000645C2 /* multithreadTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = multithreadTest.js; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
DE94AE081AF246BF00E461D4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
36F0DCC61BFAF41C0090EA4A /* libz.1.dylib in Frameworks */,
36C59D611E4B517B00A40835 /* libffi.a in Frameworks */,
DE58B6481B7C312800F64C63 /* JavaScriptCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DE94AE211AF246C000E461D4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2D5D89161B0B8BFF009382EC /* JSPatchDemo */ = {
isa = PBXGroup;
children = (
3613C33E1C6329F300E915CB /* Extensions */,
3613C35F1C6329F300E915CB /* JSPatch */,
3613C3631C6329F300E915CB /* Loader */,
2D6D12F91B0B8CF20095A435 /* Supporting Files */,
2D5D89171B0B8BFF009382EC /* AppDelegate.h */,
2D5D89181B0B8BFF009382EC /* AppDelegate.m */,
2D5D891D1B0B8BFF009382EC /* JPViewController.h */,
2D5D891E1B0B8BFF009382EC /* JPViewController.m */,
2D6D13001B0B8CFF0095A435 /* demo.js */,
);
path = JSPatchDemo;
sourceTree = "";
};
2D6D12F91B0B8CF20095A435 /* Supporting Files */ = {
isa = PBXGroup;
children = (
2D6D12FA1B0B8CF20095A435 /* Images.xcassets */,
2D6D12FB1B0B8CF20095A435 /* Info.plist */,
2D6D12FC1B0B8CF20095A435 /* main.m */,
);
path = "Supporting Files";
sourceTree = "";
};
3613C33E1C6329F300E915CB /* Extensions */ = {
isa = PBXGroup;
children = (
36B324F51E290CF3006945DF /* JPLibffi */,
3660BC171E26327800DB3765 /* JPBlock */,
36CC3A131CFEE6A80001465B /* JPCFunction */,
36CC3A301CFEE6A80001465B /* JPCFunctionBinder */,
369EC2951C9925A400334A64 /* JPSpecialInit.h */,
369EC2961C9925A400334A64 /* JPSpecialInit.m */,
3613C3AD1C6346F500E915CB /* JPCleaner.h */,
3613C3AE1C6346F500E915CB /* JPCleaner.m */,
3646F8B21CA0F89C00E10774 /* JPLocker.h */,
3646F8B31CA0F89C00E10774 /* JPLocker.m */,
4F9EBFC31D50745200EC72C1 /* JPNumber.h */,
4F9EBFC41D50745200EC72C1 /* JPNumber.m */,
360BCF4C1D82DCFC00202977 /* JPDispatch.h */,
360BCF4D1D82DCFC00202977 /* JPDispatch.m */,
360BCF521D82EFCD00202977 /* JPProtocol.h */,
360BCF531D82EFCD00202977 /* JPProtocol.m */,
);
name = Extensions;
path = ../../../Extensions;
sourceTree = "";
};
3613C35F1C6329F300E915CB /* JSPatch */ = {
isa = PBXGroup;
children = (
3613C3601C6329F300E915CB /* JPEngine.h */,
3613C3611C6329F300E915CB /* JPEngine.m */,
3613C3621C6329F300E915CB /* JSPatch.js */,
);
name = JSPatch;
path = ../../../JSPatch;
sourceTree = "";
};
3613C3631C6329F300E915CB /* Loader */ = {
isa = PBXGroup;
children = (
3613C3641C6329F300E915CB /* JPLoader.h */,
3613C3651C6329F300E915CB /* JPLoader.m */,
3613C3661C6329F300E915CB /* libs */,
3613C3751C6329F300E915CB /* tools */,
);
name = Loader;
path = ../../../Loader;
sourceTree = "";
};
3613C3661C6329F300E915CB /* libs */ = {
isa = PBXGroup;
children = (
3613C3671C6329F300E915CB /* minizip */,
3613C3711C6329F300E915CB /* RSA.h */,
3613C3721C6329F300E915CB /* RSA.m */,
3613C3731C6329F300E915CB /* ZipArchive.h */,
3613C3741C6329F300E915CB /* ZipArchive.m */,
);
path = libs;
sourceTree = "";
};
3613C3671C6329F300E915CB /* minizip */ = {
isa = PBXGroup;
children = (
3613C3681C6329F300E915CB /* crypt.h */,
3613C3691C6329F300E915CB /* ioapi.c */,
3613C36A1C6329F300E915CB /* ioapi.h */,
3613C36B1C6329F300E915CB /* mztools.c */,
3613C36C1C6329F300E915CB /* mztools.h */,
3613C36D1C6329F300E915CB /* unzip.c */,
3613C36E1C6329F300E915CB /* unzip.h */,
3613C36F1C6329F300E915CB /* zip.c */,
3613C3701C6329F300E915CB /* zip.h */,
);
path = minizip;
sourceTree = "";
};
3613C3751C6329F300E915CB /* tools */ = {
isa = PBXGroup;
children = (
3613C3761C6329F300E915CB /* packer.php */,
);
path = tools;
sourceTree = "";
};
3660BC171E26327800DB3765 /* JPBlock */ = {
isa = PBXGroup;
children = (
3660BC2B1E2634C900DB3765 /* JPBlock.h */,
3660BC2C1E2634C900DB3765 /* JPBlock.m */,
367650461E2CC3BD00828E12 /* JPBlockWrapper.h */,
367650471E2CC3BD00828E12 /* JPBlockWrapper.m */,
);
path = JPBlock;
sourceTree = "";
};
36B324F51E290CF3006945DF /* JPLibffi */ = {
isa = PBXGroup;
children = (
36C59D551E4B517B00A40835 /* libffi */,
36B3252B1E290D0C006945DF /* JPMethodSignature.h */,
36B3252C1E290D0C006945DF /* JPMethodSignature.m */,
);
path = JPLibffi;
sourceTree = "";
};
36C59D551E4B517B00A40835 /* libffi */ = {
isa = PBXGroup;
children = (
36C59D561E4B517B00A40835 /* ffi.h */,
36C59D571E4B517B00A40835 /* ffi_arm.h */,
36C59D581E4B517B00A40835 /* ffi_arm64.h */,
36C59D591E4B517B00A40835 /* ffi_i386.h */,
36C59D5A1E4B517B00A40835 /* ffi_x86_64.h */,
36C59D5B1E4B517B00A40835 /* ffitarget.h */,
36C59D5C1E4B517B00A40835 /* ffitarget_arm.h */,
36C59D5D1E4B517B00A40835 /* ffitarget_arm64.h */,
36C59D5E1E4B517B00A40835 /* ffitarget_i386.h */,
36C59D5F1E4B517B00A40835 /* ffitarget_x86_64.h */,
36C59D601E4B517B00A40835 /* libffi.a */,
);
path = libffi;
sourceTree = "";
};
36CC3A131CFEE6A80001465B /* JPCFunction */ = {
isa = PBXGroup;
children = (
36CC3A141CFEE6A80001465B /* JPCFunction.h */,
36CC3A151CFEE6A80001465B /* JPCFunction.m */,
36CC3A161CFEE6A80001465B /* JPMemory.h */,
36CC3A171CFEE6A80001465B /* JPMemory.m */,
36CC3A181CFEE6A80001465B /* JPStructPointer.h */,
36CC3A191CFEE6A80001465B /* JPStructPointer.m */,
);
path = JPCFunction;
sourceTree = "";
};
36CC3A301CFEE6A80001465B /* JPCFunctionBinder */ = {
isa = PBXGroup;
children = (
36CC3A311CFEE6A80001465B /* CoreGraphics */,
36CC3A421CFEE6A80001465B /* UIKit */,
);
path = JPCFunctionBinder;
sourceTree = "";
};
36CC3A311CFEE6A80001465B /* CoreGraphics */ = {
isa = PBXGroup;
children = (
36CC3A321CFEE6A80001465B /* JPCGBitmapContext.h */,
36CC3A331CFEE6A80001465B /* JPCGBitmapContext.m */,
36CC3A341CFEE6A80001465B /* JPCGColor.h */,
36CC3A351CFEE6A80001465B /* JPCGColor.m */,
36CC3A361CFEE6A80001465B /* JPCGContext.h */,
36CC3A371CFEE6A80001465B /* JPCGContext.m */,
36CC3A381CFEE6A80001465B /* JPCGGeometry.h */,
36CC3A391CFEE6A80001465B /* JPCGGeometry.m */,
36CC3A3A1CFEE6A80001465B /* JPCGImage.h */,
36CC3A3B1CFEE6A80001465B /* JPCGImage.m */,
36CC3A3C1CFEE6A80001465B /* JPCGPath.h */,
36CC3A3D1CFEE6A80001465B /* JPCGPath.m */,
36CC3A3E1CFEE6A80001465B /* JPCGTransform.h */,
36CC3A3F1CFEE6A80001465B /* JPCGTransform.m */,
36CC3A401CFEE6A80001465B /* JPCoreGraphics.h */,
36CC3A411CFEE6A80001465B /* JPCoreGraphics.m */,
);
path = CoreGraphics;
sourceTree = "";
};
36CC3A421CFEE6A80001465B /* UIKit */ = {
isa = PBXGroup;
children = (
36CC3A431CFEE6A80001465B /* JPUIGeometry.h */,
36CC3A441CFEE6A80001465B /* JPUIGeometry.m */,
36CC3A451CFEE6A80001465B /* JPUIGraphics.h */,
36CC3A461CFEE6A80001465B /* JPUIGraphics.m */,
36CC3A471CFEE6A80001465B /* JPUIImage.h */,
36CC3A481CFEE6A80001465B /* JPUIImage.m */,
36CC3A491CFEE6A80001465B /* JPUIKit.h */,
36CC3A4A1CFEE6A80001465B /* JPUIKit.m */,
);
path = UIKit;
sourceTree = "";
};
DE94AE021AF246BE00E461D4 = {
isa = PBXGroup;
children = (
36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */,
DE58B6471B7C312800F64C63 /* JavaScriptCore.framework */,
2D5D89161B0B8BFF009382EC /* JSPatchDemo */,
DE94AE271AF246C000E461D4 /* JSPatchTests */,
DE94AE0C1AF246BF00E461D4 /* Products */,
);
sourceTree = "";
};
DE94AE0C1AF246BF00E461D4 /* Products */ = {
isa = PBXGroup;
children = (
DE94AE0B1AF246BF00E461D4 /* JSPatchDemo.app */,
DE94AE241AF246C000E461D4 /* JSPatchDemoTests.xctest */,
);
name = Products;
sourceTree = "";
};
DE94AE271AF246C000E461D4 /* JSPatchTests */ = {
isa = PBXGroup;
children = (
4F9EBFC61D50749200EC72C1 /* JPNumberTest.h */,
4F9EBFC71D50749200EC72C1 /* JPNumberTest.m */,
4F9EBFC81D50749200EC72C1 /* jsNumberTest.js */,
3694925C1CFEFE42003F44CA /* JPCFunctionTest.h */,
3694925D1CFEFE42003F44CA /* JPCFunctionTest.m */,
3694925E1CFEFE42003F44CA /* jsCFunctionTest.js */,
36CE191C1CAEA1DE007D73AC /* JPJSClassTest.h */,
36CE191D1CAEA1DE007D73AC /* JPJSClassTest.m */,
36CE191A1CAEA179007D73AC /* jsClassTest.js */,
6C6CAC711C5F0BCA00444348 /* JPSuperTestObject.h */,
6C6CAC731C5F0BCA00444348 /* JPSuperTestObject.m */,
6C6CAC721C5F0BCA00444348 /* superTest.js */,
36CE19231CB3E709007D73AC /* JPPerformanceTest.h */,
36CE19241CB3E709007D73AC /* JPPerformanceTest.m */,
36CE19261CB3E72B007D73AC /* performanceTest.js */,
2DA3C429206A1892005877CB /* newBlockTest.h */,
2DA3C42A206A1892005877CB /* newBlockTest.m */,
2DA3C433206B5569005877CB /* newBlockTest.js */,
6C72B7941C352BA80086C98D /* newProtocolTest.h */,
6C72B7951C352BA80086C98D /* newProtocolTest.m */,
6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */,
E1B89E9E1B203482000645C2 /* JPMultithreadTestObject.h */,
E1B89E9F1B203482000645C2 /* JPMultithreadTestObject.m */,
DE94AE431AF2480000E461D4 /* JPTestObject.h */,
DE94AE441AF2480000E461D4 /* JPTestObject.m */,
E1B89EA11B218986000645C2 /* JPInheritanceTestObjects.h */,
E1B89EA21B218986000645C2 /* JPInheritanceTestObjects.m */,
DE6FFF021B42B01C0005EE83 /* protocolTest.js */,
2D0DF7061B22F75C005695DA /* inheritTest.js */,
DE94AE451AF2480000E461D4 /* test.js */,
E1B89EAD1B228818000645C2 /* multithreadTest.js */,
DE94AE2A1AF246C000E461D4 /* JSPatchTests.m */,
DE94AE281AF246C000E461D4 /* Supporting Files */,
);
path = JSPatchTests;
sourceTree = "";
};
DE94AE281AF246C000E461D4 /* Supporting Files */ = {
isa = PBXGroup;
children = (
DE94AE291AF246C000E461D4 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
DE94AE0A1AF246BF00E461D4 /* JSPatchDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = DE94AE2E1AF246C000E461D4 /* Build configuration list for PBXNativeTarget "JSPatchDemo" */;
buildPhases = (
DE94AE071AF246BF00E461D4 /* Sources */,
DE94AE081AF246BF00E461D4 /* Frameworks */,
DE94AE091AF246BF00E461D4 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = JSPatchDemo;
productName = JSPatch;
productReference = DE94AE0B1AF246BF00E461D4 /* JSPatchDemo.app */;
productType = "com.apple.product-type.application";
};
DE94AE231AF246C000E461D4 /* JSPatchTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = DE94AE311AF246C000E461D4 /* Build configuration list for PBXNativeTarget "JSPatchTests" */;
buildPhases = (
DE94AE201AF246C000E461D4 /* Sources */,
DE94AE211AF246C000E461D4 /* Frameworks */,
DE94AE221AF246C000E461D4 /* Resources */,
);
buildRules = (
);
dependencies = (
DE94AE261AF246C000E461D4 /* PBXTargetDependency */,
);
name = JSPatchTests;
productName = JSPatchTests;
productReference = DE94AE241AF246C000E461D4 /* JSPatchDemoTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
DE94AE031AF246BF00E461D4 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0620;
ORGANIZATIONNAME = bang;
TargetAttributes = {
DE94AE0A1AF246BF00E461D4 = {
CreatedOnToolsVersion = 6.2;
};
DE94AE231AF246C000E461D4 = {
CreatedOnToolsVersion = 6.2;
TestTargetID = DE94AE0A1AF246BF00E461D4;
};
};
};
buildConfigurationList = DE94AE061AF246BF00E461D4 /* Build configuration list for PBXProject "JSPatchDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = DE94AE021AF246BE00E461D4;
productRefGroup = DE94AE0C1AF246BF00E461D4 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
DE94AE0A1AF246BF00E461D4 /* JSPatchDemo */,
DE94AE231AF246C000E461D4 /* JSPatchTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
DE94AE091AF246BF00E461D4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6C9C0EE51C25A7DA00FCAAC5 /* newProtocolTest.js in Resources */,
3613C3871C6329F300E915CB /* JSPatch.js in Resources */,
3613C38F1C6329F300E915CB /* packer.php in Resources */,
DE6FFF051B42C25D0005EE83 /* protocolTest.js in Resources */,
2D6D12FD1B0B8CF20095A435 /* Images.xcassets in Resources */,
2D6D13011B0B8CFF0095A435 /* demo.js in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DE94AE221AF246C000E461D4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DE6FFF031B42B01C0005EE83 /* protocolTest.js in Resources */,
2D0DF7071B22F75C005695DA /* inheritTest.js in Resources */,
6C6CAC741C5F0BCA00444348 /* superTest.js in Resources */,
DE94AE471AF2480000E461D4 /* test.js in Resources */,
36CE191B1CAEA179007D73AC /* jsClassTest.js in Resources */,
6C9C0EE41C25A7C700FCAAC5 /* newProtocolTest.js in Resources */,
4F9EBFCA1D50749200EC72C1 /* jsNumberTest.js in Resources */,
E1B89EAE1B228818000645C2 /* multithreadTest.js in Resources */,
369492601CFEFE42003F44CA /* jsCFunctionTest.js in Resources */,
36CE19271CB3E72B007D73AC /* performanceTest.js in Resources */,
2DA3C434206B5569005877CB /* newBlockTest.js in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
DE94AE071AF246BF00E461D4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
36CC3A591CFEE6A80001465B /* JPUIImage.m in Sources */,
360BCF4E1D82DCFC00202977 /* JPDispatch.m in Sources */,
3613C3AF1C6346F500E915CB /* JPCleaner.m in Sources */,
2D5D89211B0B8BFF009382EC /* AppDelegate.m in Sources */,
36CC3A511CFEE6A80001465B /* JPCGContext.m in Sources */,
3613C38E1C6329F300E915CB /* ZipArchive.m in Sources */,
3613C3861C6329F300E915CB /* JPEngine.m in Sources */,
36CC3A531CFEE6A80001465B /* JPCGImage.m in Sources */,
36CC3A541CFEE6A80001465B /* JPCGPath.m in Sources */,
3613C3881C6329F300E915CB /* JPLoader.m in Sources */,
36CC3A501CFEE6A80001465B /* JPCGColor.m in Sources */,
4F9EBFC51D50745200EC72C1 /* JPNumber.m in Sources */,
36CC3A521CFEE6A80001465B /* JPCGGeometry.m in Sources */,
360BCF541D82EFCD00202977 /* JPProtocol.m in Sources */,
E1B89EA01B203482000645C2 /* JPMultithreadTestObject.m in Sources */,
3660BC2D1E2634C900DB3765 /* JPBlock.m in Sources */,
3613C38B1C6329F300E915CB /* unzip.c in Sources */,
36CC3A4C1CFEE6A80001465B /* JPMemory.m in Sources */,
36CC3A5A1CFEE6A80001465B /* JPUIKit.m in Sources */,
36CC3A4D1CFEE6A80001465B /* JPStructPointer.m in Sources */,
36CC3A571CFEE6A80001465B /* JPUIGeometry.m in Sources */,
36CC3A551CFEE6A80001465B /* JPCGTransform.m in Sources */,
36CC3A561CFEE6A80001465B /* JPCoreGraphics.m in Sources */,
3613C38D1C6329F300E915CB /* RSA.m in Sources */,
3613C3891C6329F300E915CB /* ioapi.c in Sources */,
36CC3A4F1CFEE6A80001465B /* JPCGBitmapContext.m in Sources */,
2D5D89251B0B8BFF009382EC /* JPViewController.m in Sources */,
3613C38A1C6329F300E915CB /* mztools.c in Sources */,
36CC3A581CFEE6A80001465B /* JPUIGraphics.m in Sources */,
36CC3A4B1CFEE6A80001465B /* JPCFunction.m in Sources */,
36B3252D1E290D0C006945DF /* JPMethodSignature.m in Sources */,
3613C38C1C6329F300E915CB /* zip.c in Sources */,
2D6D12FF1B0B8CF20095A435 /* main.m in Sources */,
3646F8B41CA0F89C00E10774 /* JPLocker.m in Sources */,
367650481E2CC3BD00828E12 /* JPBlockWrapper.m in Sources */,
369EC2971C9925A400334A64 /* JPSpecialInit.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DE94AE201AF246C000E461D4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6C6CAC751C5F0BCA00444348 /* JPSuperTestObject.m in Sources */,
6C72B7961C352BA80086C98D /* newProtocolTest.m in Sources */,
DE94AE461AF2480000E461D4 /* JPTestObject.m in Sources */,
36CE191E1CAEA1DE007D73AC /* JPJSClassTest.m in Sources */,
36CE19251CB3E709007D73AC /* JPPerformanceTest.m in Sources */,
E1B89EA31B218986000645C2 /* JPInheritanceTestObjects.m in Sources */,
4F9EBFC91D50749200EC72C1 /* JPNumberTest.m in Sources */,
DE94AE2B1AF246C000E461D4 /* JSPatchTests.m in Sources */,
2DA3C42B206A1892005877CB /* newBlockTest.m in Sources */,
3694925F1CFEFE42003F44CA /* JPCFunctionTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
DE94AE261AF246C000E461D4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DE94AE0A1AF246BF00E461D4 /* JSPatchDemo */;
targetProxy = DE94AE251AF246C000E461D4 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
DE94AE2C1AF246C000E461D4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
DE94AE2D1AF246C000E461D4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
DE94AE2F1AF246C000E461D4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
INFOPLIST_FILE = "$(SRCROOT)/JSPatchDemo/Supporting Files/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_GENERATE_MAP_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
"../../**",
);
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = "";
PRODUCT_NAME = JSPatchDemo;
};
name = Debug;
};
DE94AE301AF246C000E461D4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
INFOPLIST_FILE = "$(SRCROOT)/JSPatchDemo/Supporting Files/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_GENERATE_MAP_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
"../../**",
);
ONLY_ACTIVE_ARCH = NO;
OTHER_LDFLAGS = "";
PRODUCT_NAME = JSPatchDemo;
};
name = Release;
};
DE94AE321AF246C000E461D4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = JSPatchTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = JSPatchDemoTests;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JSPatchDemo.app/JSPatchDemo";
};
name = Debug;
};
DE94AE331AF246C000E461D4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = JSPatchTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = JSPatchDemoTests;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JSPatchDemo.app/JSPatchDemo";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
DE94AE061AF246BF00E461D4 /* Build configuration list for PBXProject "JSPatchDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DE94AE2C1AF246C000E461D4 /* Debug */,
DE94AE2D1AF246C000E461D4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DE94AE2E1AF246C000E461D4 /* Build configuration list for PBXNativeTarget "JSPatchDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DE94AE2F1AF246C000E461D4 /* Debug */,
DE94AE301AF246C000E461D4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DE94AE311AF246C000E461D4 /* Build configuration list for PBXNativeTarget "JSPatchTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DE94AE321AF246C000E461D4 /* Debug */,
DE94AE331AF246C000E461D4 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = DE94AE031AF246BF00E461D4 /* Project object */;
}
================================================
FILE: Demo/iOSDemo/JSPatchDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Demo/iOSDemo/JSPatchDemo.xcodeproj/xcshareddata/xcschemes/JSPatchDemo.xcscheme
================================================
================================================
FILE: Demo/iOSDemo/JSPatchTests/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
net.cnbang.$(PRODUCT_NAME:rfc1034identifier)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
================================================
FILE: Demo/iOSDemo/JSPatchTests/InheritTest.js
================================================
var global = this;
(function() {
defineClass("JPInheritTest01ObjectB", {
m1: function() {
return "JP_01ObjB_m1";
}
});
defineClass("JPInheritTest02ObjectB", {
m1: function() {
return "JP_02ObjB_m1";
}
});
defineClass("JPInheritTest02ObjectC", {
m2: function() {
return "JP_02ObjC_m2";
}
});
})();
(function(){
defineClass("JPInheritTest02ObjectB", {
m1:function(){
return "JP_02ObjB_m1";
},
m3:function(){
return "JP_02ObjC_m3";
}
},
{});
defineClass("JPInheritTest02ObjectC", {
m2:function(){
return "JP_02ObjC_m2";
},
m3:function(){
return self.super().m3();
}
},
{});
})();
(function(){
defineClass("JPInheritTest03ObjectB", {
m1:function(){
return "JP_03ObjB_m1";
}
},
{});
defineClass("JPInheritTest03ObjectC", {
m2:function(){
return "JP_03ObjC_m2";
}
},
{});
})();
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPCFunctionTest.h
================================================
//
// JPCFunctionTest.h
// JSPatchDemo
//
// Created by bang on 6/1/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
@interface JPCFunctionTest : NSObject
+ (BOOL)testCfuncWithCGSize;
+ (BOOL)testCfuncWithCGRect;
+ (BOOL)testCfuncWithId;
+ (BOOL)testCfuncWithInt;
+ (BOOL)testCfuncWithCGFloat;
+ (BOOL)testCfuncReturnPointer;
+ (BOOL)testCFunctionReturnClass;
+ (BOOL)testCFunctionVoid;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPCFunctionTest.m
================================================
//
// JPCFunctionTest.m
// JSPatchDemo
//
// Created by bang on 6/1/16.
// Copyright © 2016 bang. All rights reserved.
//
#import "JPCFunctionTest.h"
#import
#import "JPEngine.h"
static bool voidFuncRet = false;
CGSize cfuncWithCGSize(CGSize size){
return size;
}
CGRect cfuncWithCGRect(CGRect rect){
return rect;
}
id cfuncWithId(NSString *str){
return str;
}
int cfuncWithInt(int num) {
return num;
}
CGFloat cfuncWithCGFloat(CGFloat num) {
return num;
}
void *cfuncReturnPointer() {
char *a = "abc";
return a;
}
bool cfuncWithPointerIsEqual(char *a) {
return a[0] == 'a';
}
void cfuncVoid() {
NSLog(@"dsssdfsdf");
}
@implementation JPCFunctionTest
+ (BOOL)testCfuncWithCGSize{
return NO;
}
+ (BOOL)testCfuncWithCGRect{
return NO;
}
+ (BOOL)testCfuncWithId{
return NO;
};
+ (BOOL)testCfuncWithInt{
return NO;
};
+ (BOOL)testCfuncWithCGFloat{
return NO;
};
+ (BOOL)testCfuncReturnPointer{
return NO;
};
+ (BOOL)testCFunctionReturnClass{
return NO;
};
+ (BOOL)testCFunctionVoid{
return voidFuncRet;
};
+ (void)setupCFunctionVoidSucc{
voidFuncRet = true;
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPInheritanceTestObjects.h
================================================
//
// JPInheritanceTestObjects.h
// JSPatchDemo
//
// Created by Qiu WeiJia on 6/5/15.
// Copyright (c) 2015 bang. All rights reserved.
//
#import
@interface JPInheritTest01ObjectA : NSObject
- (NSString*)m1;
- (NSString*)m2;
@end
@interface JPInheritTest01ObjectB : JPInheritTest01ObjectA
- (NSString*)m1;
@end
@interface JPInheritTest02ObjectA : NSObject
- (NSString*)m1;
- (NSString*)m2;
- (NSString*)m3;
@end
@interface JPInheritTest02ObjectB : JPInheritTest02ObjectA
- (NSString*)m1;
- (NSString*)m3;
@end
@interface JPInheritTest02ObjectC : JPInheritTest02ObjectB
- (NSString*)m2;
@end
@interface JPInheritTest03ObjectA : NSObject
- (NSString*)m1;
- (NSString*)m2;
@end
@interface JPInheritTest03ObjectB : JPInheritTest03ObjectA
- (NSString*)m1;
@end
@interface JPInheritTest03ObjectC : JPInheritTest03ObjectA
- (NSString*)m2;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPInheritanceTestObjects.m
================================================
//
// JPInheritanceTestObjects.m
// JSPatchDemo
//
// Created by Qiu WeiJia on 6/5/15.
// Copyright (c) 2015 bang. All rights reserved.
//
#import "JPInheritanceTestObjects.h"
@implementation JPInheritTest01ObjectA
- (NSString*)m1
{
return @"01ObjA_m1";
}
- (NSString*)m2
{
return @"01ObjA_m2";
}
@end
@implementation JPInheritTest01ObjectB
- (NSString*)m1
{
return @"01ObjB_m1";
}
@end
@implementation JPInheritTest02ObjectA
- (NSString*)m1
{
return @"02ObjA_m1";
}
- (NSString*)m2
{
return @"02ObjA_m2";
}
- (NSString*)m3
{
return @"02ObjA_m3";
}
@end
@implementation JPInheritTest02ObjectB
- (NSString*)m1
{
return @"02ObjB_m1";
}
- (NSString*)m3
{
return @"02ObjB_m3";
}
@end
@implementation JPInheritTest02ObjectC
- (NSString*)m2
{
return @"02ObjC_m2";
}
@end
@implementation JPInheritTest03ObjectA
- (NSString*)m1
{
return @"03ObjA_m1";
}
- (NSString*)m2
{
return @"03ObjA_m2";
}
@end
@implementation JPInheritTest03ObjectB
- (NSString*)m1
{
return @"03ObjB_m1";
}
@end
@implementation JPInheritTest03ObjectC
- (NSString*)m2
{
return @"03ObjC_m2";
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPJSClassTest.h
================================================
//
// JPJSClassTest.h
// JSPatchDemo
//
// Created by bang on 4/1/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
@interface JPJSClassTest : NSObject
+ (BOOL)isPassA;
+ (BOOL)isPassB;
+ (BOOL)isPassC;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPJSClassTest.m
================================================
//
// JPJSClassTest.m
// JSPatchDemo
//
// Created by bang on 4/1/16.
// Copyright © 2016 bang. All rights reserved.
//
#import "JPJSClassTest.h"
@implementation JPJSClassTest
+ (BOOL)isPassA
{
return NO;
}
+ (BOOL)isPassB
{
return NO;
}
+ (BOOL)isPassC
{
return NO;
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPMultithreadTestObject.h
================================================
//
// MultithreadTestObject.h
// JSPatchDemo
//
// Created by Qiu WeiJia on 15/6/4.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import
@interface JPMultithreadTestObject : NSObject
{
NSMutableArray *_values;
}
@property int objectId;
- (instancetype)init;
- (void)addValueJS:(NSNumber*)number;
- (void)addValue:(NSNumber*)number;
- (void)addValueNoPatch:(NSNumber*)number;
- (BOOL)checkAllValues;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPMultithreadTestObject.m
================================================
//
// MultithreadTestObject.m
// JSPatchDemo
//
// Created by Qiu WeiJia on 15/6/4.
// Copyright (c) 2015年 bang. All rights reserved.
//
#import "JPMultithreadTestObject.h"
@implementation JPMultithreadTestObject
- (instancetype)init {
self = [super init];
if (self) {
_values = [[NSMutableArray alloc] init];
[_values addObject:[NSNumber numberWithInt:-1]];
}
return self;
}
- (void)addValueJS:(NSNumber*)number
{
}
- (void)addValue:(NSNumber*)number
{
if ([_values count] > 0 && [[_values objectAtIndex:0] integerValue] < 0) {
[_values removeAllObjects];
}
[_values addObject:number];
}
- (void)addValueNoPatch:(NSNumber*)number
{
[_values addObject:number];
}
- (BOOL)checkAllValues
{
for (NSNumber *num in _values) {
if ([num intValue] != self.objectId) {
return FALSE;
}
}
return TRUE;
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPNumberTest.h
================================================
//
// JPNumberTest.h
// JSPatchDemo
//
// Created by pucheng on 16/8/2.
// Copyright © 2016年 bang. All rights reserved.
//
#import
@interface JPNumberTest : NSObject
+ (BOOL)testJPNumNSNumber;
+ (BOOL)testJPNumNSDecimalNumber;
+ (BOOL)testJPNumToJS;
+ (BOOL)testJPNUmToOC;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPNumberTest.m
================================================
//
// JPNumberTest.m
// JSPatchDemo
//
// Created by pucheng on 16/8/2.
// Copyright © 2016年 bang. All rights reserved.
//
#import "JPNumberTest.h"
@implementation JPNumberTest
+ (BOOL)testJPNumNSNumber {
return NO;
}
+ (BOOL)testJPNumNSDecimalNumber {
return NO;
}
+ (BOOL)testJPNumToJS {
return NO;
}
+ (BOOL)testJPNUmToOC {
return NO;
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPPerformanceTest.h
================================================
//
// JPPerformanceTest.h
// JSPatchDemo
//
// Created by bang on 4/5/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
@interface JPPerformanceTest : NSObject
- (void)testJSCallOCEmptyMethod;
- (void)testJSCallOCMethodWithParamObject;
- (void)testJSCallOCMethodReturnObject;
- (void)testJSCallJSEmptyMethod;
- (void)testJSCallJSMethodWithLargeDictionaryParam;
- (void)testJSCallJSMethodWithLargeDictionaryParamAutoConvert;
- (void)testJSCallJSMethodWithParam;
- (void)testOCCallEmptyMethod;
- (void)testOCCallMethodWithParamObject;
- (void)testOCCallMethodReturnObject;
- (void)testJSCallMallocJPMemory;
- (void)testJSCallMallocJPCFunction;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPPerformanceTest.m
================================================
//
// JPPerformanceTest.m
// JSPatchDemo
//
// Created by bang on 4/5/16.
// Copyright © 2016 bang. All rights reserved.
//
#import "JPPerformanceTest.h"
#import
@implementation JPPerformanceTest
//overrided in JS
- (void)testJSCallOCEmptyMethod {}
- (void)testJSCallOCMethodWithParamObject{}
- (void)testJSCallOCMethodReturnObject{}
- (void)testJSCallJSEmptyMethod{}
- (void)testJSCallJSMethodWithLargeDictionaryParam{}
- (void)testJSCallJSMethodWithLargeDictionaryParamAutoConvert{}
- (void)testJSCallJSMethodWithParam{}
- (void)testOCCallEmptyMethod {
for (int i = 0; i < 10000; i ++) {
[self emptyMethodToOverride];
}
}
- (void)testOCCallMethodWithParamObject {
NSObject *obj = [[NSObject alloc] init];
for (int i = 0; i < 10000; i ++) {
[self methodWithParamObjectToOverride:obj];
}
}
- (void)testOCCallMethodReturnObject {
id ret;
for (int i = 0; i < 10000; i ++) {
ret = [self methodReturnObjectToOverride];
}
}
- (void)testJSCallMallocJPMemory{}
- (void)testJSCallMallocJPCFunction{}
#pragma mark performance
static NSObject *testPerformanceObj;
- (void)initTestPerformanceObj {
if (!testPerformanceObj) testPerformanceObj = [[NSObject alloc] init];
}
- (void)emptyMethod {
}
- (void)methodWithParamObject:(NSObject *)obj {
}
- (NSObject *)methodReturnObject {
return testPerformanceObj;
}
- (void)emptyMethodToOverride {
}
- (void)methodWithParamObjectToOverride:(NSObject *)obj {
}
- (NSObject *)methodReturnObjectToOverride {
return nil;
}
- (void)allArgSumWithBlock:(double (^)(CGFloat arg0, CGPoint arg1, NSInteger arg2, id arg3))block {
NSNumber *arg3 = [NSNumber numberWithDouble:3.3];
double sum = block(3.2, (CGPoint){1.1,1.2}, 10,arg3);
NSLog(@"==== sum = %@",@(sum));
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPSuperTestObject.h
================================================
//
// JPSuperTestObject.h
// JSPatchDemo
//
// Created by bang on 4/1/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
@interface JPSuperTestA : NSObject
@end
@interface JPSuperTestB : NSObject
@end
@interface JPSuperTestB1 : JPSuperTestB
@end
@interface JPSuperTestC : NSObject
@end
@interface JPSuperTestC1 : JPSuperTestC
@end
@interface JPSuperTestC2 : JPSuperTestC1
@end
@interface JPSuperTestResult : NSObject
+ (BOOL)isPassA;
+ (BOOL)isPassB;
+ (BOOL)isPassC;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPSuperTestObject.m
================================================
//
// JPSuperTestObject.m
// JSPatchDemo
//
// Created by bang on 4/1/16.
// Copyright © 2016 bang. All rights reserved.
//
#import "JPSuperTestObject.h"
@implementation JPSuperTestA
- (NSString *)method {
return @"A";
}
@end
@implementation JPSuperTestB
- (NSString *)method {
return @"B";
}
@end
@implementation JPSuperTestB1
- (NSString *)method {
return [NSString stringWithFormat:@"%@%@", [super method], @"1"];
}
@end
@implementation JPSuperTestC
- (NSString *)method {
return @"C";
}
@end
@implementation JPSuperTestC1
- (NSString *)method {
return [NSString stringWithFormat:@"%@%@", [super method], @"1"];
}
@end
@implementation JPSuperTestC2
- (NSString *)method {
return [NSString stringWithFormat:@"%@%@", [super method], @"2"];
}
@end
@implementation JPSuperTestResult
+ (BOOL)isPassA {
return NO;
}
+ (BOOL)isPassB {
return NO;
}
+ (BOOL)isPassC {
JPSuperTestC2 *c = [[JPSuperTestC2 alloc] init];
return [[c method] isEqualToString:@"C1C2"];
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPTestObject.h
================================================
//
// ISTestObject.h
// InstaScript
//
// Created by bang on 15/4/30.
// Copyright (c) 2015 bang. All rights reserved.
//
#import
#import
@interface JPTestObject : NSObject
- (void)funcWithInt:(int)intValue;
@property (nonatomic, assign) BOOL funcReturnVoidPassed;
@property (nonatomic, assign) BOOL funcReturnStringPassed;
@property (nonatomic, assign) BOOL funcReturnDoublePassed;
@property (nonatomic, assign) BOOL funcReturnClassPassed;
@property (nonatomic, assign) BOOL funcReturnViewWithFramePassed;
@property (nonatomic, assign) BOOL funcWithViewAndReturnViewPassed;
@property (nonatomic, assign) BOOL funcWithIntPassed;
@property (nonatomic, assign) BOOL funcWithNilPassed;
@property (nonatomic, assign) BOOL funcReturnNilPassed;
@property (nonatomic, assign) BOOL funcWithNilAndOthersPassed;
@property (nonatomic, assign) BOOL funcWithNullPassed;
@property (nonatomic, assign) BOOL funcTestBoolPassed;
@property (nonatomic, assign) BOOL funcTestNSNumberPassed;
@property (nonatomic, assign) BOOL funcWithDictAndDoublePassed;
@property (nonatomic, assign) BOOL funcWithRangeAndReturnRangePassed;
@property (nonatomic, assign) BOOL funcWithRectAndReturnRectPassed;
@property (nonatomic, assign) BOOL funcWithPointAndReturnPointPassed;
@property (nonatomic, assign) BOOL funcWithSizeAndReturnSizePassed;
@property (nonatomic, assign) BOOL funcWithClassAndReturnStringPassed;
@property (nonatomic, assign) BOOL funcReturnDictStringIntPassed;
@property (nonatomic, assign) BOOL funcReturnDictStringViewPassed;
@property (nonatomic, assign) BOOL funcReturnArrayControllerViewStringPassed;
@property (nonatomic, assign) BOOL funcReturnDictPassed;
@property (nonatomic, assign) BOOL testBoxingObjPassed;
@property (nonatomic, assign) BOOL funcReturnBlockPassed;
@property (nonatomic, assign) BOOL funcReturnObjectBlockPassed;
@property (nonatomic, assign) BOOL funcReturnObjectBlockReturnValuePassed;
@property (nonatomic, assign) BOOL funcReturnJSBlockPassed;
@property (nonatomic, assign) BOOL callBlockWithStringAndIntPassed;
@property (nonatomic, assign) BOOL callBlockWithStringAndIntReturnValuePassed;
@property (nonatomic, assign) BOOL callBlockWithArrayAndViewPassed;
@property (nonatomic, assign) BOOL callBlockWithBoolAndBlockPassed;
@property (nonatomic, assign) BOOL callBlockWithObjectAndBlockPassed;
@property (nonatomic, assign) BOOL callBlockWithObjectAndBlockReturnValuePassed;
@property (nonatomic, assign) BOOL callBlockWithDoubleAndReturnDoublePassed;
@property (nonatomic, assign) BOOL funcToSwizzleWithStringViewIntPassed;
@property (nonatomic, assign) BOOL funcToSwizzleViewPassed;
@property (nonatomic, assign) BOOL funcToSwizzleViewCalledOriginalPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnViewPassed;
@property (nonatomic, assign) BOOL funcToSwizzleParamNilPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnIntPassed;
@property (nonatomic, assign) BOOL funcToSwizzleWithBlockPassed;
@property (nonatomic, assign) BOOL funcToSwizzle_withUnderLine_Passed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnRectPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnPointPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnSizePassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnRangePassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnEdgeInsetsPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnRectJSPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnPointJSPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnSizeJSPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnRangeJSPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnEdgeInsetsJSPassed;
@property (nonatomic, assign) BOOL funcToSwizzleTestGCDPassed;
@property (nonatomic, assign) BOOL funcToSwizzleTestClassPassed;
@property (nonatomic, assign) BOOL funcToSwizzleTestSelectorPassed;
@property (nonatomic, assign) BOOL funcToSwizzleTestCharPassed;
@property (nonatomic, assign) BOOL funcToSwizzleReturnClassPassed;
@property (nonatomic, assign) BOOL funcTestCharPassed;
@property (nonatomic, assign) BOOL funcToSwizzleTestPointerPassed;
@property (nonatomic, assign) BOOL funcTestPointerPassed;
@property (nonatomic, assign) BOOL funcTestSizeofPassed;
@property (nonatomic, assign) BOOL funcTestGetPointerPassed;
@property (nonatomic, assign) BOOL funcTestNSErrorPointerPassed;
@property (nonatomic, assign) BOOL funcTestNilParametersInBlockPassed;
@property (nonatomic, assign) BOOL classFuncToSwizzlePassed;
@property (nonatomic, assign) BOOL classFuncToSwizzleReturnObjPassed;
@property (nonatomic, assign) BOOL classFuncToSwizzleReturnObjCalledOriginalPassed;
@property (nonatomic, assign) BOOL classFuncToSwizzleReturnIntPassed;
@property (nonatomic, assign) BOOL classFuncToSwizzleReturnDoublePassed;
@property (nonatomic, assign) BOOL funcCallSuperPassed;
@property (nonatomic, assign) BOOL callForwardInvocationPassed;
@property (nonatomic, strong) UIView *testView;
@property (nonatomic, assign) BOOL propertySetFramePassed;
@property (nonatomic, assign) BOOL propertySetViewPassed;
@property (nonatomic, assign) BOOL newTestObjectReturnViewPassed;
@property (nonatomic, assign) BOOL newTestObjectReturnBoolPassed;
@property (nonatomic, assign) BOOL newTestObjectCustomFuncPassed;
@property (nonatomic, assign) BOOL mutableArrayPassed;
@property (nonatomic, assign) BOOL mutableStringPassed;
@property (nonatomic, assign) BOOL mutableDictionaryPassed;
@property (nonatomic, assign) BOOL funcWithTransformPassed;
@property (nonatomic, assign) BOOL transformTranslatePassed;
@property (nonatomic, assign) BOOL funcWithRectPointerPassed;
@property (nonatomic, assign) BOOL funcWithTransformPointerPassed;
@property (nonatomic, assign) BOOL consoleLogPassed;
@property (nonatomic, assign) BOOL overrideParentMethodPassed;
@property (nonatomic, assign) BOOL variableParameterMethodPassed;
- (NSString*)funcOverrideParentMethod;
- (void)funcToSwizzleTestGCD:(void(^)())block;
- (NSDictionary *)funcToSwizzleReturnDictionary:(NSDictionary *)dict;
- (NSDictionary *)funcToSwizzleReturnJSDictionary;
- (NSArray *)funcToSwizzleReturnArray:(NSArray *)arr;
- (NSString *)funcToSwizzleReturnString:(NSString *)str;
@end
@interface JPTestSubObject : JPTestObject
@property (nonatomic, assign) BOOL funcCallSuperSubObjectPassed;
@end
@protocol JPTestProtocol
- (double)protocolWithDouble:(double)num dict:(NSDictionary *)dictionary;
+ (NSString *)classProtocolWithString:(NSString *)string int:(NSInteger)num;
@end
@protocol JPTestProtocol2
@optional
- (NSInteger)protocolWithInt:(NSInteger)num;
@end
@interface JPTestProtocolObject : NSObject
- (BOOL)testProtocolMethods;
@end
@interface JPTestSwizzledForwardInvocationSuperObject : NSObject
@property (nonatomic, assign) BOOL callSwizzledSuperForwardInvocationPassed;
- (void)swizzleSuperForwoardInvocation;
@end
@interface JPTestSwizzledForwardInvocationSubObject : JPTestSwizzledForwardInvocationSuperObject
- (void)callTestSwizzledSuperForwardInvocation;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JPTestObject.m
================================================
//
// JPTestObject.m
// InstaScript
//
// Created by bang on 15/4/30.
// Copyright (c) 2015 bang. All rights reserved.
//
#import "JPTestObject.h"
#import
@implementation JPTestObject
- (void)funcReturnVoid
{
self.funcReturnVoidPassed = YES;
}
- (NSString *)funcReturnString
{
return @"stringFromOC";
}
+ (NSString *)classFunCallReturnString
{
return @"classFunCallReturnString";
}
- (Class)funcReturnClass
{
return [self class];
}
- (Class)funcToSwizzleReturnClass
{
return nil;
}
- (double)funcReturnDouble {
return 100.0;
}
- (CGRect)funcWithRectAndReturnRect:(CGRect)rect
{
return rect;
}
- (CGPoint)funcWithPointAndReturnPoint:(CGPoint)point
{
return point;
}
- (CGSize)funcWithSizeAndReturnSize:(CGSize)size
{
return size;
}
- (NSRange)funcWithRangeAndReturnRange:(NSRange)range
{
return range;
}
- (UIView *)funcReturnViewWithFrame:(CGRect)frame
{
UIView *view = [[UIView alloc] initWithFrame:frame];
return view;
}
- (UIView *)funcWithViewAndReturnView:(UIView *)view
{
return view;
}
- (NSString *)funcWithClassAndReturnString:(Class)cls
{
return NSStringFromClass(cls);
}
- (void)funcWithInt:(int)intValue
{
self.funcWithIntPassed = intValue == 42;
}
- (void)funcWithNil:(NSObject *)nilObj
{
self.funcWithNilPassed = nilObj == nil;
}
- (id)funcReturnNil
{
return nil;
}
- (BOOL)funcTestBool:(BOOL)b
{
return b;
}
- (NSNumber *)funcTestNSNumber:(NSNumber *)num
{
return num;
}
- (void)funcWithNil:(NSObject *)nilObj dict:(NSDictionary *)dict str:(NSString *)str num:(double)num
{
self.funcWithNilAndOthersPassed = nilObj == nil && [dict[@"k"] isEqualToString:@"JSPatch"] && [str isEqualToString:@"JSPatch"] && num - 4.2 < 0.001;
}
- (void)funcWithNull:(NSNull *)nullObj
{
self.funcWithNullPassed = [nullObj isKindOfClass:[NSNull class]];
}
#pragma mark - NSDictionary / NSArray
- (void)funcWithDict:(NSDictionary *)dict andDouble:(double)doubleValue
{
BOOL dictPass = [dict[@"test"] isEqualToString:@"test"];
BOOL doublePass = doubleValue - 4.2 < 0.001;
self.funcWithDictAndDoublePassed = dictPass && doublePass;
}
- (NSDictionary *)funcReturnDict:(NSDictionary *)dict
{
return dict;
}
- (NSDictionary *)funcReturnDictStringInt
{
return @{@"str": @"stringFromOC", @"num": @(42)};
}
- (NSDictionary *)funcReturnDictStringView
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
return @{@"view": view, @"str": @"stringFromOC"};
}
- (NSArray *)funcReturnArrayControllerViewString
{
UIViewController *controller = [[UIViewController alloc] init];
UIView *view = [[UIView alloc] init];
return @[controller, view, @"stringFromOC"];
}
- (NSString *)getString
{
return @"JSPatch";
}
- (NSArray *)getArray
{
return @[@"JSPatch", @(1)];
}
- (NSDictionary *)getDictionary
{
return @{@"k": @"JSPatch"};
}
- (void)funcTestBoxingObj:(NSArray *)data
{
NSString *str = data[0];
NSDictionary *dict = data[1];
NSArray *arr = data[2];
self.testBoxingObjPassed = [str isEqualToString:[self getString]] && [dict[@"k"] isEqualToString:[[self getDictionary] objectForKey:@"k"]] && [arr[0] isEqualToString:[[self getArray] objectAtIndex:0]];
}
#pragma mark - block
typedef void (^ISTestBlock)(NSString *str, int num);
- (ISTestBlock)funcReturnBlock
{
ISTestBlock block = ^(NSString *str, int num) {
self.funcReturnBlockPassed = [str isEqualToString:@"stringFromJS"] && num == 42;
};
return block;
}
typedef id (^JPTestObjectBlock)(NSDictionary *dict, UIView *view);
- (JPTestObjectBlock)funcReturnObjectBlock
{
JPTestObjectBlock block = ^(NSDictionary *dict, UIView *view) {
self.funcReturnObjectBlockPassed = [dict[@"str"] isEqualToString:@"stringFromJS"] && [dict[@"view"] isKindOfClass:[UIView class]] && view.frame.size.width == 100;
return @"succ";
};
return block;
}
- (ISTestBlock)funcReturnJSBlock:(ISTestBlock)jsblock
{
return jsblock;
}
- (void)callBlockWithStringAndInt:(id(^)(NSString *str, int num))block
{
id ret = block(@"stringFromOC", 42);
self.callBlockWithStringAndIntReturnValuePassed = [ret isEqualToString:@"succ"];
}
- (void)callBlockDelay:(id(^)(NSString *str, int num))block
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
id ret = block(@"stringFromOC", 42);
self.callBlockWithStringAndIntReturnValuePassed = [ret isEqualToString:@"succ"];
});
}
- (void)callBlockWithArrayAndView:(void(^)(NSArray *arr, UIView *view))block
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
block(@[@"stringFromOC", view], view);
}
- (void)callBlockWithBoolAndBlock:(void(^)(BOOL b, ISTestBlock block))block
{
ISTestBlock cbBlock = ^(NSString *str, int num) {
self.callBlockWithBoolAndBlockPassed = [str isEqualToString:@"stringFromJS"] && num == 42;
};
block(YES, cbBlock);
}
- (void)callBlockWithObjectAndBlock:(void(^)(UIView *view, JPTestObjectBlock block))block
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
JPTestObjectBlock cbBlock = ^id(NSDictionary *dict, UIView *view) {
self.callBlockWithObjectAndBlockPassed = [dict[@"str"] isEqualToString:@"stringFromJS"] && [dict[@"view"] isKindOfClass:[UIView class]] && view.frame.size.width == 100;
return @"succ";
};
block(view, cbBlock);
}
- (void)callBlockWithDouble:(double(^)(double num))block
{
double ret = block(4.2);
self.callBlockWithDoubleAndReturnDoublePassed = fabs(ret - 8.4) < 0.1;
}
#pragma mark - swizzle
typedef struct {
char *name;
int idx;
}JPTestStruct;
- (void)callSwizzleMethod
{
[self funcToSwizzleWithString:@"stringFromOC" view:[[UIView alloc] init] int:42];
[self funcToSwizzle:4.2 view:[[UIView alloc] init]];
UIView *view = [self funcToSwizzleReturnView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]];
self.funcToSwizzleReturnViewPassed = view.frame.size.width == 100;
UIView *nilView = [self funcToSwizzleReturnView:nil];
self.funcToSwizzleParamNilPassed = !nilView;
int num = [self funcToSwizzleReturnInt:42];
self.funcToSwizzleReturnIntPassed = num == 42;
[JPTestObject classFuncToSwizzle:self int:10];
id ret = [JPTestObject classFuncToSwizzleReturnObj:self];
if ([ret isKindOfClass:[JPTestObject class]]) {
self.classFuncToSwizzleReturnObjPassed = YES;
}
int retI = [JPTestObject classFuncToSwizzleReturnInt:42];
if (retI == 42) {
self.classFuncToSwizzleReturnIntPassed = YES;
}
double retD = [JPTestObject classFuncToSwizzleReturnDouble:100.0];
if (fabs(retD - 100.0) < FLT_EPSILON) {
self.classFuncToSwizzleReturnDoublePassed = YES;
}
[self funcToSwizzleWithBlock:^(UIView *view, int num) {
self.funcToSwizzleWithBlockPassed = view && num == 42;
}];
[self funcToSwizzle_withUnderLine_:42];
CGRect rect = [self funcToSwizzleReturnRect:CGRectMake(0, 0, 100, 100)];
self.funcToSwizzleReturnRectPassed = rect.size.width == 100;
CGPoint point = [self funcToSwizzleReturnPoint:CGPointMake(42, 42)];
self.funcToSwizzleReturnPointPassed = point.x == 42;
CGSize size = [self funcToSwizzleReturnSize:CGSizeMake(42, 42)];
self.funcToSwizzleReturnSizePassed = size.width == 42;
NSRange range = [self funcToSwizzleReturnRange:NSMakeRange(0, 42)];
self.funcToSwizzleReturnRangePassed = range.length == 42;
UIEdgeInsets edgeInsets = [self funcToSwizzleReturnEdgeInsets:UIEdgeInsetsMake(42, 42, 0, 0)];
self.funcToSwizzleReturnEdgeInsetsPassed = edgeInsets.left == 42;
SEL selector = [self funcToSwizzleTestSelector:@selector(funcToSwizzleTestSelector:)];
self.funcToSwizzleTestSelectorPassed = [NSStringFromSelector(selector) isEqualToString:@"funcToSwizzleTestSelector:"];
char *cStr = [self funcToSwizzleTestChar:"JSPatch"];
self.funcToSwizzleTestCharPassed = strcmp("JSPatch", cStr) == 0;
Class myClass = [self funcToSwizzleReturnClass];
self.funcToSwizzleReturnClassPassed = [NSStringFromClass(myClass) isEqualToString:@"UIView"];
JPTestStruct *testStruct = (JPTestStruct*)malloc(sizeof(JPTestStruct));
testStruct->idx = 42;
testStruct->name = "JSPatch";
JPTestStruct *testStructReturn = [self funcToSwizzleTestPointer:testStruct];
self.funcToSwizzleTestPointerPassed = testStructReturn->idx == 42 && strcmp(testStructReturn->name, "JSPatch") == 0;
}
- (void)funcToSwizzleWithString:(NSString *)str view:(UIView *)view int:(NSInteger)i
{
self.funcToSwizzleWithStringViewIntPassed = NO;
}
- (void)funcToSwizzle:(double)num view:(UIView *)view
{
self.funcToSwizzleViewCalledOriginalPassed = 4.2 - num< 0.01 && view;
}
- (UIView *)funcToSwizzleReturnView:(UIView *)view
{
return nil;
}
- (int)funcToSwizzleReturnInt:(int)num
{
return 0;
}
- (NSDictionary *)funcToSwizzleReturnDictionary:(NSDictionary *)dict
{
return nil;
}
- (NSDictionary *)funcToSwizzleReturnJSDictionary
{
return nil;
}
- (NSArray *)funcToSwizzleReturnArray:(NSArray *)arr
{
return nil;
}
- (NSString *)funcToSwizzleReturnString:(NSString *)str
{
return nil;
}
- (void)funcToSwizzleWithBlock:(void(^)(UIView *view, int num))block
{
}
- (void)funcToSwizzle_withUnderLine_:(int)num
{
}
- (CGRect)funcToSwizzleReturnRect:(CGRect)rect
{
return CGRectZero;
}
- (CGPoint)funcToSwizzleReturnPoint:(CGPoint)point
{
return CGPointZero;
}
- (CGSize)funcToSwizzleReturnSize:(CGSize)size
{
return CGSizeZero;
}
- (NSRange)funcToSwizzleReturnRange:(NSRange)range
{
return NSMakeRange(0, 0);
}
- (UIEdgeInsets)funcToSwizzleReturnEdgeInsets:(UIEdgeInsets)edgeInsets
{
return UIEdgeInsetsZero;
}
- (void)funcToSwizzleTestGCD:(void(^)())block
{
}
- (Class)funcToSwizzleTestClass:(Class)cls
{
return nil;
}
- (SEL)funcToSwizzleTestSelector:(SEL)selector
{
return nil;
}
- (char *)funcToSwizzleTestChar:(char *)cStr
{
return NULL;
}
- (char *)funcReturnChar
{
return "JSPatch";
}
- (void)funcTestChar:(char *)cStr
{
self.funcTestCharPassed = strcmp("JSPatch", cStr) == 0;
}
- (void *)funcToSwizzleTestPointer:(void *)pointer
{
return NULL;
}
- (BOOL)funcTestNSErrorPointer:(NSError **)error
{
NSError *tmp = [[NSError alloc]initWithDomain:@"com.albert43" code:43 userInfo:@{@"msg":@"test error"}];
if (error)
*error = tmp;
return NO;
}
- (void *)funcReturnPointer
{
JPTestStruct *testStruct = (JPTestStruct*)malloc(sizeof(JPTestStruct));
testStruct->idx = 42;
testStruct->name = "JSPatch";
return testStruct;
}
- (void)funcTestPointer:(void *)pointer
{
JPTestStruct *testStruct = pointer;
self.funcTestPointerPassed = testStruct->idx == 42 && strcmp(testStruct->name, "JSPatch") == 0;
}
- (BOOL)funcTestGetPointer1:(NSString *)str
{
if ([str isEqualToString:@"JSPatch"]) {
return YES;
}
return NO;
}
- (BOOL)funcTestGetPointer2:(NSError *)error
{
if ([[[error userInfo] description] isEqualToString:[@{@"msg":@"test"} description]]) {
return YES;
}
return NO;
}
- (BOOL)funcTestGetPointer3:(void *)arr
{
char *p = arr;
for (int i = 0; i < 10; i++) {
if (p[i] != 'A') {
return false;
}
}
return true;
}
typedef NSString * (^JSBlock)(NSError *);
- (JSBlock)funcGenerateBlock {
JSBlock block = ^(NSError *err) {
if (err) {
return [err description];
}else {
return @"no error";
}
};
return block;
}
- (NSString *)excuteBlockWithNilParameters:(JSBlock)blk {
if (blk) {
return blk(nil);
}
return nil;
}
+ (void)classFuncToSwizzle:(JPTestObject *)testObject int:(NSInteger)i
{
}
+ (id)classFuncToSwizzleReturnObj:(JPTestObject *)obj
{
obj.classFuncToSwizzleReturnObjCalledOriginalPassed = YES;
return nil;
}
+ (int)classFuncToSwizzleReturnInt:(int)i
{
return 0;
}
+ (double)classFuncToSwizzleReturnDouble:(double)d
{
return 0;
}
#pragma mark - super
- (void)funcCallSuper
{
self.funcCallSuperPassed = YES;
}
#pragma mark - performance
- (void)pFuncVoid
{
}
- (int)pFuncReturnInt
{
return 42;
}
- (void)pFuncParamInt:(int)num
{
}
- (id)pFuncReturnSelf
{
return self;
}
- (void)pFuncParamSelf:(id)obj
{
}
#pragma mark - forward
- (void)callTestForward
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
[self performSelector:@selector(testForward) withObject:nil];
#pragma clang diagnostic pop
}
- (void)funcToForward
{
self.callForwardInvocationPassed = YES;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([NSStringFromSelector(anInvocation.selector) isEqualToString:@"testForward"]) {
[self funcToForward];
}
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
if ([NSStringFromSelector(aSelector) isEqualToString:@"funcToSwizzleRect:"]) {
NSLog(@"ss");
}
if ([NSStringFromSelector(aSelector) isEqualToString:@"testForward"]) {
return [self methodSignatureForSelector:@selector(funcToForward)];
}
return [super methodSignatureForSelector:aSelector];
}
#pragma mark -
- (NSString*)funcOverrideParentMethod
{
return @"orgi";
}
#pragma mark CGAffineTransform
- (CGAffineTransform)funcWithTransform:(CGAffineTransform)transform
{
return transform;
}
#pragma mark structPointer
- (void)funcWithRectPointer:(CGRect *)rect
{
self.funcWithRectPointerPassed = rect->size.width == 100;
rect->origin.x = 42;
}
- (void)funcWithTransformPointer:(CGAffineTransform *)transform
{
self.funcWithTransformPointerPassed = transform->a == 100;
transform->tx = 42;
}
@end
@implementation JPTestSubObject
- (instancetype)init
{
self = [super init];
if (self) {
self.funcCallSuperSubObjectPassed = YES;
}
return self;
}
- (void)funcCallSuper
{
self.funcCallSuperSubObjectPassed = NO;
}
@end
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprotocol"
@implementation JPTestProtocolObject
- (BOOL)testProtocolMethods
{
double dNum = [self protocolWithDouble:4.2 dict:@{@"name": @"JSPatch"}];
NSInteger iNum = [self protocolWithInt:42];
NSString *str = [JPTestProtocolObject classProtocolWithString:@"JSPatch" int:42];
return dNum - 4.2 < 0.001 && iNum == 42 && [str isEqualToString:@"JSPatch"];
}
#pragma clang diagnostic pop
@end
@implementation JPTestSwizzledForwardInvocationSuperObject
- (void)swizzleSuperForwoardInvocation
{
class_replaceMethod([JPTestSwizzledForwardInvocationSuperObject class], @selector(forwardInvocation:), (IMP)SwizzledSuperForwardInvocation, "v@:@");
}
static void SwizzledSuperForwardInvocation(__unsafe_unretained id assignSlf, SEL selector, NSInvocation *invocation)
{
if ([NSStringFromSelector(invocation.selector) isEqualToString:@"testSwizzledSuperForwardInvocation"]) {
((JPTestSwizzledForwardInvocationSuperObject *)assignSlf).callSwizzledSuperForwardInvocationPassed = YES;
}
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([NSStringFromSelector(anInvocation.selector) isEqualToString:@"testSwizzledSuperForwardInvocation"]) {
self.callSwizzledSuperForwardInvocationPassed = NO;
}
}
@end
@implementation JPTestSwizzledForwardInvocationSubObject
- (void)callTestSwizzledSuperForwardInvocation
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
[self performSelector:@selector(testSwizzledSuperForwardInvocation) withObject:nil];
#pragma clang diagnostic pop
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
if ([NSStringFromSelector(aSelector) isEqualToString:@"testSwizzledSuperForwardInvocation"]) {
return [self methodSignatureForSelector:@selector(callTestSwizzledSuperForwardInvocation)];
}
return [super methodSignatureForSelector:aSelector];
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/JSPatchTests.m
================================================
//
// InstaScriptTests.m
// InstaScriptTests
//
// Created by bang on 15/4/30.
// Copyright (c) 2015 bang. All rights reserved.
//
#import
#import
#import "JPEngine.h"
#import "JPTestObject.h"
#import "JPInheritanceTestObjects.h"
#import "JPMultithreadTestObject.h"
#import "newProtocolTest.h"
#import "JPSuperTestObject.h"
#import "JPJSClassTest.h"
#import "JPMemory.h"
#import "JPPerformanceTest.h"
#import "JPCFunctionTest.h"
#import "JPNumberTest.h"
#import "newBlockTest.h"
@interface JSPatchTests : XCTestCase
@end
@implementation JSPatchTests
- (void)loadPatch:(NSString *)patchName
{
NSString *jsPath = [[NSBundle bundleForClass:[self class]] pathForResource:patchName ofType:@"js"];
[JPEngine evaluateScriptWithPath:jsPath];
}
- (void)setUp {
[super setUp];
[JPEngine startEngine];
[JPEngine addExtensions:@[@"JPMemory", @"JPStructPointer", @"JPCoreGraphics", @"JPUIKit"]];
}
- (void)tearDown {
[super tearDown];
}
- (void)testEngine {
[self loadPatch:@"test"];
JSValue *objValue = [JPEngine context][@"ocObj"];
JPTestObject *obj = [objValue toObjectOfClass:[JPTestObject class]];
JSValue *subObjValue = [JPEngine context][@"subObj"];
JPTestSubObject *subObj = [subObjValue toObjectOfClass:[JPTestSubObject class]];
XCTAssert(obj.funcReturnVoidPassed, @"funcReturnVoidPassed");
XCTAssert(obj.funcReturnStringPassed, @"funcReturnStringPassed");
XCTAssert(obj.funcReturnClassPassed, @"funcReturnClassPassed");
// Test for functions which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0
// This case shall fail if you comment line 957~959 in JPEngine.m on iOS7.0.
XCTAssert(obj.funcReturnDoublePassed, @"funcReturnDoublePassed");
XCTAssert(obj.funcWithIntPassed, @"funcWithIntPassed");
XCTAssert(obj.funcWithNilPassed, @"funcWithNilPassed");
XCTAssert(obj.funcReturnNilPassed, @"funcReturnNilPassed");
XCTAssert(obj.funcWithNilAndOthersPassed, @"funcWithNilAndOthersPassed");
XCTAssert(obj.funcWithNullPassed, @"funcWithNullPassed");
XCTAssert(obj.funcTestBoolPassed, @"funcTestBoolPassed");
XCTAssert(obj.funcTestNSNumberPassed, @"funcTestNSNumberPassed");
XCTAssert(obj.funcWithDictAndDoublePassed, @"funcWithDictAndDoublePassed");
XCTAssert(obj.funcWithRectAndReturnRectPassed, @"funcWithRectAndReturnRectPassed");
XCTAssert(obj.funcWithSizeAndReturnSizePassed, @"funcWithSizeAndReturnSizePassed");
XCTAssert(obj.funcWithPointAndReturnPointPassed, @"funcWithPointAndReturnPointPassed");
XCTAssert(obj.funcWithRangeAndReturnRangePassed, @"funcWithRangeAndReturnRangePassed");
XCTAssert(obj.funcWithClassAndReturnStringPassed, @"funcWithClassAndReturnInstancePassed");
XCTAssert(obj.funcReturnViewWithFramePassed, @"funcReturnViewWithFramePassed");
XCTAssert(obj.funcWithViewAndReturnViewPassed, @"funcWithViewAndReturnViewPassed");
XCTAssert(obj.funcReturnDictStringViewPassed, @"funcReturnDictStringViewPassed");
XCTAssert(obj.funcReturnDictStringIntPassed, @"funcReturnDictStringIntPassed");
XCTAssert(obj.funcReturnArrayControllerViewStringPassed, @"funcReturnArrayControllerViewStringPassed");
XCTAssert(obj.funcReturnDictPassed, @"funcReturnDictPassed");
XCTAssert(obj.funcReturnDictPassed, @"testBoxingObjPassed");
XCTAssert(obj.funcReturnBlockPassed, @"funcReturnBlockPassed");
XCTAssert(obj.funcReturnObjectBlockPassed, @"funcReturnObjectBlockPassed");
XCTAssert(obj.funcReturnObjectBlockReturnValuePassed, @"funcReturnObjectBlockReturnValuePassed");
XCTAssert(obj.funcReturnJSBlockPassed, @"funcReturnBlockPassed");
XCTAssert(obj.callBlockWithStringAndIntPassed, @"callBlockWithStringAndIntPassed");
XCTAssert(obj.callBlockWithStringAndIntReturnValuePassed, @"callBlockWithStringAndIntReturnValuePassed");
XCTAssert(obj.callBlockWithArrayAndViewPassed, @"callBlockWithArrayAndViewPassed");
XCTAssert(obj.callBlockWithBoolAndBlockPassed, @"callBlockWithBoolAndBlockPassed");
XCTAssert(obj.callBlockWithObjectAndBlockPassed, @"callBlockWithObjectAndBlockPassed");
XCTAssert(obj.callBlockWithObjectAndBlockReturnValuePassed, @"callBlockWithObjectAndBlockReturnValuePassed");
XCTAssert(obj.callBlockWithDoubleAndReturnDoublePassed, @"callBlockWithDoubleAndReturnDoublePassed");
XCTAssert(obj.funcToSwizzleWithStringViewIntPassed, @"funcToSwizzleWithStringViewIntPassed");
XCTAssert(obj.funcToSwizzleViewPassed, @"funcToSwizzleViewPassed");
XCTAssert(obj.funcToSwizzleViewCalledOriginalPassed, @"funcToSwizzleViewCalledOriginalPassed");
XCTAssert(obj.funcToSwizzleReturnViewPassed, @"funcToSwizzleReturnViewPassed");
XCTAssert(obj.funcToSwizzleParamNilPassed, @"funcToSwizzleParamNilPassed");
XCTAssert(obj.funcToSwizzleReturnIntPassed, @"funcToSwizzleReturnIntPassed");
XCTAssert(obj.funcToSwizzleWithBlockPassed, @"funcToSwizzleWithBlockPassed");
XCTAssert(obj.funcToSwizzle_withUnderLine_Passed, @"funcToSwizzle_withUnderLine_Passed");
XCTAssert(obj.funcToSwizzleReturnRectPassed, @"funcToSwizzleReturnRectPassed");
XCTAssert(obj.funcToSwizzleReturnPointPassed, @"funcToSwizzleReturnPointPassed");
XCTAssert(obj.funcToSwizzleReturnSizePassed, @"funcToSwizzleReturnSizePassed");
XCTAssert(obj.funcToSwizzleReturnRangePassed, @"funcToSwizzleReturnRangePassed");
XCTAssert(obj.funcToSwizzleReturnEdgeInsetsPassed, @"funcToSwizzleReturnEdgeInsetsPassed");
XCTAssert(obj.funcToSwizzleReturnRectJSPassed, @"funcToSwizzleReturnRectJSPassed");
XCTAssert(obj.funcToSwizzleReturnPointJSPassed, @"funcToSwizzleReturnPointJSPassed");
XCTAssert(obj.funcToSwizzleReturnSizeJSPassed, @"funcToSwizzleReturnSizeJSPassed");
XCTAssert(obj.funcToSwizzleReturnRangeJSPassed, @"funcToSwizzleReturnRangeJSPassed");
XCTAssert(obj.funcToSwizzleReturnEdgeInsetsJSPassed, @"funcToSwizzleReturnEdgeInsetsJSPassed");
XCTAssert(obj.funcToSwizzleTestClassPassed, @"funcToSwizzleTestClassPassed");
XCTAssert(obj.funcToSwizzleTestSelectorPassed, @"funcToSwizzleTestSelectorPassed");
XCTAssert(obj.funcToSwizzleTestCharPassed, @"funcToSwizzleTestCharPassed");
XCTAssert(obj.funcToSwizzleTestClassPassed,@"funcToSwizzleTestClassPassed");
XCTAssert(obj.funcTestCharPassed, @"funcTestCharPassed");
XCTAssert(obj.funcToSwizzleTestPointerPassed, @"funcToSwizzleTestPointerPassed");
XCTAssert(obj.funcTestPointerPassed, @"funcTestPointerPassed");
XCTAssert(obj.funcTestSizeofPassed,@"funcSizeofPassed");
XCTAssert(obj.funcTestGetPointerPassed, @"funcGetPointerPassed");
XCTAssert(obj.funcTestNSErrorPointerPassed, @"funcTestNSErrorPointerPassed");
XCTAssert(obj.funcTestNilParametersInBlockPassed, @"funcTestNilParametersInBlockPassed");
NSDictionary *originalDict = @{@"k": @"v"};
NSDictionary *dict = [obj funcToSwizzleReturnDictionary:originalDict];
XCTAssert(originalDict == dict, @"funcToSwizzleReturnDictionary");
dict = [obj funcToSwizzleReturnJSDictionary];
XCTAssertEqualObjects(dict[@"str"], @"js_string", @"funcToSwizzleReturnJSDictionary");
NSArray *originalArr = @[@"js", @"patch"];
NSArray *arr = [obj funcToSwizzleReturnArray:originalArr];
XCTAssert(originalArr == arr, @"funcToSwizzleReturnArray");
NSString *originalStr = @"JSPatch";
NSString *str = [obj funcToSwizzleReturnString:originalStr];
XCTAssert(originalStr == str, @"funcToSwizzleReturnString");
XCTAssert(obj.classFuncToSwizzlePassed, @"classFuncToSwizzlePassed");
XCTAssert(obj.classFuncToSwizzleReturnObjPassed, @"classFuncToSwizzleReturnObjPassed");
XCTAssert(obj.classFuncToSwizzleReturnObjCalledOriginalPassed, @"classFuncToSwizzleReturnObjCalledOriginalPassed");
XCTAssert(obj.classFuncToSwizzleReturnIntPassed, @"classFuncToSwizzleReturnIntPassed");
// Test for functions which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0
// This case shall fail if you comment line 1050~1052 in JPEngine.m on iOS7.0.
XCTAssert(obj.classFuncToSwizzleReturnDoublePassed, @"classFuncToSwizzleReturnDoublePassed");
XCTAssert(subObj.funcCallSuperSubObjectPassed, @"funcCallSuperSubObjectPassed");
XCTAssert(subObj.funcCallSuperPassed, @"funcCallSuperPassed");
XCTAssert(obj.callForwardInvocationPassed, @"callForwardInvocationPassed");
JPTestSwizzledForwardInvocationSubObject *tmp = [[JPTestSwizzledForwardInvocationSubObject alloc] init];
[tmp callTestSwizzledSuperForwardInvocation];
XCTAssert(!tmp.callSwizzledSuperForwardInvocationPassed);
[tmp swizzleSuperForwoardInvocation];
[tmp callTestSwizzledSuperForwardInvocation];
XCTAssert(tmp.callSwizzledSuperForwardInvocationPassed);
XCTAssert(obj.propertySetFramePassed, @"propertySetFramePassed");
XCTAssert(obj.propertySetViewPassed, @"propertySetViewPassed");
XCTAssert(obj.newTestObjectReturnViewPassed, @"newTestObjectReturnViewPassed");
XCTAssert(obj.newTestObjectReturnBoolPassed, @"newTestObjectReturnBoolPassed");
XCTAssert(obj.mutableArrayPassed, @"mutableArrayPassed");
XCTAssert(obj.mutableDictionaryPassed, @"mutableDictionaryPassed");
XCTAssert(obj.mutableStringPassed, @"mutableStringPassed");
XCTAssert(obj.funcWithTransformPassed, @"funcWithTransformPassed");
XCTAssert(obj.transformTranslatePassed, @"funcWithTransformPassed");
XCTAssert(obj.funcWithRectPointerPassed, @"funcWithRectPointerPassed");
XCTAssert(obj.funcWithTransformPointerPassed, @"funcWithTransformPointerPassed");
XCTAssertEqualObjects(@"overrided",[subObj funcOverrideParentMethod]);
XCTAssert(obj.variableParameterMethodPassed, @"variableParameterMethodPassed");
JPTestProtocolObject *testProtocolObj = [[JPTestProtocolObject alloc] init];
XCTAssert([testProtocolObj testProtocolMethods], @"testProtocolMethodsPassed");
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[obj funcToSwizzleTestGCD:^{
XCTAssert(obj.funcToSwizzleTestGCDPassed, @"funcToSwizzleTestGCDPassed");
dispatch_semaphore_signal(semaphore);
}];
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
- (void)testJSClass
{
[self loadPatch:@"jsClassTest"];
XCTAssert([JPJSClassTest isPassA]);
XCTAssert([JPJSClassTest isPassB]);
XCTAssert([JPJSClassTest isPassC]);
}
- (void)testSuperClass
{
[self loadPatch:@"superTest"];
XCTAssert([JPSuperTestResult isPassA]);
XCTAssert([JPSuperTestResult isPassB]);
XCTAssert([JPSuperTestResult isPassC]);
}
- (void)testInheritance
{
/*get values before patch*/
id t1objB = [[JPInheritTest01ObjectB alloc] init];
NSString* t1m1Return = [t1objB m1];
NSString* t1m2Return = [t1objB m2];
id t2objA = [[JPInheritTest02ObjectA alloc] init];
id t2objB = [[JPInheritTest02ObjectB alloc] init];
id t2objC = [[JPInheritTest02ObjectC alloc] init];
NSString* t2m1Return = [t2objA m1];
NSString* t2m2Return = [t2objA m2];
NSString* t2Bm1Return = [t2objB m1];
NSString* t2Bm2Return = [t2objB m2];
NSString* t2Cm1Return = [t2objC m1];
NSString* t2Cm2Return = [t2objC m2];
id t3objA = [[JPInheritTest03ObjectA alloc] init];
id t3objB = [[JPInheritTest03ObjectB alloc] init];
id t3objC = [[JPInheritTest03ObjectC alloc] init];
NSString* t3m1Return = [t3objA m1];
NSString* t3m2Return = [t3objA m2];
NSString* t3Bm1Return = [t3objB m1];
NSString* t3Bm2Return = [t3objB m2];
NSString* t3Cm1Return = [t3objC m1];
NSString* t3Cm2Return = [t3objC m2];
[self loadPatch:@"inheritTest"];
/*Test 1*/
XCTAssertNotEqualObjects(t1m1Return, [t1objB m1]);
XCTAssertEqualObjects(@"JP_01ObjB_m1", [t1objB m1]);
XCTAssertEqualObjects(t1m2Return,[t1objB m2]);
/*Test 2*/
XCTAssertEqualObjects(t2m1Return,[t2objA m1]);
XCTAssertEqualObjects(t2m2Return,[t2objA m2]);
XCTAssertNotEqualObjects(t2Bm1Return,[t2objB m1]);
XCTAssertEqualObjects(@"JP_02ObjB_m1",[t2objB m1]);
XCTAssertEqualObjects(t2Bm2Return,[t2objB m2]);
XCTAssertNotEqualObjects(t2Cm1Return,[t2objC m1]);
XCTAssertEqualObjects(@"JP_02ObjB_m1",[t2objC m1]);
XCTAssertNotEqualObjects(t2Cm2Return,[t2objC m2]);
XCTAssertEqualObjects(@"JP_02ObjC_m2",[t2objC m2]);
XCTAssertEqualObjects(@"JP_02ObjC_m3", [t2objC m3]);
/*Test 3*/
XCTAssertEqualObjects(t3m1Return,[t3objA m1]);
XCTAssertEqualObjects(t3m2Return,[t3objA m2]);
XCTAssertNotEqualObjects(t3Bm1Return,[t3objB m1]);
XCTAssertEqualObjects(@"JP_03ObjB_m1",[t3objB m1]);
XCTAssertEqualObjects(t3Bm2Return,[t3objB m2]);
XCTAssertEqualObjects(t3Cm1Return,[t3objC m1]);
XCTAssertNotEqualObjects(t3Cm2Return,[t3objC m2]);
XCTAssertEqualObjects(@"JP_03ObjC_m2",[t3objC m2]);
}
- (void)testCFunction
{
[self loadPatch:@"jsCFunctionTest"];
XCTAssert([JPCFunctionTest testCfuncWithCGSize], @"testCfuncWithCGSize");
XCTAssert([JPCFunctionTest testCfuncWithCGRect], @"testCfuncWithCGRect");
XCTAssert([JPCFunctionTest testCfuncWithId], @"testCfuncWithId");
XCTAssert([JPCFunctionTest testCfuncWithInt], @"testCfuncWithInt");
XCTAssert([JPCFunctionTest testCfuncWithCGFloat], @"testCfuncWithCGFloat");
XCTAssert([JPCFunctionTest testCfuncReturnPointer], @"testCfuncReturnPointer");
XCTAssert([JPCFunctionTest testCFunctionReturnClass], @"testCFunctionReturnClass");
XCTAssert([JPCFunctionTest testCFunctionVoid], @"testCFunctionVoid");
}
#pragma mark - jsNumberTest
- (void)testJPNumber {
[self loadPatch:@"jsNumberTest"];
XCTAssert([JPNumberTest testJPNumNSNumber], @"testJPNumNSNumber");
XCTAssert([JPNumberTest testJPNumNSDecimalNumber], @"testJPNumNSDecimalNumber");
XCTAssert([JPNumberTest testJPNumToJS], @"testJPNumToJS");
XCTAssert([JPNumberTest testJPNUmToOC], @"testJPNumToOC");
}
#pragma mark - multithreadTest
dispatch_semaphore_t sem;
int finishcount = 0;
bool success = false;
#define LOOPCOUNT 100
void thread(void* context);
- (void)testDispatchQueue
{
[self loadPatch:@"multithreadTest"];
success = false;
NSMutableArray *objs = [[NSMutableArray alloc] init];
for (int i = 0; i < LOOPCOUNT; i++) {
JPMultithreadTestObject *obj = [[JPMultithreadTestObject alloc] init];
obj.objectId = i;
[objs addObject:obj];
}
dispatch_queue_t q1 = dispatch_queue_create("serial queue", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < LOOPCOUNT; i++) {
dispatch_async_f(q1, (__bridge void*)[objs objectAtIndex:i], thread);
}
sem = dispatch_semaphore_create(0);
dispatch_semaphore_wait(sem,DISPATCH_TIME_FOREVER);
XCTAssertTrue(success,@"serial queue test failed");
success = false;
dispatch_queue_t q2 = dispatch_queue_create("concurrent queue", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < LOOPCOUNT; i++) {
dispatch_async_f(q2, (__bridge void*)[objs objectAtIndex:i], thread);
}
sem = dispatch_semaphore_create(0);
dispatch_semaphore_wait(sem,DISPATCH_TIME_FOREVER);
XCTAssertTrue(success,@"concurrent queue test failed");
}
void thread(void* context)
{
JPMultithreadTestObject *obj = (__bridge JPMultithreadTestObject*)context;
for (int i = 0; i < LOOPCOUNT; i++) {
[obj addValue:[NSNumber numberWithInt:obj.objectId]];
}
finishcount++;
if (![obj checkAllValues]) {
NSLog(@"found wrong data in object %d", obj.objectId);
dispatch_semaphore_signal(sem);
return;
}
if (finishcount == LOOPCOUNT) {
finishcount = 0;
success = true;
dispatch_semaphore_signal(sem);
}
}
#pragma mark - performance
- (void)testJSCallEmptyMethodPerformance
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallOCEmptyMethod];
}];
}
- (void)testJSCallMethodWithParamObjectPerformance
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallOCMethodWithParamObject];
}];
}
- (void)testJSCallMethodReturnObjectPerformance
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallOCMethodReturnObject];
}];
}
- (void)testOCCallJSEmptyMethodPerformance
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testOCCallEmptyMethod];
}];
}
- (void)testOCCallJSMethodWithParamObjectPerformance
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testOCCallMethodWithParamObject];
}];
}
- (void)testOCCallJSMethodReturnObjectPerformance
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testOCCallMethodReturnObject];
}];
}
- (void)testJSCallJSEmptyMethod
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallJSEmptyMethod];
}];
}
- (void)testJSCallJSMethodWithParam
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallJSMethodWithParam];
}];
}
- (void)testJSCallJSMethodWithLargeDictionaryParam
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallJSMethodWithLargeDictionaryParam];
}];
}
- (void)testJSCallJSMethodWithLargeDictionaryParamAutoConvert
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallJSMethodWithLargeDictionaryParamAutoConvert];
}];
}
- (void)testJSCallMallocJPMemory
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallMallocJPMemory];
}];
}
- (void)testJSCallMallocJPCFunction
{
[self loadPatch:@"performanceTest"];
JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];
[self measureBlock:^{
[obj testJSCallMallocJPCFunction];
}];
}
- (void)testNewBlock {
[self loadPatch:@"newBlockTest"];
newBlockTest *obj = [[newBlockTest alloc] init];
[obj removeJPBlock];
[obj testJSBlockToOCCall];
XCTAssert(obj.success, @"testJSBlockToOCCall");
}
- (void)testNewProtocol{
[self loadPatch:@"newProtocolTest"];
//Protocol baseTest
baseTestProtocolObject *baseTest = [baseTestProtocolObject new];
int retBaseTest1 = [baseTest testProtocol:YES];
XCTAssertEqual(retBaseTest1, 1);
[baseTest test2Protocol:2];
[baseTest test3Protocol:NO withB:0.2f withC:3.4f];
NSLog(@"new protocol base test end");
//Protocol structTest
structTestProtocolObject *structTest = [structTestProtocolObject new];
int retStructTest1 = [structTest testProtocol:CGRectZero];
XCTAssertEqual(retStructTest1, 1);
CGPoint retStructTest2 = [structTest test2Protocol:CGSizeZero];
XCTAssertTrue(CGPointEqualToPoint(retStructTest2, CGPointMake(100, 100)));
CGSize retStructTest3 = [structTest test3Protocol:CGRectZero withB:3.1f withC:4];
XCTAssertTrue(CGSizeEqualToSize(retStructTest3, CGSizeMake(100, 100)));
NSLog(@"new protocol struct test end");
//Protocol objectTest
objectTestProtocolObject *objectTest = [objectTestProtocolObject new];
int retObjectTest1 = [objectTest testProtocol:@"teststring"];
XCTAssertEqual(retObjectTest1, 1);
int retObjectTest2 = [objectTest test2Protocol:@"teststring"];
XCTAssertEqual(retObjectTest2, 1);
CGSize retObjectTest3 = [objectTest test3Protocol:@[@1,@2] withB:@"teststring" withC:2];
XCTAssertTrue(CGSizeEqualToSize(retObjectTest3, CGSizeMake(100, 100)));
NSLog(@"new protocol object test end");
//Protocol sepcialTest
specialTestProtocolObject *specialTest = [specialTestProtocolObject new];
[specialTest testProtocol:@selector(viewDidLoad)];
[specialTest test2Protocol:^{
NSLog(@"11");
}];
[specialTest test3Protocol:0.5f withB:^{
NSLog(@"11");
} withC:@selector(viewDidLoad)];
NSLog(@"new protocol special test end");
//Protocol typeEncodeTest
typeEncodeTestProtocolObject *encodeTest = [typeEncodeTestProtocolObject new];
[encodeTest testProtocol:@"teststring"];
NSString* retEncodeTest2 = [encodeTest test2Protocol:@[@1,@2] withB:@"testtest"];
XCTAssertTrue([retEncodeTest2 isEqualToString:@"string"]);
NSLog(@"new protocol encode test end");
//Protocol classTest
int retClassTest1 = [classTestProtocolObject testProtocol:@"teststring"];
XCTAssertEqual(retClassTest1, 1);
int retClassTest2 = [classTestProtocolObject test2Protocol:@"teststring"];
XCTAssertEqual(retClassTest2, 1);
CGSize retClassTest3 = [classTestProtocolObject test3Protocol:@[@1,@2] withB:@"teststring" withC:2];
XCTAssertTrue(CGSizeEqualToSize(retClassTest3, CGSizeMake(100, 100)));
NSLog(@"new protocol object test end");
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/jsCFunctionTest.js
================================================
require('JPEngine').addExtensions(['JPCFunction'])
require('JPEngine').defineStruct({
"name": "CGSize",
"types": "FF",
"keys": ["width", "height"]
});
require('JPEngine').defineStruct({
"name": "CGPoint",
"types": "FF",
"keys": ["x", "y"]
});
require('JPEngine').defineStruct({
"name": "CGRect",
"types": "{CGPoint}{CGSize}",
"keys": ["origin", "size"]
});
defineClass('JPCFunctionTest', {}, {
testCfuncWithCGSize: function() {
defineCFunction("cfuncWithCGSize", "{CGSize}, {CGSize}")
var ret = cfuncWithCGSize({width:1, height:2});
return ret.width == 1 && ret.height == 2;
},
testCfuncWithCGRect: function() {
defineCFunction("cfuncWithCGRect", "{CGRect}, {CGRect}")
var ret = cfuncWithCGRect({origin:{x:1,y:2},size:{width:3, height:4}});
console.log("testCfuncWithCGRect", JSON.stringify(ret), ret.origin, ret.origin.x);
return ret.origin.x == 1 && ret.origin.y == 2 && ret.size.width == 3 && ret.size.height == 4;
},
testCfuncWithId: function() {
defineCFunction("cfuncWithId", "id, NSString *")
var ret = cfuncWithId("JSPatch");
return ret.toJS() == "JSPatch";
},
testCfuncWithInt: function() {
defineCFunction("cfuncWithInt", "int, int")
return cfuncWithInt(42) == 42
},
testCfuncWithCGFloat: function() {
defineCFunction("cfuncWithCGFloat", "CGFloat, CGFloat")
return cfuncWithCGFloat(42.2) - 42.2 < 0.1
},
testCfuncReturnPointer: function() {
defineCFunction("cfuncReturnPointer", "void*")
defineCFunction("cfuncWithPointerIsEqual", "bool, void*")
var ptr = cfuncReturnPointer()
return cfuncWithPointerIsEqual(ptr)
},
testCFunctionReturnClass: function() {
defineCFunction("NSClassFromString", "Class, NSString *")
var viewCls = NSClassFromString("UIView")
var view = require('UIView').alloc().init()
return view.isKindOfClass(viewCls);
},
testCFunctionVoid: function() {
defineCFunction("cfuncVoid", "void")
self.setupCFunctionVoidSucc();
return self.ORIGtestCFunctionVoid();
},
})
================================================
FILE: Demo/iOSDemo/JSPatchTests/jsClassTest.js
================================================
defineClass('JSClsA', ['prop1', 'prop2'], {
init: function(){
self = self.super().init();
self.setProp1('1');
self.setProp2('2');
return self;
},
_privateMethod: function() {
return 'P';
},
method: function() {
return 'A' + self.prop1() + self.prop2();
},
}, {
clsMethod: function() {
return 'A'
},
})
defineClass('JSSuperTestA', {
method: function(){
return 'A'
}
})
defineClass('JSSuperTestA1: JSSuperTestA', {
method: function(){
return self.super().method() + '1'
}
})
defineClass('JSSuperTestA2: JSSuperTestA1', {
method: function(){
return self.super().method() + '2'
}
})
defineJSClass('JSClassA', {
init: function() {
this.prop1 = 'A'
return this
},
method: function() {
return this.prop1
}
}, {
clsMethod: function() {
return '1'
}
})
defineJSClass('JSClassA1: JSClassA', {
method: function() {
return this.super().method() + '1'; //should be 'A1'
}
})
defineJSClass('JSClassA2: JSClassA1', {
method: function() {
return this.super().method() + '2'; //should be 'A12'
}
})
defineClass('JPJSClassTest', {}, {
isPassA: function() {
var o = JSClsA.alloc().init();
return o.method() == 'A12' && o._privateMethod() == 'P' && JSClsA.clsMethod() == 'A';
},
isPassB: function() {
var o = JSSuperTestA2.alloc().init();
return o.method() == 'A12';
},
isPassC: function() {
var o = JSClassA2.alloc().init();
return o.method() == 'A12' && JSClassA.clsMethod() == '1';
}
})
================================================
FILE: Demo/iOSDemo/JSPatchTests/jsNumberTest.js
================================================
require('JPEngine').addExtensions(['JPNumber'])
defineClass('JPNumberTest', {}, {
testJPNumNSNumber: function() {
var oc_n = OCNumber("NSNumber", "numberWithInt:", [233])
return oc_n.compare(233) == 0
},
testJPNumNSDecimalNumber: function() {
var oc_n = OCNumber("NSDecimalNumber", "decimalNumberWithMantissa:exponent:isNegative:", [10, 2, 0])
return oc_n.compare(1000) == 0
},
testJPNumToJS: function() {
var oc_n = OCNumber("NSNumber", "numberWithFloat:", [0.14])
var js_n = toJSNumber(oc_n)
return js_n + 3 - 3.14 < 0.0001
},
testJPNUmToOC: function() {
var oc_n = toOCNumber(2.14)
return oc_n.compare(2.14) == 0
}
})
================================================
FILE: Demo/iOSDemo/JSPatchTests/multithreadTest.js
================================================
var global = this;
(function() {
defineClass('JPMultithreadTestObject', {
addValueJS: function(num) {
self.addValue(num);
},
addValue: function(num) {
self.ORIGaddValue(num);
}
});
})();
================================================
FILE: Demo/iOSDemo/JSPatchTests/newBlockTest.h
================================================
//
// newBlockTest.h
// JSPatchTests
//
// Created by WELCommand on 2018/3/27.
// Copyright © 2018年 bang. All rights reserved.
//
#import
#import
@interface newBlockTest : NSObject
@property (nonatomic, assign) BOOL success;
- (void)removeJPBlock;
- (void)testJSBlockToOCCall;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/newBlockTest.js
================================================
defineClass("newBlockTest", {
testJSBlockToOCCall: function() {
self.performBlock(block("CGFloat, int, CGPoint, double, CGFloat, NSNumber*, NSString*, NSInteger", function(arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
return arg1 + arg2.x + arg2.y + arg3 + arg4 + arg5 + arg6.doubleValue() + arg7;
}));
}
}, {});
================================================
FILE: Demo/iOSDemo/JSPatchTests/newBlockTest.m
================================================
//
// newBlockTest.m
// JSPatchTests
//
// Created by WELCommand on 2018/3/27.
// Copyright © 2018年 bang. All rights reserved.
//
#import "newBlockTest.h"
#import
#import "JPEngine.h"
@implementation newBlockTest
- (void)testJSBlockToOCCall {}
+ (void)main:(JSContext *)context
{
context[@"__genBlock"] = nil;
}
- (void)removeJPBlock {
[JPEngine addExtensions:@[@"newBlockTest"]];
}
- (void)performBlock:(CGFloat (^)(int arg1, CGPoint arg2, double arg3, CGFloat arg4, NSNumber *arg5, NSString *arg6, NSInteger arg7))block {
_success = (block(1, (CGPoint){3.3, 3.3}, 1.1, 1.1, @(11), @"4.4", 17) == (CGFloat)(1 + 3.3 + 3.3 + 1.1 + 1.1 + 11 + 4.4 + 17)) && (block(1, (CGPoint){3.3, 3.3}, 1.1, 1.1, @(11), @"4.4", 17) == (CGFloat)(1 + 3.3 + 3.3 + 1.1 + 1.1 + 11 + 4.4 + 17));
}
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/newProtocolTest.h
================================================
//
// newProrotcolTest.h
// JSPatchDemo
//
// Created by Awhisper on 15/12/27.
// Copyright © 2015年 bang. All rights reserved.
//
#import
#import
@interface baseTestProtocolObject : NSObject
-(int)testProtocol:(BOOL)arg;
-(void)test2Protocol:(NSInteger)arg;
-(void)test3Protocol:(BOOL)arg1 withB:(float)arg2 withC:(CGFloat)arg3;
@end
@interface structTestProtocolObject : NSObject
-(int)testProtocol:(CGRect)arg;
-(CGPoint)test2Protocol:(CGSize)arg;
-(CGSize)test3Protocol:(CGRect)arg1 withB:(float)arg2 withC:(NSInteger)arg3;
@end
@interface objectTestProtocolObject : NSObject
-(int)testProtocol:(NSString*)arg;
-(int)test2Protocol:(NSString*)arg;
-(CGSize)test3Protocol:(NSArray*)arg1 withB:(NSString*)arg2 withC:(NSInteger)arg3;
@end
//typedef void(^name)(void);
@interface specialTestProtocolObject : NSObject
-(void)testProtocol:(SEL)arg;
-(void)test2Protocol:(void(^)(void))arg;
-(void)test3Protocol:(float)arg1 withB:(void(^)(void))arg2 withC:(SEL)arg3;
@end
@interface typeEncodeTestProtocolObject : NSObject
-(void)testProtocol:(id)arg;
-(NSString*)test2Protocol:(NSArray*)arg1 withB:(NSString*)arg2;
@end
@interface classTestProtocolObject : NSObject
+(int)testProtocol:(NSString*)arg;
+(int)test2Protocol:(NSString*)arg;
+(CGSize)test3Protocol:(NSArray*)arg1 withB:(NSString*)arg2 withC:(NSInteger)arg3;
@end
================================================
FILE: Demo/iOSDemo/JSPatchTests/newProtocolTest.js
================================================
defineProtocol("baseTestProtocol",{
//argument type can be bool BOOL int NSInterger float CGFloat ... any base type
//one argument BOOL return int
testProtocol:{
paramsType:"BOOL",
returnType:"int",
},
//one argument NSInterger return void
test2Protocol:{
paramsType:"BOOL",
//returnType:"void",//option no returnType mean void
},
//multiArguments seperated by ","
test3Protocol_withB_withC:{
paramsType:"BOOL , float , CGFloat",
//returnType:"void",//option no returnType mean void
},
})
//with new protocol you can add basetype args method
defineClass('baseTestProtocolObject : NSObject ' , {
testProtocol:function(arg1){
console.log(arg1);
return 1;
},
test2Protocol: function(arg1) {
console.log(arg1);
},
test3Protocol_withB_withC:function(arg1,arg2,arg3){
console.log(arg1);
},
})
defineProtocol("structTestProtocol",{
//argument type can be CGRect CGSize CGPoint ... many systemstruct
//only support system struct
//custom struct see encodeTypeTest
//one argument CGRect return int
testProtocol:{
paramsType:"CGRect",
returnType:"int",
},
//one argument CGSize return CGPoint
test2Protocol:{
paramsType:"CGSize",
returnType:"CGPoint",
},
//multiArguments seperated by "," struct & baseType mix
test3Protocol_withB_withC:{
paramsType:"CGRect , float , NSInteger",
returnType:"CGSize",
},
})
//with new protocol you can add struct type args method
defineClass('structTestProtocolObject : NSObject ' , {
testProtocol:function(arg1){
console.log(arg1);
return 1;
},
test2Protocol: function(arg1) {
console.log(arg1);
var point = {x:100,y:100};
return point;
},
test3Protocol_withB_withC:function(arg1,arg2,arg3){
console.log(arg1);
var size = {width:100,height:100};
return size;
},
})
defineProtocol("objectTestProtocol",{
//argument type can be any NSObject
//one argument NSString , return int
//you can turn NSString to id
testProtocol:{
paramsType:"id",
returnType:"int",
},
//you can use NSString is All ok
test2Protocol:{
paramsType:"NSString",
returnType:"int",
},
//multiArguments seperated by "," object & baseType mix
test3Protocol_withB_withC:{
paramsType:"id , NSString , NSInteger",
returnType:"CGSize",
},
})
//with new protocol you can add mix type args method
defineClass('objectTestProtocolObject : NSObject ' , {
testProtocol:function(arg1){
console.log(arg1);
return 1;
},
test2Protocol: function(arg1) {
console.log(arg1);
return 1;
},
test3Protocol_withB_withC:function(arg1,arg2,arg3){
console.log(arg1);
var size = {width:100,height:100};
return size;
},
})
defineProtocol("specialTestProtocol",{
//argument type can be selector and block
//one argument Selctor must use "SEL"
testProtocol:{
paramsType:"SEL",
//returnType:"int",//option no returnType mean void
},
//one argument bloc must use "block"
test2Protocol:{
paramsType:"block",
// returnType:"CGPoint",//option no returnType mean void
},
//multiArguments seperated by "," struct & baseType mix
test3Protocol_withB_withC:{
paramsType:"CGFloat , block , SEL",
// returnType:"CGSize",//option no returnType mean void
},
})
//with new protocol you can add mix type args method
defineClass('specialTestProtocolObject : NSObject ' , {
testProtocol:function(arg1){
console.log(arg1);
},
test2Protocol: function(arg1) {
console.log(arg1);
arg1();
},
test3Protocol_withB_withC:function(arg1,arg2,arg3){
console.log(arg1);
arg2();
},
})
defineProtocol("encodeTestProtocol",{
//use typeEncode to define complex method
//you can write typeEncode by using runtime
//you can input any string
//makesure the number of args is right
testProtocol:{
paramsType:"unknown",
returnType:"something",
typeEncode:"v12@0:4@8",
},
//you can write typeEncode by yourself
//you can input any string
//makesure the number of args is right
testProtocol_withB:{
paramsType:"idontknown , mygod",
returnType:"wooo",
typeEncode:"@@:@@",
},
//if your paramsType or returnType is complex
//youcan input any string just make sure number is right
//write the whole typeEncode or use runtime to generate typeEncode
})
//with new protocol you can add encodetype method
defineClass('typeEncodeTestProtocolObject : NSObject ' , {
testProtocol:function(arg1){
console.log(arg1);
},
test2Protocol_withB: function(arg1,arg2) {
console.log(arg1);
var ret = "string";
return ret;
},
})
defineProtocol("classTestProtocol",{},{
//argument type can be any NSObject
//one argument NSString , return int
//you can turn NSString to id
testProtocol:{
paramsType:"id",
returnType:"int",
},
//you can use NSString is All ok
test2Protocol:{
paramsType:"NSString",
returnType:"int",
},
//multiArguments seperated by "," object & baseType mix
test3Protocol_withB_withC:{
paramsType:"id , NSString , NSInteger",
returnType:"CGSize",
},
})
//with new protocol you can add class method
defineClass('classTestProtocolObject : NSObject ' ,{}, {
testProtocol:function(arg1){
console.log(arg1);
return 1;
},
test2Protocol: function(arg1) {
console.log(arg1);
return 1;
},
test3Protocol_withB_withC:function(arg1,arg2,arg3){
console.log(arg1);
var size = {width:100,height:100};
return size;
},
})
================================================
FILE: Demo/iOSDemo/JSPatchTests/newProtocolTest.m
================================================
//
// newProrotcolTest.m
// JSPatchDemo
//
// Created by Awhisper on 15/12/27.
// Copyright © 2015年 bang. All rights reserved.
//
#import "newProtocolTest.h"
#import "JPEngine.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wincomplete-implementation"
@implementation baseTestProtocolObject
// no method definition
// no crash means addProtocol success
@end
@implementation structTestProtocolObject
// no method definition
// no crash means addProtocol success
@end
@implementation objectTestProtocolObject
// no method definition
// no crash means addProtocol success
@end
@implementation specialTestProtocolObject
// no method definition
// no crash means addProtocol success
@end
@implementation typeEncodeTestProtocolObject
// no method definition
// no crash means addProtocol success
@end
@implementation classTestProtocolObject
// no method definition
// no crash means addProtocol success
@end
#pragma clang diagnostic pop
================================================
FILE: Demo/iOSDemo/JSPatchTests/performanceTest.js
================================================
var performanceTestObj = require('NSObject').alloc().init();
var largeDict = {
"id": 2619381,
"title": "Seaborn Oyster Co.",
"description": null,
"width": 400,
"height": 300,
"images": {
"hidpi": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg",
"normal": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg",
"teaser": "https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg"
},
"views_count": 2166,
"likes_count": 235,
"comments_count": 2,
"attachments_count": 0,
"rebounds_count": 0,
"buckets_count": 11,
"created_at": "2016-03-29T17:12:41Z",
"updated_at": "2016-03-29T17:12:53Z",
"html_url": "https://dribbble.com/shots/2619381-Seaborn-Oyster-Co",
"attachments_url": "https://api.dribbble.com/v1/shots/2619381/attachments",
"buckets_url": "https://api.dribbble.com/v1/shots/2619381/buckets",
"comments_url": "https://api.dribbble.com/v1/shots/2619381/comments",
"likes_url": "https://api.dribbble.com/v1/shots/2619381/likes",
"projects_url": "https://api.dribbble.com/v1/shots/2619381/projects",
"rebounds_url": "https://api.dribbble.com/v1/shots/2619381/rebounds",
"animated": false,
"tags": [
"charleston",
"company",
"ocean",
"oyster",
"sea",
"wave"
],
"user": {
"id": 52758,
"name": "Jay Fletcher",
"username": "jfletcherdesign",
"html_url": "https://dribbble.com/jfletcherdesign",
"avatar_url": "https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283",
"bio": "",
"location": "Charleston, SC",
"links": {
"web": "http://www.jfletcherdesign.com",
"twitter": "https://twitter.com/jfletcherdesign"
},
"buckets_count": 0,
"comments_received_count": 5239,
"followers_count": 13803,
"followings_count": 558,
"likes_count": 6531,
"likes_received_count": 104895,
"projects_count": 10,
"rebounds_received_count": 325,
"shots_count": 481,
"teams_count": 0,
"can_upload_shot": true,
"type": "Player",
"pro": true,
"buckets_url": "https://api.dribbble.com/v1/users/52758/buckets",
"followers_url": "https://api.dribbble.com/v1/users/52758/followers",
"following_url": "https://api.dribbble.com/v1/users/52758/following",
"likes_url": "https://api.dribbble.com/v1/users/52758/likes",
"projects_url": "https://api.dribbble.com/v1/users/52758/projects",
"shots_url": "https://api.dribbble.com/v1/users/52758/shots",
"teams_url": "https://api.dribbble.com/v1/users/52758/teams",
"created_at": "2011-08-13T23:30:38Z",
"updated_at": "2016-03-29T17:12:53Z"
},
"team": null
};
defineClass('JPPerformanceTest', {
testJSCallOCEmptyMethod: function() {
var slf = self
for (var i = 0; i < 10000; i ++) {
slf.emptyMethod();
}
},
testJSCallOCMethodWithParamObject: function() {
var slf = self
for (var i = 0; i < 10000; i ++) {
slf.methodWithParamObject(performanceTestObj);
}
},
testJSCallOCMethodReturnObject: function() {
var slf = self
for (var i = 0; i < 10000; i ++) {
slf.methodReturnObject();
}
},
testJSCallJSEmptyMethod: function() {
var slf = self
for (var i = 0; i < 10000; i ++) {
slf.newJSEmptyMethod();
}
},
testJSCallJSMethodWithParam: function() {
var slf = self
for (var i = 0; i < 10000; i ++) {
slf.newJSMethodWithParam(performanceTestObj);
}
},
testJSCallJSMethodWithLargeDictionaryParam: function() {
var slf = self
for (var i = 0; i < 1000; i ++) {
slf.newJSMethodWithLargeDictionaryParam(largeDict);
}
},
testJSCallJSMethodWithLargeDictionaryParamAutoConvert: function() {
var slf = self
autoConvertOCType(1);
for (var i = 0; i < 1000; i ++) {
slf.newJSMethodWithLargeDictionaryParam(largeDict);
}
autoConvertOCType(0);
},
emptyMethodToOverride: function() {
},
methodWithParamObjectToOverride: function(obj) {
},
methodReturnObjectToOverride: function() {
return performanceTestObj;
},
newJSEmptyMethod: function() {
},
newJSMethodWithParam: function(param) {
},
newJSMethodWithLargeDictionaryParam: function(dict) {
},
testJSCallMallocJPMemory: function() {
require('JPEngine').addExtensions(['JPMemory'])
for (var i = 0; i < 100000; i ++) {
var p = malloc(10)
}
},
testJSCallMallocJPCFunction: function() {
require('JPEngine').addExtensions(['JPCFunction'])
for (var i = 0; i < 100000; i ++) {
defineCFunction("malloc", "void *, size_t")
var p = malloc(10)
}
}
})
================================================
FILE: Demo/iOSDemo/JSPatchTests/protocolTest.js
================================================
var global = this;
(function() {
defineClass("JPTestProtocolObject : NSObject ", {
protocolWithDouble_dict: function(num, dict) {
if (dict.objectForKey("name").toJS() == "JSPatch" && num - 4.2 < 0.001) {
return num
}
return 0
},
protocolWithInt: function(num) {
return num
}
}, {
classProtocolWithString_int: function(str, num) {
if (num == 42) return str
return null
}
})
})();
================================================
FILE: Demo/iOSDemo/JSPatchTests/superTest.js
================================================
defineClass('JPJSSuperTestA1 : JPSuperTestA', {
method: function() {
var str = self.super().method().toJS();
return str + '1';
}
})
defineClass('JPJSSuperTestA2 : JPJSSuperTestA1', {
method: function() {
var str = self.super().method();
return str + '2';
}
})
defineClass('JPJSSuperTestB2 : JPSuperTestB1', {
method: function() {
var str = self.super().method().toJS();
return str + '2';
}
})
defineClass('JPJSSuperTestB3 : JPJSSuperTestB2', {
method: function() {
var str = self.super().method();
return str + '3';
}
})
defineClass('JPSuperTestC1', {
method: function() {
var ret = self.ORIGmethod().toJS(); //should be C1
console.log("ttttt: " + ret + self.super().method().toJS())
return ret + self.super().method().toJS(); //should be C1C
}
})
defineClass('JPSuperTestResult', {}, {
isPassA: function() {
var o = JPJSSuperTestA2.alloc().init();
return o.method() == 'A12';
},
isPassB: function (){
var o2 = JPJSSuperTestB2.alloc().init();
var o3 = JPJSSuperTestB3.alloc().init();
return o2.method() == 'B12' && o3.method() == 'B123';
}
})
================================================
FILE: Demo/iOSDemo/JSPatchTests/test.js
================================================
include('protocolTest.js')
include('newProtocolTest.js')
var global = this;
require('JPEngine').defineStruct({
"name": "UIEdgeInsets",
"types": "FFFF",
"keys": ["top", "left", "bottom", "right"]
});
(function() {
defineClass("JPTestObject", {
funcToSwizzle_view: function(num, view) {
self.ORIGfuncToSwizzle_view(num, view)
self.setFuncToSwizzleViewPassed(view && 4.2 - num < 0.01)
},
funcToSwizzleWithString_view_int: function(str, view, i) {
self.setFuncToSwizzleWithStringViewIntPassed(str.toJS() == "stringFromOC" && view && i == 42)
},
funcToSwizzleReturnView: function(view) {
return view
},
funcToSwizzleReturnInt: function(num) {
return num
},
funcToSwizzleReturnDictionary: function(dict) {
return dict
},
funcToSwizzleReturnJSDictionary: function() {
return {"str" : "js_string"};
},
funcToSwizzleReturnArray: function(arr) {
return arr
},
funcToSwizzleReturnString: function(str) {
return str
},
funcToSwizzleWithBlock: function(blk) {
blk(UIView.alloc().init(), 42)
},
funcToSwizzle__withUnderLine__: function(num) {
self.setFuncToSwizzle__withUnderLine__Passed(num == 42)
},
funcOverrideParentMethod:function(){
return "overrided";
},
funcToSwizzleReturnRect: function(rect) {
self.setFuncToSwizzleReturnRectJSPassed(rect.width == 100)
return rect;
},
funcToSwizzleReturnSize: function(size) {
self.setFuncToSwizzleReturnSizeJSPassed(size.width == 42)
return size;
},
funcToSwizzleReturnPoint: function(point) {
self.setFuncToSwizzleReturnPointJSPassed(point.x == 42)
return point;
},
funcToSwizzleReturnRange: function(range) {
self.setFuncToSwizzleReturnRangeJSPassed(range.length == 42)
return range;
},
funcToSwizzleReturnEdgeInsets: function(edge) {
self.setFuncToSwizzleReturnEdgeInsetsJSPassed(edge.top == 42)
return edge;
},
funcToSwizzleTestGCD: function(completeBlock) {
var execCount = 0
var slf = self
var dispatchExecBlock = function() {
if (++execCount >= 4) {
slf.setFuncToSwizzleTestGCDPassed(1)
completeBlock()
}
}
dispatch_async_main(dispatchExecBlock);
dispatch_async_global_queue(dispatchExecBlock);
dispatch_sync_main(dispatchExecBlock);
dispatch_after(1, dispatchExecBlock);
},
funcToSwizzleTestClass: function(cls) {
return cls
},
funcToSwizzleTestSelector: function(sel) {
return sel
},
funcToSwizzleTestChar: function(cStr) {
return cStr
},
funcToSwizzleTestPointer: function(pointer) {
return pointer
},
funcToSwizzleReturnClass:function(){
return require('JPTestObject').class()
}
},
{
classFuncToSwizzle_int: function(o, num) {
o.setClassFuncToSwizzlePassed(num == 10)
},
classFuncToSwizzleReturnObj: function(o) {
self.ORIGclassFuncToSwizzleReturnObj(o)
return o
},
classFuncToSwizzleReturnInt: function(i) {
return i
},
///////Test for function which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0
classFuncToSwizzleReturnDouble: function(d) {
return d
}
})
defineClass("JPTestSwizzledForwardInvocationSubObject",{
stubMethod: function() {}
})
var JPTestObject = require("JPTestObject")
var UIView = require("UIView")
var obj = JPTestObject.alloc().init()
global.ocObj = obj.__obj;
////////Swizzle
obj.callSwizzleMethod()
var cls = obj.funcToSwizzleTestClass(JPTestObject.class())
obj.setFuncToSwizzleTestClassPassed(obj.isKindOfClass(cls))
obj.funcTestChar(obj.funcReturnChar())
var pointer = obj.funcReturnPointer()
////////Base
obj.funcReturnVoid();
var testReturnString = obj.funcReturnString().toJS();
obj.setFuncReturnStringPassed(testReturnString == "stringFromOC")
////////Test Class function call
testReturnString = obj.funcReturnClass().classFunCallReturnString().toJS();
testReturnString2 = obj.funcToSwizzleReturnClass().classFunCallReturnString().toJS();
obj.setFuncReturnClassPassed(testReturnString == "classFunCallReturnString" && testReturnString2 == "classFunCallReturnString")
////////Test Parameter Class return String
var instanceString = obj.funcWithClassAndReturnString(JPTestObject.class()).toJS()
var instanceString2 = obj.funcWithClassAndReturnString(obj.funcToSwizzleReturnClass()).toJS()
var instanceString3 = obj.funcWithClassAndReturnString(obj.funcReturnClass()).toJS()
var instanceString4 = obj.funcWithClassAndReturnString(require('JPTestObject')).toJS()
obj.setFuncWithClassAndReturnStringPassed(
instanceString == "JPTestObject" &&
instanceString2 == "JPTestObject" &&
instanceString3 == "JPTestObject" &&
instanceString4 == "JPTestObject"
)
///////Test for functions which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0
var testReturnDouble = obj.funcReturnDouble()
console.log(testReturnDouble == 100)
obj.setFuncReturnDoublePassed(testReturnDouble == 100)
obj.funcWithInt(42);
obj.funcWithDict_andDouble({test: "test"}, 4.2)
//////nil / NSNull
obj.funcWithNil_dict_str_num(null, {k: "JSPatch"}, "JSPatch", 4.2)
obj.funcWithNull(nsnull)
var o = obj.funcReturnNil()
obj.funcWithNil(o)
obj.setFuncReturnNilPassed(!o)
o.callAnyMethod().willNotCrash()
var bTrue = obj.funcTestBool(true)
var bFalse = obj.funcTestBool(false)
var bFalseNum = obj.funcTestBool(0)
obj.setFuncTestBoolPassed(bTrue && !bFalse && !bFalseNum)
var num0 = obj.funcTestNSNumber(0)
var num1 = obj.funcTestNSNumber(1)
obj.setFuncTestNSNumberPassed(num0 === 0 && num1 === 1)
///////UIView/NSObject
var view = obj.funcReturnViewWithFrame({
x: 0,
y: 0,
width: 100,
height: 100
});
var viewFrame = view.frame()
obj.setFuncReturnViewWithFramePassed(viewFrame.width == 100 && viewFrame.height == 100)
var newView = UIView.alloc().initWithFrame({
x: 10,
y: 10,
width: 20,
height: 20
})
var returnedView = obj.funcWithViewAndReturnView(newView);
var returnedViewFrame = returnedView.frame()
obj.setFuncWithViewAndReturnViewPassed(returnedViewFrame.width == 20 && returnedViewFrame.x == 10)
//////CGRect/CGPoint/CGSize/NSRange
var rect = obj.funcWithRectAndReturnRect({
x: 10,
y: 10,
width: 4.2,
height: 4.2
});
obj.setFuncWithRectAndReturnRectPassed(rect.x == 10 && rect.y == 10 && rect.width - 4.2 < 0.01 && rect.height - 4.2 < 0.01)
var point = obj.funcWithPointAndReturnPoint({
x: 10,
y: 10
});
obj.setFuncWithPointAndReturnPointPassed(point.x == 10 && point.y == 10)
var size = obj.funcWithSizeAndReturnSize({
width: 10,
height: 10
});
obj.setFuncWithSizeAndReturnSizePassed(size.width == 10 && size.height == 10)
var range = obj.funcWithRangeAndReturnRange({
location: 0,
length: 100
});
obj.setFuncWithRangeAndReturnRangePassed(range.location == 0 && range.length == 100)
/////Dictionary/Array
var dict = obj.funcReturnDictStringInt().toJS()
obj.setFuncReturnDictStringIntPassed(dict["str"] == "stringFromOC" && dict["num"] == 42)
var dict = obj.funcReturnDictStringView().toJS();
var dictViewFrame = dict["view"].frame()
obj.setFuncReturnDictStringViewPassed(dict.str == "stringFromOC" && dictViewFrame.width == 100)
var arr = obj.funcReturnArrayControllerViewString().toJS()
obj.setFuncReturnArrayControllerViewStringPassed(arr[0] && arr[1] && arr[2] == "stringFromOC")
var dict = obj.funcReturnDict({name: "JSPatch"}).toJS()
obj.setFuncReturnDictPassed(dict.name == "JSPatch")
//////property
var view = UIView.alloc().init();
view.setFrame({
x: 10,
y: 10,
width: 100,
height: 100
})
obj.setPropertySetFramePassed(view.frame().width == 100 && view.bounds().height == 100)
obj.testView = view
obj.setPropertySetViewPassed(obj.testView.frame().x == 10)
/////Block
require('JPEngine').addExtensions(['JPBlock']);
var blk = obj.funcReturnBlock();
blk("stringFromJS", 42);
var blk = obj.funcReturnObjectBlock();
var view = UIView.alloc().initWithFrame({
x: 10,
y: 10,
width: 100,
height: 100
})
var blkRet = blk({
str: "stringFromJS",
view: view
}, view)
obj.setFuncReturnObjectBlockReturnValuePassed(blkRet.toJS() == "succ")
var jsBlkRet = obj.funcReturnJSBlock(block("id, NSString *, int", function(str, num) {
obj.setFuncReturnJSBlockPassed(str.toJS() == 'stringFromJS' && num == 42)
}))
jsBlkRet('stringFromJS', 42);
obj.callBlockWithStringAndInt(block("id, NSString *, int", function(str, num) {
obj.setCallBlockWithStringAndIntPassed(str.toJS() == "stringFromOC" && num == 42)
return "succ"
}))
obj.callBlockDelay(block("id, NSString *, int", function(str, num) {
obj.setCallBlockWithStringAndIntPassed(str.toJS() == "stringFromOC" && num == 42)
return "succ"
}))
// request big memory to trigger JSContext gc
// make sure the above argument function(str, num) not freed before calling.
require('JPEngine').addExtensions(['JPCFunction'])
for (var i = 0; i < 100000; i ++) {
defineCFunction("malloc", "void *, size_t")
var p = malloc(10)
}
obj.callBlockWithArrayAndView(block("id, NSArray *, UIView *", function(arr, view) {
var viewFrame = view.frame()
arr = arr.toJS()
obj.setCallBlockWithArrayAndViewPassed(arr[0] == "stringFromOC" && arr[1] && viewFrame.width == 100)
}))
obj.callBlockWithBoolAndBlock(block("id, BOOL, NSBlock *", function(b, blk) {
blk("stringFromJS", b ? 42 : 0);
}))
obj.callBlockWithObjectAndBlock(block("id, UIView *, NSBlock *", function(view, blk) {
var viewFrame = view.frame()
var ret = blk((viewFrame.width == 100 ? {
"str": "stringFromJS",
"view": view
}: {}), view)
obj.setCallBlockWithObjectAndBlockReturnValuePassed(ret.toJS() == "succ")
}))
obj.callBlockWithDouble(block("double, double", function(num) {
return num + 4.2;
}));
//////super
var subObj = require("JPTestSubObject").alloc().init()
global.subObj = subObj.__obj;
subObj.super().funcCallSuper()
//////forwardInvocation
obj.callTestForward()
//////new class
var JPNewTestObject = defineClass("JPNewTestObject", {
funcReturnView: function(x) {
var view = UIView.alloc().initWithFrame({
x: x,
y: 10,
width: 20,
height: 20
})
return view
}
},
{
funcReturnBool: function(view, num) {
return view && num == 42
}
})
var newTestObj = JPNewTestObject.alloc().init()
var view = newTestObj.funcReturnView(42)
obj.setNewTestObjectReturnViewPassed(view.frame().x == 42)
obj.setNewTestObjectReturnBoolPassed(JPNewTestObject.funcReturnBool(view, 42))
//mutable
var arr = require('NSMutableArray').alloc().init()
arr.addObject("ctn")
obj.setMutableArrayPassed(arr.objectAtIndex(0).toJS() == "ctn")
var dict = require('NSMutableDictionary').alloc().init()
dict.setObject_forKey("ctn", "k")
obj.setMutableDictionaryPassed(dict.objectForKey("k").toJS() == "ctn")
var str = require('NSMutableString').alloc().init()
str.appendString("JS")
str.appendString("Patch")
obj.setMutableStringPassed(str.toJS() == "JSPatch")
var arr = []
arr.push(obj.getString(), obj.getDictionary(), obj.getArray())
obj.funcTestBoxingObj(arr)
obj.setConsoleLogPassed(console.log != undefined)
//extension
var transform = obj.funcWithTransform({tx: 100, ty: 100, a: 1, b: 0, c: 0, d: 1})
obj.setFuncWithTransformPassed(transform.tx == 100 && transform.ty == 100 && transform.a == 1)
var translated = CGAffineTransformTranslate(transform, 10, 10);
obj.setTransformTranslatePassed(translated.tx == 110 && translated.ty == 110)
obj.funcTestPointer(pointer)
free(pointer)
//sizeof
var rectSize = sizeof("CGRect")
var pointSize = sizeof("CGPoint")
var sizeSize = sizeof("CGSize")
var vectorSize = sizeof("CGVector")
var edgeInsetsSize = sizeof("UIEdgeInsets")
var transformSize = sizeof("CGAffineTransform")
var rangeSize = sizeof("NSRange")
obj.setFuncTestSizeofPassed(rectSize > 0 && pointSize > 0 && sizeSize > 0 && vectorSize > 0 && edgeInsetsSize > 0 && transformSize > 0 && rangeSize > 0)
//getPointerTest1 - Test Object in JPBoxing
var sig = require('JPTestObject').instanceMethodSignatureForSelector("funcTestGetPointer1:");
var invocation = require('NSInvocation').invocationWithMethodSignature(sig)
var str = require('NSString').stringWithString('JSPatch')
invocation.setTarget(obj)
invocation.setSelector("funcTestGetPointer1:")
invocation.setArgument_atIndex(getPointer(str), 2)
invocation.invoke()
var ret1 = malloc(1)
invocation.getReturnValue(ret1)
var bool1 = pvalBool(ret1)
//getPointerTest2 - Test Normal Object
var sig = require('JPTestObject').instanceMethodSignatureForSelector("funcTestGetPointer2:");
var invocation = require('NSInvocation').invocationWithMethodSignature(sig)
var err = require('NSError').errorWithDomain_code_userInfo("com.albert43",45,{msg:"test"});
invocation.setTarget(obj)
invocation.setSelector("funcTestGetPointer2:")
invocation.setArgument_atIndex(getPointer(err), 2)
invocation.invoke()
var ret2 = malloc(1)
invocation.getReturnValue(ret2);
var bool2 = pvalBool(ret2)
//getPointerTest3 - Test Pointer
var ptr = malloc(10)
memset(ptr, 65, 10)
var sig = require('JPTestObject').instanceMethodSignatureForSelector("funcTestGetPointer3:");
var invocation = require('NSInvocation').invocationWithMethodSignature(sig)
invocation.setTarget(obj)
invocation.setSelector("funcTestGetPointer3:")
invocation.setArgument_atIndex(getPointer(ptr), 2)
invocation.invoke()
var ret3 = malloc(1)
invocation.getReturnValue(ret3);
var bool3 = pvalBool(ret3)
obj.setFuncTestGetPointerPassed(bool1 && bool2 && bool3)
free(ret1)
free(ret2)
free(ret3)
free(ptr)
//funcTestNSErrorPointer
var p_error = malloc(8)
obj.funcTestNSErrorPointer(p_error)
var error = pval(p_error)
if (!error) {
obj.setFuncTestNSErrorPointerPassed(false)
} else {
var code = error.code()
obj.setFuncTestNSErrorPointerPassed(code==43)
}
releaseTmpObj(p_error)
free(p_error)
//funcTestNilParametersInBlock
var blk = obj.funcGenerateBlock()
var str1 = blk(obj.funcReturnNil())
var str2 = blk(null)
var str3 = obj.excuteBlockWithNilParameters(block("NSError *", blk))
if (str1.toJS() == "no error" && str2.toJS() == "no error" && str3.toJS() == "no error") {
obj.setFuncTestNilParametersInBlockPassed(true)
}
//newStruct
var pRect = newStruct('CGRect', {x:0, y:0, width:100, height:100});
obj.funcWithRectPointer(pRect);
var rect = pvalStruct('CGRect', pRect);
obj.setFuncWithRectPointerPassed(obj.funcWithRectPointerPassed() && rect.x == 42)
free(pRect);
var pTransform = newStruct('CGAffineTransform', {tx:0, ty:0, a:100, b:100, c:0, d:0});
obj.funcWithTransformPointer(pTransform);
var transform = pvalStruct('CGAffineTransform', pTransform);
obj.setFuncWithTransformPointerPassed(obj.funcWithTransformPointerPassed() && transform.tx == 42)
free(pTransform);
//variable parameter method
var strWithFormat = require('NSString').stringWithFormat("%@ %@", "a", "b");
obj.setVariableParameterMethodPassed(strWithFormat.toJS() == "a b");
})();
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/AppDelegate.h
================================================
//
// AppDelegate.h
// JSPatchPlayground
//
// Created by bang on 5/14/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
@interface AppDelegate : UIResponder
@property (strong, nonatomic) UIWindow *window;
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/AppDelegate.m
================================================
//
// AppDelegate.m
// JSPatchPlayground
//
// Created by bang on 5/14/16.
// Copyright © 2016 bang. All rights reserved.
//
#import "AppDelegate.h"
#import "JPRootViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
JPRootViewController *rootViewController = [[JPRootViewController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// 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.
// 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.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 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.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// 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.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// 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.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/Brand Assets.launchimage/Contents.json
================================================
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"minimum-system-version" : "7.0",
"subtype" : "retina4",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/LaunchImage.launchimage/Contents.json
================================================
{
"images" : [
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "Default-576@2x.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "736h",
"filename" : "Default-736@3x.png",
"minimum-system-version" : "8.0",
"orientation" : "landscape",
"scale" : "3x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "667h",
"filename" : "Default-667@2x.png",
"minimum-system-version" : "8.0",
"orientation" : "portrait",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"filename" : "Default@2x.png",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"extent" : "full-screen",
"idiom" : "iphone",
"subtype" : "retina4",
"filename" : "Default-568h@2x.png",
"minimum-system-version" : "7.0",
"orientation" : "portrait",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
APPL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
LSRequiresIPhoneOS
projectPath
$(SRCROOT)/$(TARGET_NAME)
UIRequiredDeviceCapabilities
armv7
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/JPErrorMsgViewController.h
================================================
//
// JPErrorMsgViewController.h
// JSPatchPlayground
//
// Created by bang on 5/14/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
@interface JPErrorMsgViewController : UIViewController
- (instancetype)initWithMsg:(NSString *)msg;
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/JPErrorMsgViewController.m
================================================
//
// JPErrorMsgViewController.m
// JSPatchPlayground
//
// Created by bang on 5/14/16.
// Copyright © 2016 bang. All rights reserved.
//
#import "JPErrorMsgViewController.h"
@interface JPErrorMsgViewController ()
@property (nonatomic) NSString *msg;
@end
@implementation JPErrorMsgViewController
- (instancetype)initWithMsg:(NSString *)msg
{
self = [super init];
if (self) {
self.msg = msg;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
UITextView *textView = [[UITextView alloc] initWithFrame:[UIScreen mainScreen].bounds];
textView.scrollEnabled = YES;
textView.text = self.msg;
[self.view addSubview:textView];
self.title = @"JSPatch Error";
[self.navigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStyleDone target:self action:@selector(handleBack)]];
}
- (void)handleBack
{
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/JPRootViewController.h
================================================
//
// ViewController.h
// JSPatchPlayground
//
// Created by bang on 5/14/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
@interface JPRootViewController : UIViewController
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/JPRootViewController.m
================================================
//
// ViewController.m
// JSPatchPlayground
//
// Created by bang on 5/14/16.
// Copyright © 2016 bang. All rights reserved.
//
#import "JPRootViewController.h"
#import "JPEngine.h"
#import "SGDirWatchdog.h"
#import "JPCleaner.h"
#import "JPErrorMsgViewController.h"
@interface JPRootViewController ()
@property (nonatomic) NSMutableArray *watchDogs;
@property (nonatomic) UIWindow *errorWindow;
@property (nonatomic) NSString *errMsg;
@end
@implementation JPRootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
#if TARGET_IPHONE_SIMULATOR
NSString *rootPath = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"projectPath"];
#else
NSString *rootPath = [[NSBundle mainBundle] bundlePath];
#endif
[JPEngine handleException:^(NSString *msg) {
if (!self.errorWindow) {
self.errorWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 20)];
self.errorWindow.windowLevel = UIWindowLevelStatusBar + 1.0f;
self.errorWindow.backgroundColor = [UIColor blackColor];
UIButton *errBtn = [[UIButton alloc] initWithFrame:CGRectMake(5, 0, [UIScreen mainScreen].bounds.size.width - 10, 20)];
errBtn.titleLabel.font = [UIFont systemFontOfSize:10];
[errBtn setTitle:msg forState:UIControlStateNormal];
[errBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
errBtn.tag = 100;
[errBtn addTarget:self action:@selector(handleTapErrorBtn) forControlEvents:UIControlEventTouchDown];
[self.errorWindow addSubview:errBtn];
[self.errorWindow makeKeyAndVisible];
} else {
UIButton *errBtn = [self.errorWindow viewWithTag:100];
[errBtn setTitle:msg forState:UIControlStateNormal];
}
self.errMsg = msg;
self.errorWindow.hidden = NO;
}];
NSString *scriptRootPath = [rootPath stringByAppendingPathComponent:@"src"];
NSString *mainScriptPath = [NSString stringWithFormat:@"%@/%@", scriptRootPath, @"/main.js"];
[JPEngine evaluateScriptWithPath:mainScriptPath];
self.watchDogs = [[NSMutableArray alloc] init];
NSArray *contentOfFolder = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:scriptRootPath error:NULL];
[self watchFolder:scriptRootPath mainScriptPath:mainScriptPath];
for (NSString *aPath in contentOfFolder) {
NSString * fullPath = [scriptRootPath stringByAppendingPathComponent:aPath];
BOOL isDir;
if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDir] && isDir) {
[self watchFolder:fullPath mainScriptPath:mainScriptPath];
}
}
[self showController];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];
[btn setTitle:@"Push Playground" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(showController) forControlEvents:UIControlEventTouchUpInside];
[btn setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:btn];
}
- (void)handleTapErrorBtn
{
JPErrorMsgViewController *errorMsgVC = [[JPErrorMsgViewController alloc] initWithMsg:self.errMsg];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:errorMsgVC];
[self.navigationController presentViewController:navigationController animated:YES completion:nil];
}
- (void)watchFolder:(NSString *)folderPath mainScriptPath:(NSString *)mainScriptPath
{
SGDirWatchdog *watchDog = [[SGDirWatchdog alloc] initWithPath:folderPath update:^{
self.errorWindow.hidden = YES;
[JPCleaner cleanAll];
[JPEngine evaluateScriptWithPath:mainScriptPath];
[self.navigationController popToRootViewControllerAnimated:NO];
[self showController];
}];
[watchDog start];
[self.watchDogs addObject:watchDog];
}
- (void)showController
{
//override in JSPatch
}
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/libs/SGDirWatchdog.h
================================================
//
// SGDirObserver.h
// DirectoryObserver
//
// Copyright (c) 2011 Simon Grätzer.
//
#import
@interface SGDirWatchdog : NSObject
@property (readonly, nonatomic) NSString *path;
@property (copy, nonatomic) void (^update)(void);
+ (NSString *)documentsPath;
+ (id)watchtdogOnDocumentsDir:(void (^)(void))update;
- (id)initWithPath:(NSString *)path update:(void (^)(void))update;
- (void)start;
- (void)stop;
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/libs/SGDirWatchdog.m
================================================
//
// SGDirObserver.m
// DirectoryObserver
//
// Copyright (c) 2011 Simon Grätzer.
//
#import "SGDirWatchdog.h"
#import
#import
#import
@interface SGDirWatchdog ()
@property (nonatomic, readonly) CFFileDescriptorRef kqRef;
- (void)kqueueFired;
@end
static void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info) {
// Pick up the object passed in the "info" member of the CFFileDescriptorContext passed to CFFileDescriptorCreate
SGDirWatchdog* obj = (__bridge SGDirWatchdog*) info;
if ([obj isKindOfClass:[SGDirWatchdog class]] && // If we can call back to the proper sort of object ...
(kqRef == obj.kqRef) && // and the FD that issued the CB is the expected one ...
(callBackTypes == kCFFileDescriptorReadCallBack) ) // and we're processing the proper sort of CB ...
{
[obj kqueueFired]; // Invoke the instance's CB handler
}
}
@implementation SGDirWatchdog {
int _dirFD;
CFFileDescriptorRef _kqRef;
}
+ (NSString *)documentsPath {
NSArray *documentsPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return documentsPaths[0]; // Path to the application's "Documents" directory
}
+ (id)watchtdogOnDocumentsDir:(void (^)(void))update; {
return [[SGDirWatchdog alloc]initWithPath:[self documentsPath] update:update];
}
- (id)initWithPath:(NSString *)path update:(void (^)(void))update; {
if ((self = [super init])) {
_path = path;
_update = [update copy];
}
return self;
}
- (void)dealloc {
[self stop];
}
#pragma mark -
#pragma mark Extension methods
- (void)kqueueFired {
// Pull the native FD around which the CFFileDescriptor was wrapped
int kq = CFFileDescriptorGetNativeDescriptor(_kqRef);
if (kq < 0) return;
// If we pull a single available event out of the queue, assume the directory was updated
struct kevent event;
struct timespec timeout = {0, 0};
if (kevent(kq, NULL, 0, &event, 1, &timeout) == 1 && _update) {
_update();
}
// (Re-)Enable a one-shot (the only kind) callback
CFFileDescriptorEnableCallBacks(_kqRef, kCFFileDescriptorReadCallBack);
}
- (void)start {
// One ping only
if (_kqRef != NULL) return;
// Fetch pathname of the directory to monitor
NSString* docPath = self.path;
if (!docPath) return;
// Open an event-only file descriptor associated with the directory
int dirFD = open([docPath fileSystemRepresentation], O_EVTONLY);
if (dirFD < 0) return;
// Create a new kernel event queue
int kq = kqueue();
if (kq < 0)
{
close(dirFD);
return;
}
// Set up a kevent to monitor
struct kevent eventToAdd; // Register an (ident, filter) pair with the kqueue
eventToAdd.ident = dirFD; // The object to watch (the directory FD)
eventToAdd.filter = EVFILT_VNODE; // Watch for certain events on the VNODE spec'd by ident
eventToAdd.flags = EV_ADD | EV_CLEAR; // Add a resetting kevent
eventToAdd.fflags = NOTE_WRITE; // The events to watch for on the VNODE spec'd by ident (writes)
eventToAdd.data = 0; // No filter-specific data
eventToAdd.udata = NULL; // No user data
// Add a kevent to monitor
if (kevent(kq, &eventToAdd, 1, NULL, 0, NULL)) {
close(kq);
close(dirFD);
return;
}
// Wrap a CFFileDescriptor around a native FD
CFFileDescriptorContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
_kqRef = CFFileDescriptorCreate(NULL, // Use the default allocator
kq, // Wrap the kqueue
true, // Close the CFFileDescriptor if kq is invalidated
KQCallback, // Fxn to call on activity
&context); // Supply a context to set the callback's "info" argument
if (_kqRef == NULL) {
close(kq);
close(dirFD);
return;
}
// Spin out a pluggable run loop source from the CFFileDescriptorRef
// Add it to the current run loop, then release it
CFRunLoopSourceRef rls = CFFileDescriptorCreateRunLoopSource(NULL, _kqRef, 0);
if (rls == NULL) {
CFRelease(_kqRef); _kqRef = NULL;
close(kq);
close(dirFD);
return;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
CFRelease(rls);
// Store the directory FD for later closing
_dirFD = dirFD;
// Enable a one-shot (the only kind) callback
CFFileDescriptorEnableCallBacks(_kqRef, kCFFileDescriptorReadCallBack);
}
- (void)stop {
if (_kqRef) {
close(_dirFD);
CFFileDescriptorInvalidate(_kqRef);
CFRelease(_kqRef);
_kqRef = NULL;
}
}
@end
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/main.m
================================================
//
// main.m
// JSPatchPlayground
//
// Created by bang on 5/14/16.
// Copyright © 2016 bang. All rights reserved.
//
#import
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/src/JPDemoController.js
================================================
require('UILabel, UIColor, UIFont, UIScreen, UIImageView, UIImage')
var screenWidth = UIScreen.mainScreen().bounds().width;
var screenHeight = UIScreen.mainScreen().bounds().height;
defineClass('JPDemoController: UIViewController', {
viewDidLoad: function() {
self.super().viewDidLoad();
self.view().setBackgroundColor(UIColor.whiteColor());
var size = 120;
var imgView = UIImageView.alloc().initWithFrame({x: (screenWidth - size)/2, y: 150, width: size, height: size});
imgView.setImage(UIImage.imageWithContentsOfFile(resourcePath('apple.png')));
self.view().addSubview(imgView);
var label = UILabel.alloc().initWithFrame({x: 0, y: 310, width: screenWidth, height: 30});
label.setText("JSPatch");
label.setTextAlignment(1);
label.setFont(UIFont.systemFontOfSize(25));
self.view().addSubview(label);
},
})
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground/src/main.js
================================================
include('JPDemoController.js');
defineClass('JPRootViewController', {
showController: function() {
var ctrl = JPDemoController.alloc().init();
self.navigationController().pushViewController_animated(ctrl, NO);
}
});
================================================
FILE: Demo/iOSPlayground/JSPatchPlayground.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
361443641CE8041A00B303D4 /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 361443461CE8041A00B303D4 /* JPCleaner.m */; };
361443651CE8041A00B303D4 /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 361443481CE8041A00B303D4 /* JPLocker.m */; };
361443671CE8041A00B303D4 /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 3614434C1CE8041A00B303D4 /* JPSpecialInit.m */; };
3614436D1CE8041A00B303D4 /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3614435A1CE8041A00B303D4 /* JPEngine.m */; };
3614436E1CE8041A00B303D4 /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3614435B1CE8041A00B303D4 /* JSPatch.js */; };
3660A8671CE3542A008970B4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A8661CE3542A008970B4 /* main.m */; };
3660A86A1CE3542A008970B4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A8691CE3542A008970B4 /* AppDelegate.m */; };
3660A86D1CE3542A008970B4 /* JPRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A86C1CE3542A008970B4 /* JPRootViewController.m */; };
3660A8721CE3542A008970B4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3660A8711CE3542A008970B4 /* Assets.xcassets */; };
3660A8B51CE365FB008970B4 /* src in Resources */ = {isa = PBXBuildFile; fileRef = 3660A8B41CE365FB008970B4 /* src */; };
3660A8F21CE36D05008970B4 /* SGDirWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A8F11CE36D05008970B4 /* SGDirWatchdog.m */; };
3660A90D1CE4A546008970B4 /* JPErrorMsgViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A90C1CE4A546008970B4 /* JPErrorMsgViewController.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
361443451CE8041A00B303D4 /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = "