rename dirs
This commit is contained in:
37
doric-iOS/.gitignore
vendored
Normal file
37
doric-iOS/.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# OS X
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
*.xccheckout
|
||||
profile
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
Example/Pods
|
||||
# Bundler
|
||||
.bundle
|
||||
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
|
||||
#
|
||||
# Note: if you ignore the Pods directory, make sure to uncomment
|
||||
# `pod install` in .travis.yml
|
||||
#
|
||||
# Pods/
|
14
doric-iOS/.travis.yml
Normal file
14
doric-iOS/.travis.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
# references:
|
||||
# * https://www.objc.io/issues/6-build-tools/travis-ci/
|
||||
# * https://github.com/supermarin/xcpretty#usage
|
||||
|
||||
osx_image: xcode7.3
|
||||
language: objective-c
|
||||
# cache: cocoapods
|
||||
# podfile: Example/Podfile
|
||||
# before_install:
|
||||
# - gem install cocoapods # Since Travis is not always on latest version
|
||||
# - pod install --project-directory=Example
|
||||
script:
|
||||
- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/Doric.xcworkspace -scheme Doric-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
|
||||
- pod lib lint
|
48
doric-iOS/Doric.podspec
Normal file
48
doric-iOS/Doric.podspec
Normal file
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# Be sure to run `pod lib lint Doric.podspec' to ensure this is a
|
||||
# valid spec before submitting.
|
||||
#
|
||||
# Any lines starting with a # are optional, but their use is encouraged
|
||||
# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'Doric'
|
||||
s.version = '0.1.0'
|
||||
s.summary = 'A short description of Doric.'
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
# * Think: What does it do? Why did you write it? What is the focus?
|
||||
# * Try to keep it short, snappy and to the point.
|
||||
# * Write the description between the DESC delimiters below.
|
||||
# * Finally, don't worry about the indent, CocoaPods strips it!
|
||||
|
||||
s.description = <<-DESC
|
||||
TODO: Add long description of the pod here.
|
||||
DESC
|
||||
|
||||
s.homepage = 'https://github.com/doric-pub/doric'
|
||||
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
|
||||
s.license = { :type => 'Apache-2.0', :file => 'LICENSE' }
|
||||
s.author = { 'pengfei.zhou' => 'pengfeizhou@foxmail.com' }
|
||||
s.source = { :git => 'git@github.com:penfeizhou/doric.git', :tag => s.version.to_s }
|
||||
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
|
||||
|
||||
s.ios.deployment_target = '8.0'
|
||||
|
||||
s.source_files = 'Pod/Classes/**/*'
|
||||
s.resource = "Pod/Assets/*.js"
|
||||
s.resource_bundles = {
|
||||
'Doric' => ['Pod/Assets/**/*']
|
||||
}
|
||||
|
||||
s.public_header_files = 'Pod/Classes/**/*.h'
|
||||
# s.frameworks = 'UIKit', 'MapKit'
|
||||
# s.dependency 'AFNetworking', '~> 2.3'
|
||||
# s.dependency 'SDWebImage', '~> 5.0'
|
||||
s.dependency 'YYWebImage', '~>1.0.5'
|
||||
s.dependency 'YYImage/WebP'
|
||||
s.dependency 'SocketRocket', '~> 0.5.1'
|
||||
s.dependency 'GCDWebServer', '~> 3.0'
|
||||
s.dependency 'YYCache', '~> 1.0.4'
|
||||
end
|
1
doric-iOS/Example/.gitignore
vendored
Normal file
1
doric-iOS/Example/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.idea/
|
856
doric-iOS/Example/Example.xcodeproj/project.pbxproj
Normal file
856
doric-iOS/Example/Example.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,856 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 51;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1B5560FDC1A57040A84A35AB /* libPods-ExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 30CF3CCBAF1F8AD594763E4A /* libPods-ExampleTests.a */; };
|
||||
2EB14575543B0285648B858D /* libPods-Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C3CFA4394FF1344386170022 /* libPods-Example.a */; };
|
||||
835F4CD080BABFE95A6BFD16 /* libPods-ExampleUITests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 563C5AC823878F4913BBCDF2 /* libPods-ExampleUITests.a */; };
|
||||
D751D4B065D8D4FA6594B5EE /* DemoVC.m in Sources */ = {isa = PBXBuildFile; fileRef = D751D19E97EF4EDD7588FEBE /* DemoVC.m */; };
|
||||
D751D4FCC0A2322211DE3D55 /* QRScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D751DA399F1ADB6D34563B5D /* QRScanViewController.m */; };
|
||||
E2334AF022E9D2060098A085 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334AEF22E9D2060098A085 /* AppDelegate.m */; };
|
||||
E2334AF322E9D2060098A085 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334AF222E9D2060098A085 /* ViewController.m */; };
|
||||
E2334AF622E9D2060098A085 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2334AF422E9D2060098A085 /* Main.storyboard */; };
|
||||
E2334AF822E9D2070098A085 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2334AF722E9D2070098A085 /* Assets.xcassets */; };
|
||||
E2334AFB22E9D2070098A085 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2334AF922E9D2070098A085 /* LaunchScreen.storyboard */; };
|
||||
E2334AFE22E9D2070098A085 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334AFD22E9D2070098A085 /* main.m */; };
|
||||
E2334B0822E9D2070098A085 /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334B0722E9D2070098A085 /* ExampleTests.m */; };
|
||||
E2334B1322E9D2070098A085 /* ExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334B1222E9D2070098A085 /* ExampleUITests.m */; };
|
||||
E2F4481723839AC500073C7F /* demo in Resources */ = {isa = PBXBuildFile; fileRef = E2F4481623839AC500073C7F /* demo */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
E2334B0422E9D2070098A085 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = E2334AE322E9D2060098A085 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = E2334AEA22E9D2060098A085;
|
||||
remoteInfo = Example;
|
||||
};
|
||||
E2334B0F22E9D2070098A085 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = E2334AE322E9D2060098A085 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = E2334AEA22E9D2060098A085;
|
||||
remoteInfo = Example;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
016E930415B91D826F9FFF47 /* Pods-ExampleUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleUITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ExampleUITests/Pods-ExampleUITests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
30CF3CCBAF1F8AD594763E4A /* libPods-ExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3D75F592D76A665674B31A66 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = "<group>"; };
|
||||
563C5AC823878F4913BBCDF2 /* libPods-ExampleUITests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ExampleUITests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8231E841CCAF382F85C9F576 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B93423722F2E06DC238CDD18 /* Pods-ExampleUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ExampleUITests/Pods-ExampleUITests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
B93D4DB00FD244178B7CE7C4 /* Pods-ExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ExampleTests/Pods-ExampleTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C3CFA4394FF1344386170022 /* libPods-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D751D18AD6496F4A9BE1AB45 /* QRScanViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRScanViewController.h; sourceTree = "<group>"; };
|
||||
D751D19E97EF4EDD7588FEBE /* DemoVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoVC.m; sourceTree = "<group>"; };
|
||||
D751DA399F1ADB6D34563B5D /* QRScanViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRScanViewController.m; sourceTree = "<group>"; };
|
||||
D751DDEC114E037231257E64 /* DemoVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoVC.h; sourceTree = "<group>"; };
|
||||
D91241144B5A3356A3C60644 /* Pods-ExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ExampleTests/Pods-ExampleTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
E2334AEB22E9D2060098A085 /* Doric Playground.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Doric Playground.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E2334AEE22E9D2060098A085 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
E2334AEF22E9D2060098A085 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
E2334AF122E9D2060098A085 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||
E2334AF222E9D2060098A085 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||
E2334AF522E9D2060098A085 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
E2334AF722E9D2070098A085 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
E2334AFA22E9D2070098A085 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
E2334AFC22E9D2070098A085 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E2334AFD22E9D2070098A085 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
E2334B0322E9D2070098A085 /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E2334B0722E9D2070098A085 /* ExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleTests.m; sourceTree = "<group>"; };
|
||||
E2334B0922E9D2070098A085 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E2334B0E22E9D2070098A085 /* ExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E2334B1222E9D2070098A085 /* ExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleUITests.m; sourceTree = "<group>"; };
|
||||
E2334B1422E9D2070098A085 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E2F4481623839AC500073C7F /* demo */ = {isa = PBXFileReference; lastKnownFileType = folder; path = demo; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
E2334AE822E9D2060098A085 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2EB14575543B0285648B858D /* libPods-Example.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E2334B0022E9D2070098A085 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1B5560FDC1A57040A84A35AB /* libPods-ExampleTests.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E2334B0B22E9D2070098A085 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
835F4CD080BABFE95A6BFD16 /* libPods-ExampleUITests.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
6CBE6FA5F47A90E57AB456B2 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8231E841CCAF382F85C9F576 /* Pods-Example.debug.xcconfig */,
|
||||
3D75F592D76A665674B31A66 /* Pods-Example.release.xcconfig */,
|
||||
D91241144B5A3356A3C60644 /* Pods-ExampleTests.debug.xcconfig */,
|
||||
B93D4DB00FD244178B7CE7C4 /* Pods-ExampleTests.release.xcconfig */,
|
||||
016E930415B91D826F9FFF47 /* Pods-ExampleUITests.debug.xcconfig */,
|
||||
B93423722F2E06DC238CDD18 /* Pods-ExampleUITests.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D80A9B07B39AD04027CAE17B /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C3CFA4394FF1344386170022 /* libPods-Example.a */,
|
||||
30CF3CCBAF1F8AD594763E4A /* libPods-ExampleTests.a */,
|
||||
563C5AC823878F4913BBCDF2 /* libPods-ExampleUITests.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E2334AE222E9D2060098A085 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2334AED22E9D2060098A085 /* Example */,
|
||||
E2334B0622E9D2070098A085 /* ExampleTests */,
|
||||
E2334B1122E9D2070098A085 /* ExampleUITests */,
|
||||
E2334AEC22E9D2060098A085 /* Products */,
|
||||
6CBE6FA5F47A90E57AB456B2 /* Pods */,
|
||||
D80A9B07B39AD04027CAE17B /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E2334AEC22E9D2060098A085 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2334AEB22E9D2060098A085 /* Doric Playground.app */,
|
||||
E2334B0322E9D2070098A085 /* ExampleTests.xctest */,
|
||||
E2334B0E22E9D2070098A085 /* ExampleUITests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E2334AED22E9D2060098A085 /* Example */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2F4481623839AC500073C7F /* demo */,
|
||||
E2334AEE22E9D2060098A085 /* AppDelegate.h */,
|
||||
E2334AEF22E9D2060098A085 /* AppDelegate.m */,
|
||||
E2334AF122E9D2060098A085 /* ViewController.h */,
|
||||
E2334AF222E9D2060098A085 /* ViewController.m */,
|
||||
E2334AF422E9D2060098A085 /* Main.storyboard */,
|
||||
E2334AF722E9D2070098A085 /* Assets.xcassets */,
|
||||
E2334AFC22E9D2070098A085 /* Info.plist */,
|
||||
E2334AF922E9D2070098A085 /* LaunchScreen.storyboard */,
|
||||
E2334AFD22E9D2070098A085 /* main.m */,
|
||||
D751D19E97EF4EDD7588FEBE /* DemoVC.m */,
|
||||
D751DDEC114E037231257E64 /* DemoVC.h */,
|
||||
D751DA399F1ADB6D34563B5D /* QRScanViewController.m */,
|
||||
D751D18AD6496F4A9BE1AB45 /* QRScanViewController.h */,
|
||||
);
|
||||
path = Example;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E2334B0622E9D2070098A085 /* ExampleTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2334B0722E9D2070098A085 /* ExampleTests.m */,
|
||||
E2334B0922E9D2070098A085 /* Info.plist */,
|
||||
);
|
||||
path = ExampleTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E2334B1122E9D2070098A085 /* ExampleUITests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2334B1222E9D2070098A085 /* ExampleUITests.m */,
|
||||
E2334B1422E9D2070098A085 /* Info.plist */,
|
||||
);
|
||||
path = ExampleUITests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
E2334AEA22E9D2060098A085 /* Example */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E2334B1722E9D2070098A085 /* Build configuration list for PBXNativeTarget "Example" */;
|
||||
buildPhases = (
|
||||
BE34CD8291B20D26F2ADE3E1 /* [CP] Check Pods Manifest.lock */,
|
||||
E24A030C22EED0D500AB4631 /* Package JS Bundle */,
|
||||
E2334AE722E9D2060098A085 /* Sources */,
|
||||
E2334AE822E9D2060098A085 /* Frameworks */,
|
||||
E2334AE922E9D2060098A085 /* Resources */,
|
||||
2719DACF05C7A7C1EB4AD553 /* [CP] Embed Pods Frameworks */,
|
||||
C232600D894D85358A6ABF4D /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Example;
|
||||
productName = Example;
|
||||
productReference = E2334AEB22E9D2060098A085 /* Doric Playground.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
E2334B0222E9D2070098A085 /* ExampleTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E2334B1A22E9D2070098A085 /* Build configuration list for PBXNativeTarget "ExampleTests" */;
|
||||
buildPhases = (
|
||||
48D050F720D3A879060292A8 /* [CP] Check Pods Manifest.lock */,
|
||||
E2334AFF22E9D2070098A085 /* Sources */,
|
||||
E2334B0022E9D2070098A085 /* Frameworks */,
|
||||
E2334B0122E9D2070098A085 /* Resources */,
|
||||
68729F70B03CECDBAD2022E4 /* [CP] Embed Pods Frameworks */,
|
||||
D5C1C722575685F99C382E01 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
E2334B0522E9D2070098A085 /* PBXTargetDependency */,
|
||||
);
|
||||
name = ExampleTests;
|
||||
productName = ExampleTests;
|
||||
productReference = E2334B0322E9D2070098A085 /* ExampleTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
E2334B0D22E9D2070098A085 /* ExampleUITests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = E2334B1D22E9D2070098A085 /* Build configuration list for PBXNativeTarget "ExampleUITests" */;
|
||||
buildPhases = (
|
||||
074533B9C1C5204E8750B07B /* [CP] Check Pods Manifest.lock */,
|
||||
E2334B0A22E9D2070098A085 /* Sources */,
|
||||
E2334B0B22E9D2070098A085 /* Frameworks */,
|
||||
E2334B0C22E9D2070098A085 /* Resources */,
|
||||
AC45D4A1B85D5D5A2F6E3DBD /* [CP] Embed Pods Frameworks */,
|
||||
F0AA1A5ADB99F5ECA1F9331E /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
E2334B1022E9D2070098A085 /* PBXTargetDependency */,
|
||||
);
|
||||
name = ExampleUITests;
|
||||
productName = ExampleUITests;
|
||||
productReference = E2334B0E22E9D2070098A085 /* ExampleUITests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.ui-testing";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
E2334AE322E9D2060098A085 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1030;
|
||||
ORGANIZATIONNAME = pengfei.zhou;
|
||||
TargetAttributes = {
|
||||
E2334AEA22E9D2060098A085 = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
};
|
||||
E2334B0222E9D2070098A085 = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
TestTargetID = E2334AEA22E9D2060098A085;
|
||||
};
|
||||
E2334B0D22E9D2070098A085 = {
|
||||
CreatedOnToolsVersion = 10.3;
|
||||
TestTargetID = E2334AEA22E9D2060098A085;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = E2334AE622E9D2060098A085 /* Build configuration list for PBXProject "Example" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = E2334AE222E9D2060098A085;
|
||||
productRefGroup = E2334AEC22E9D2060098A085 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
E2334AEA22E9D2060098A085 /* Example */,
|
||||
E2334B0222E9D2070098A085 /* ExampleTests */,
|
||||
E2334B0D22E9D2070098A085 /* ExampleUITests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
E2334AE922E9D2060098A085 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E2334AFB22E9D2070098A085 /* LaunchScreen.storyboard in Resources */,
|
||||
E2F4481723839AC500073C7F /* demo in Resources */,
|
||||
E2334AF822E9D2070098A085 /* Assets.xcassets in Resources */,
|
||||
E2334AF622E9D2060098A085 /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E2334B0122E9D2070098A085 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E2334B0C22E9D2070098A085 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
074533B9C1C5204E8750B07B /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-ExampleUITests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
2719DACF05C7A7C1EB4AD553 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
48D050F720D3A879060292A8 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-ExampleTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
68729F70B03CECDBAD2022E4 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ExampleTests/Pods-ExampleTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
AC45D4A1B85D5D5A2F6E3DBD /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ExampleUITests/Pods-ExampleUITests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
BE34CD8291B20D26F2ADE3E1 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C232600D894D85358A6ABF4D /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/Doric/Doric.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Doric.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D5C1C722575685F99C382E01 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ExampleTests/Pods-ExampleTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E24A030C22EED0D500AB4631 /* Package JS Bundle */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Package JS Bundle";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\" ] && \\. \"$NVM_DIR/nvm.sh\" # This loads nvm\n[ -s \"$NVM_DIR/bash_completion\" ] && \\. \"$NVM_DIR/bash_completion\" # This loads nvm bash_completion\n\ncd ../../js-framework && npm run build\ncd ../demo && npm run build\n";
|
||||
};
|
||||
F0AA1A5ADB99F5ECA1F9331E /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ExampleUITests/Pods-ExampleUITests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
E2334AE722E9D2060098A085 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E2334AF322E9D2060098A085 /* ViewController.m in Sources */,
|
||||
E2334AFE22E9D2070098A085 /* main.m in Sources */,
|
||||
E2334AF022E9D2060098A085 /* AppDelegate.m in Sources */,
|
||||
D751D4B065D8D4FA6594B5EE /* DemoVC.m in Sources */,
|
||||
D751D4FCC0A2322211DE3D55 /* QRScanViewController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E2334AFF22E9D2070098A085 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E2334B0822E9D2070098A085 /* ExampleTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
E2334B0A22E9D2070098A085 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E2334B1322E9D2070098A085 /* ExampleUITests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
E2334B0522E9D2070098A085 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = E2334AEA22E9D2060098A085 /* Example */;
|
||||
targetProxy = E2334B0422E9D2070098A085 /* PBXContainerItemProxy */;
|
||||
};
|
||||
E2334B1022E9D2070098A085 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = E2334AEA22E9D2060098A085 /* Example */;
|
||||
targetProxy = E2334B0F22E9D2070098A085 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
E2334AF422E9D2060098A085 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
E2334AF522E9D2060098A085 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E2334AF922E9D2070098A085 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
E2334AFA22E9D2070098A085 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
E2334B1522E9D2070098A085 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
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 = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E2334B1622E9D2070098A085 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "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 = gnu11;
|
||||
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 = 12.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E2334B1822E9D2070098A085 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 8231E841CCAF382F85C9F576 /* Pods-Example.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 7EE2RX3L3P;
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pub.doric.Example;
|
||||
PRODUCT_NAME = "Doric Playground";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E2334B1922E9D2070098A085 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3D75F592D76A665674B31A66 /* Pods-Example.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 7EE2RX3L3P;
|
||||
INFOPLIST_FILE = Example/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pub.doric.Example;
|
||||
PRODUCT_NAME = "Doric Playground";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E2334B1B22E9D2070098A085 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D91241144B5A3356A3C60644 /* Pods-ExampleTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pub.doric.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E2334B1C22E9D2070098A085 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B93D4DB00FD244178B7CE7C4 /* Pods-ExampleTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
INFOPLIST_FILE = ExampleTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pub.doric.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
E2334B1E22E9D2070098A085 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 016E930415B91D826F9FFF47 /* Pods-ExampleUITests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
INFOPLIST_FILE = ExampleUITests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pub.doric.ExampleUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_TARGET_NAME = Example;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
E2334B1F22E9D2070098A085 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B93423722F2E06DC238CDD18 /* Pods-ExampleUITests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
INFOPLIST_FILE = ExampleUITests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pub.doric.ExampleUITests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TEST_TARGET_NAME = Example;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
E2334AE622E9D2060098A085 /* Build configuration list for PBXProject "Example" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E2334B1522E9D2070098A085 /* Debug */,
|
||||
E2334B1622E9D2070098A085 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E2334B1722E9D2070098A085 /* Build configuration list for PBXNativeTarget "Example" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E2334B1822E9D2070098A085 /* Debug */,
|
||||
E2334B1922E9D2070098A085 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E2334B1A22E9D2070098A085 /* Build configuration list for PBXNativeTarget "ExampleTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E2334B1B22E9D2070098A085 /* Debug */,
|
||||
E2334B1C22E9D2070098A085 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
E2334B1D22E9D2070098A085 /* Build configuration list for PBXNativeTarget "ExampleUITests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
E2334B1E22E9D2070098A085 /* Debug */,
|
||||
E2334B1F22E9D2070098A085 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = E2334AE322E9D2060098A085 /* Project object */;
|
||||
}
|
7
doric-iOS/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
doric-iOS/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Example.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1030"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E2334AEA22E9D2060098A085"
|
||||
BuildableName = "Doric Playground.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E2334AEA22E9D2060098A085"
|
||||
BuildableName = "Doric Playground.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E2334B0222E9D2070098A085"
|
||||
BuildableName = "ExampleTests.xctest"
|
||||
BlueprintName = "ExampleTests"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E2334B0D22E9D2070098A085"
|
||||
BuildableName = "ExampleUITests.xctest"
|
||||
BlueprintName = "ExampleUITests"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E2334AEA22E9D2060098A085"
|
||||
BuildableName = "Doric Playground.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E2334AEA22E9D2060098A085"
|
||||
BuildableName = "Doric Playground.app"
|
||||
BlueprintName = "Example"
|
||||
ReferencedContainer = "container:Example.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
17
doric-iOS/Example/Example/AppDelegate.h
Normal file
17
doric-iOS/Example/Example/AppDelegate.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// AppDelegate.h
|
||||
// Example
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
// Copyright © 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
|
||||
@end
|
||||
|
61
doric-iOS/Example/Example/AppDelegate.m
Normal file
61
doric-iOS/Example/Example/AppDelegate.m
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// AppDelegate.m
|
||||
// Example
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
// Copyright © 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "ViewController.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
@property(nonatomic, strong) UIViewController *rootVC;
|
||||
@property(nonatomic, strong) UINavigationController *navigationController;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.rootVC = [[ViewController alloc] init];
|
||||
|
||||
self.window.rootViewController = self.rootVC;
|
||||
self.navigationController = [[UINavigationController
|
||||
alloc] initWithRootViewController:self.rootVC];
|
||||
[self.window addSubview:self.navigationController.view];
|
||||
[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 invalidate graphics rendering callbacks. 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 active 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
|
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"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" : "20x20",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
6
doric-iOS/Example/Example/Assets.xcassets/Contents.json
Normal file
6
doric-iOS/Example/Example/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
25
doric-iOS/Example/Example/Base.lproj/LaunchScreen.storyboard
Normal file
25
doric-iOS/Example/Example/Base.lproj/LaunchScreen.storyboard
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
24
doric-iOS/Example/Example/Base.lproj/Main.storyboard
Normal file
24
doric-iOS/Example/Example/Base.lproj/Main.storyboard
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
12
doric-iOS/Example/Example/DemoVC.h
Normal file
12
doric-iOS/Example/Example/DemoVC.h
Normal file
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/19.
|
||||
// Copyright (c) 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
@interface DemoVC : UIViewController
|
||||
- (instancetype)initWithPath:(NSString *)filePath;
|
||||
@end
|
39
doric-iOS/Example/Example/DemoVC.m
Normal file
39
doric-iOS/Example/Example/DemoVC.m
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/19.
|
||||
// Copyright (c) 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import "DemoVC.h"
|
||||
#import "Doric.h"
|
||||
|
||||
@interface DemoVC ()
|
||||
@property(nonatomic, copy) NSString *filePath;
|
||||
@end
|
||||
|
||||
@implementation DemoVC
|
||||
- (instancetype)initWithPath:(NSString *)filePath {
|
||||
if (self = [self init]) {
|
||||
_filePath = filePath;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
self.title = self.filePath;
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
NSString *path = [[NSBundle mainBundle] bundlePath];
|
||||
NSString *demoPath = [path stringByAppendingPathComponent:@"demo"];
|
||||
NSString *fullPath = [demoPath stringByAppendingPathComponent:self.filePath];
|
||||
NSString *jsContent = [NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:nil];
|
||||
DoricPanel *panel = [DoricPanel new];
|
||||
[panel.view also:^(UIView *it) {
|
||||
it.width = self.view.width;
|
||||
it.height = self.view.height - 88;
|
||||
it.top = 88;
|
||||
[self.view addSubview:it];
|
||||
}];
|
||||
[self addChildViewController:panel];
|
||||
[panel config:jsContent alias:self.filePath];
|
||||
}
|
||||
|
||||
@end
|
54
doric-iOS/Example/Example/Info.plist
Normal file
54
doric-iOS/Example/Example/Info.plist
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Scan QR Code</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string></string>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
10
doric-iOS/Example/Example/QRScanViewController.h
Normal file
10
doric-iOS/Example/Example/QRScanViewController.h
Normal file
@@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/21.
|
||||
// Copyright (c) 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface QRScanViewController : UIViewController
|
||||
@end
|
93
doric-iOS/Example/Example/QRScanViewController.m
Normal file
93
doric-iOS/Example/Example/QRScanViewController.m
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/21.
|
||||
// Copyright (c) 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import "QRScanViewController.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "Doric.h"
|
||||
|
||||
@interface QRScanViewController () <AVCaptureMetadataOutputObjectsDelegate>
|
||||
@property(strong, nonatomic) AVCaptureDevice *device;
|
||||
@property(strong, nonatomic) AVCaptureDeviceInput *input;
|
||||
@property(strong, nonatomic) AVCaptureMetadataOutput *output;
|
||||
@property(strong, nonatomic) AVCaptureSession *session;
|
||||
@property(strong, nonatomic) AVCaptureVideoPreviewLayer *previewLayer;
|
||||
@property(strong, nonatomic) UIPinchGestureRecognizer *pinchGes;
|
||||
@property(assign, nonatomic) CGFloat scanRegion_W;
|
||||
@property(assign, nonatomic) CGFloat initScale;
|
||||
@end
|
||||
|
||||
@implementation QRScanViewController
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.title = @"扫一扫";
|
||||
[self configBasicDevice];
|
||||
[self configPinchGes];
|
||||
[self.session startRunning];
|
||||
}
|
||||
|
||||
- (void)configBasicDevice {
|
||||
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
self.input = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:nil];
|
||||
self.output = [[AVCaptureMetadataOutput alloc] init];
|
||||
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
|
||||
self.session = [[AVCaptureSession alloc] init];
|
||||
[self.session setSessionPreset:AVCaptureSessionPresetHigh];
|
||||
if ([self.session canAddInput:self.input]) {
|
||||
[self.session addInput:self.input];
|
||||
}
|
||||
if ([self.session canAddOutput:self.output]) {
|
||||
[self.session addOutput:self.output];
|
||||
}
|
||||
[self.output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
|
||||
[self.output setRectOfInterest:CGRectMake(0, 0, 1, 1)];
|
||||
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
|
||||
self.previewLayer.frame = CGRectMake(0, 0, self.view.width, self.view.height);
|
||||
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||
[self.view.layer addSublayer:self.previewLayer];
|
||||
}
|
||||
|
||||
- (void)configPinchGes {
|
||||
self.pinchGes = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchDetected:)];
|
||||
[self.view addGestureRecognizer:self.pinchGes];
|
||||
}
|
||||
|
||||
- (void)pinchDetected:(UIPinchGestureRecognizer *)recogniser {
|
||||
if (!_device) {
|
||||
return;
|
||||
}
|
||||
if (recogniser.state == UIGestureRecognizerStateBegan) {
|
||||
_initScale = _device.videoZoomFactor;
|
||||
}
|
||||
NSError *error = nil;
|
||||
[_device lockForConfiguration:&error];
|
||||
if (!error) {
|
||||
CGFloat zoomFactor;
|
||||
CGFloat scale = recogniser.scale;
|
||||
if (scale < 1.0f) {
|
||||
zoomFactor = self.initScale - pow(self.device.activeFormat.videoMaxZoomFactor, 1.0f - recogniser.scale);
|
||||
} else {
|
||||
zoomFactor = self.initScale + pow(self.device.activeFormat.videoMaxZoomFactor, (recogniser.scale - 1.0f) / 2.0f);
|
||||
}
|
||||
zoomFactor = MIN(15.0f, zoomFactor);
|
||||
zoomFactor = MAX(1.0f, zoomFactor);
|
||||
_device.videoZoomFactor = zoomFactor;
|
||||
[_device unlockForConfiguration];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - AVCaptureMetadataOutputObjectsDelegate
|
||||
|
||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
|
||||
[self.session stopRunning];
|
||||
if ([metadataObjects count] >= 1) {
|
||||
AVMetadataMachineReadableCodeObject *qrObject = [metadataObjects lastObject];
|
||||
NSString *result = qrObject.stringValue;
|
||||
NSLog(@"Scan result is %@", result);
|
||||
[[DoricDriver instance] connectDevKit:[NSString stringWithFormat:@"ws://%@:7777", result]];
|
||||
ShowToast([NSString stringWithFormat:@"Connected to %@", result], BOTTOM);
|
||||
[self.navigationController popViewControllerAnimated:NO];
|
||||
}
|
||||
}
|
||||
@end
|
15
doric-iOS/Example/Example/ViewController.h
Normal file
15
doric-iOS/Example/Example/ViewController.h
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// ViewController.h
|
||||
// Example
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
// Copyright © 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface ViewController : UIViewController
|
||||
|
||||
|
||||
@end
|
||||
|
83
doric-iOS/Example/Example/ViewController.m
Normal file
83
doric-iOS/Example/Example/ViewController.m
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// ViewController.m
|
||||
// Example
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
// Copyright © 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ViewController.h"
|
||||
#import "Doric.h"
|
||||
#import "DemoVC.h"
|
||||
#import "QRScanViewController.h"
|
||||
|
||||
@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
|
||||
@property(nonatomic, copy) NSArray <NSString *> *demoFilePaths;
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.title = @"Doric Demo";
|
||||
NSString *path = [[NSBundle mainBundle] bundlePath];
|
||||
NSString *demoPath = [path stringByAppendingPathComponent:@"demo"];
|
||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||
self.demoFilePaths = [[mgr subpathsAtPath:demoPath] filter:^BOOL(NSString *obj) {
|
||||
return ![obj containsString:@".map"];
|
||||
}];
|
||||
NSMutableArray <NSString *> *tmp = [self.demoFilePaths mutableCopy];
|
||||
[tmp insertObject:@"Dev Kit" atIndex:0];
|
||||
self.demoFilePaths = tmp;
|
||||
[self.view addSubview:[[UITableView new] also:^(UITableView *it) {
|
||||
it.width = self.view.width;
|
||||
it.height = self.view.height;
|
||||
it.left = it.top = 0;
|
||||
it.dataSource = self;
|
||||
it.delegate = self;
|
||||
}]];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return self.demoFilePaths.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSString *path = self.demoFilePaths[(NSUInteger) indexPath.row];
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
|
||||
if (cell == nil) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellID"];
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
}
|
||||
cell.textLabel.text = path;
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (BOOL)isSimulator {
|
||||
return TARGET_OS_SIMULATOR == 1;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.row == 0) {
|
||||
if (self.isSimulator) {
|
||||
NSString *result = @"127.0.0.1";
|
||||
[[DoricDriver instance] connectDevKit:[NSString stringWithFormat:@"ws://%@:7777", result]];
|
||||
ShowToast([NSString stringWithFormat:@"Connected to %@", result], BOTTOM);
|
||||
} else {
|
||||
[self.navigationController pushViewController:[QRScanViewController new] animated:NO];
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSString *file = self.demoFilePaths[(NSUInteger) indexPath.row];
|
||||
if ([file containsString:@"NavigatorDemo"]) {
|
||||
DoricViewController *doricViewController = [[DoricViewController alloc]
|
||||
initWithScheme:[NSString stringWithFormat:@"assets://demo/%@", file]
|
||||
alias:self.demoFilePaths[(NSUInteger) indexPath.row]];
|
||||
[self.navigationController pushViewController:doricViewController animated:NO];
|
||||
} else {
|
||||
DemoVC *demoVC = [[DemoVC alloc] initWithPath:file];
|
||||
[self.navigationController pushViewController:demoVC animated:NO];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
1
doric-iOS/Example/Example/demo
Symbolic link
1
doric-iOS/Example/Example/demo
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../demo/bundle/src/
|
16
doric-iOS/Example/Example/main.m
Normal file
16
doric-iOS/Example/Example/main.m
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// main.m
|
||||
// Example
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
// Copyright © 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
37
doric-iOS/Example/ExampleTests/ExampleTests.m
Normal file
37
doric-iOS/Example/ExampleTests/ExampleTests.m
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// ExampleTests.m
|
||||
// ExampleTests
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
// Copyright © 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface ExampleTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation ExampleTests
|
||||
|
||||
- (void)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.
|
||||
}
|
||||
|
||||
- (void)testExample {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
- (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
|
22
doric-iOS/Example/ExampleTests/Info.plist
Normal file
22
doric-iOS/Example/ExampleTests/Info.plist
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
38
doric-iOS/Example/ExampleUITests/ExampleUITests.m
Normal file
38
doric-iOS/Example/ExampleUITests/ExampleUITests.m
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// ExampleUITests.m
|
||||
// ExampleUITests
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
// Copyright © 2019 pengfei.zhou. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface ExampleUITests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation ExampleUITests
|
||||
|
||||
- (void)setUp {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
|
||||
// In UI tests it is usually best to stop immediately when a failure occurs.
|
||||
self.continueAfterFailure = NO;
|
||||
|
||||
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
|
||||
[[[XCUIApplication alloc] init] launch];
|
||||
|
||||
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
- (void)testExample {
|
||||
// Use recording to get started writing UI tests.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
@end
|
22
doric-iOS/Example/ExampleUITests/Info.plist
Normal file
22
doric-iOS/Example/ExampleUITests/Info.plist
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
17
doric-iOS/Example/Podfile
Normal file
17
doric-iOS/Example/Podfile
Normal file
@@ -0,0 +1,17 @@
|
||||
# Uncomment the next line to define a global platform for your project
|
||||
# platform :ios, '9.0'
|
||||
|
||||
target 'Example' do
|
||||
|
||||
pod 'Doric', :path => '../'
|
||||
target 'ExampleTests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
target 'ExampleUITests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
end
|
201
doric-iOS/LICENSE
Normal file
201
doric-iOS/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [2019] [Doric.Pub]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
0
doric-iOS/Pod/Assets/.gitkeep
Normal file
0
doric-iOS/Pod/Assets/.gitkeep
Normal file
1
doric-iOS/Pod/Assets/bundle
Symbolic link
1
doric-iOS/Pod/Assets/bundle
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../js-framework/bundle
|
1
doric-iOS/Pod/Assets/dist
Symbolic link
1
doric-iOS/Pod/Assets/dist
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../debugger/dist
|
0
doric-iOS/Pod/Classes/.gitkeep
Normal file
0
doric-iOS/Pod/Classes/.gitkeep
Normal file
31
doric-iOS/Pod/Classes/Dev/DoricLocalServer.h
Normal file
31
doric-iOS/Pod/Classes/Dev/DoricLocalServer.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricLocalServer.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/8/14.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricLocalServer : NSObject
|
||||
- (void)startWithPort:(NSUInteger)port;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
130
doric-iOS/Pod/Classes/Dev/DoricLocalServer.m
Normal file
130
doric-iOS/Pod/Classes/Dev/DoricLocalServer.m
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricLocalServer.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/8/14.
|
||||
//
|
||||
|
||||
#import "DoricLocalServer.h"
|
||||
#import "GCDWebServer.h"
|
||||
#import "GCDWebServerDataResponse.h"
|
||||
#import "DoricUtil.h"
|
||||
#import "DoricContextManager.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
typedef id (^ServerHandler)(GCDWebServerRequest *request);
|
||||
|
||||
@interface DoricLocalServer ()
|
||||
@property(nonatomic, strong) GCDWebServer *server;
|
||||
@property(nonatomic, strong) NSMutableDictionary *handlers;
|
||||
@end
|
||||
|
||||
@implementation DoricLocalServer
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_server = [[GCDWebServer alloc] init];
|
||||
_handlers = [[NSMutableDictionary alloc] init];
|
||||
[self configurate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)localIPAddress {
|
||||
NSString *localIP = nil;
|
||||
struct ifaddrs *addrs;
|
||||
if (getifaddrs(&addrs) == 0) {
|
||||
const struct ifaddrs *cursor = addrs;
|
||||
while (cursor != NULL) {
|
||||
if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0) {
|
||||
//NSString *name = [NSString stringWithUTF8String:cursor->ifa_name];
|
||||
//if ([name isEqualToString:@"en0"]) // Wi-Fi adapter
|
||||
{
|
||||
localIP = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *) cursor->ifa_addr)->sin_addr)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor = cursor->ifa_next;
|
||||
}
|
||||
freeifaddrs(addrs);
|
||||
}
|
||||
return localIP;
|
||||
}
|
||||
|
||||
- (GCDWebServerResponse *)handleRequest:(GCDWebServerRequest *)request {
|
||||
if ([request.path hasPrefix:@"/api/"]) {
|
||||
NSString *command = [request.path substringFromIndex:@"/api/".length];
|
||||
ServerHandler handler = [self.handlers objectForKey:command];
|
||||
if (handler) {
|
||||
id dic = handler(request);
|
||||
return [GCDWebServerDataResponse responseWithJSONObject:dic];
|
||||
}
|
||||
return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>It's a API request.</p></body></html>"];
|
||||
}
|
||||
NSBundle *bundle = DoricBundle();
|
||||
NSString *filePath = [NSString stringWithFormat:@"%@/dist%@", bundle.bundlePath, request.path];
|
||||
NSData *data = [NSData dataWithContentsOfFile:filePath];
|
||||
NSURL *url = [NSURL fileURLWithPath:filePath];
|
||||
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
|
||||
NSHTTPURLResponse *response;
|
||||
[NSURLConnection sendSynchronousRequest:req returningResponse:&response error:nil];
|
||||
return [GCDWebServerDataResponse responseWithData:data contentType:response.MIMEType];
|
||||
}
|
||||
|
||||
- (void)configurate {
|
||||
__weak typeof(self) _self = self;
|
||||
[self.server addDefaultHandlerForMethod:@"GET"
|
||||
requestClass:[GCDWebServerRequest class]
|
||||
processBlock:^GCDWebServerResponse *(GCDWebServerRequest *request) {
|
||||
__strong typeof(_self) self = _self;
|
||||
return [self handleRequest:request];
|
||||
}];
|
||||
[self.handlers setObject:^id(GCDWebServerRequest *request) {
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
|
||||
for (NSValue *value in [[DoricContextManager instance] aliveContexts]) {
|
||||
DoricContext *context = value.nonretainedObjectValue;
|
||||
[array addObject:@{
|
||||
@"source": context.source,
|
||||
@"id": context.contextId,
|
||||
}];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
forKey:@"allContexts"];
|
||||
|
||||
[self.handlers setObject:^id(GCDWebServerRequest *request) {
|
||||
NSString *contextId = [request.query objectForKey:@"id"];
|
||||
DoricContext *context = [[DoricContextManager instance] getContext:contextId];
|
||||
return @{
|
||||
@"id": context.contextId,
|
||||
@"source": context.source,
|
||||
@"script": context.script
|
||||
};
|
||||
}
|
||||
forKey:@"context"];
|
||||
}
|
||||
|
||||
- (void)startWithPort:(NSUInteger)port {
|
||||
[self.server startWithPort:port bonjourName:nil];
|
||||
DoricLog(@"Start Server At %@:%d", [self localIPAddress], port);
|
||||
}
|
||||
@end
|
33
doric-iOS/Pod/Classes/Dev/DoricWSClient.h
Normal file
33
doric-iOS/Pod/Classes/Dev/DoricWSClient.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// WSClient.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/8/14.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricWSClient : NSObject
|
||||
- (instancetype)initWithUrl:(NSString *)url;
|
||||
|
||||
- (void)close;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
81
doric-iOS/Pod/Classes/Dev/DoricWSClient.m
Normal file
81
doric-iOS/Pod/Classes/Dev/DoricWSClient.m
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// WSClient.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/8/14.
|
||||
//
|
||||
|
||||
#import "DoricWSClient.h"
|
||||
#import <SocketRocket/SRWebSocket.h>
|
||||
#import "DoricUtil.h"
|
||||
#import "DoricContextManager.h"
|
||||
|
||||
@interface DoricWSClient () <SRWebSocketDelegate>
|
||||
@property(nonatomic, strong) SRWebSocket *websocket;
|
||||
@end
|
||||
|
||||
@implementation DoricWSClient
|
||||
- (instancetype)initWithUrl:(NSString *)url {
|
||||
if (self = [super init]) {
|
||||
_websocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:url]];
|
||||
_websocket.delegate = self;
|
||||
[_websocket open];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
|
||||
DoricLog(@"webSocketDidOpen");
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload {
|
||||
DoricLog(@"webSocketdidReceivePong");
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
|
||||
NSData *jsonData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSError *err;
|
||||
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:NSJSONReadingMutableContainers
|
||||
error:&err];
|
||||
if (err) {
|
||||
DoricLog(@"webSocketdidReceiveMessage parse error:%@", err);
|
||||
return;
|
||||
}
|
||||
NSString *source = [[dic valueForKey:@"source"] mutableCopy];
|
||||
NSString *script = [dic valueForKey:@"script"];
|
||||
for (NSValue *value in [[DoricContextManager instance] aliveContexts]) {
|
||||
DoricContext *context = value.nonretainedObjectValue;
|
||||
if ([source containsString:context.source]) {
|
||||
[context reload:script];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
|
||||
DoricLog(@"webSocketdidFailWithError");
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
|
||||
DoricLog(@"webSocketdidCloseWithCode");
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
[self.websocket close];
|
||||
}
|
||||
@end
|
28
doric-iOS/Pod/Classes/Doric.h
Normal file
28
doric-iOS/Pod/Classes/Doric.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#import "DoricContext.h"
|
||||
#import "DoricLayouts.h"
|
||||
#import "DoricExtensions.h"
|
||||
#import "DoricViewNode.h"
|
||||
#import "DoricRootNode.h"
|
||||
#import "UIView+Doric.h"
|
||||
#import "DoricUtil.h"
|
||||
#import "DoricPanel.h"
|
||||
#import "DoricJSLoaderManager.h"
|
||||
#import "DoricNavigatorDelegate.h"
|
||||
#import "DoricNavBarDelegate.h"
|
||||
#import "DoricViewController.h"
|
||||
#import "DoricPromise.h"
|
64
doric-iOS/Pod/Classes/DoricContext.h
Normal file
64
doric-iOS/Pod/Classes/DoricContext.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricContext.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricDriver.h"
|
||||
#import "DoricNavigatorDelegate.h"
|
||||
#import "DoricNavBarDelegate.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class DoricViewNode;
|
||||
@class DoricRootNode;
|
||||
|
||||
@interface DoricContext : NSObject
|
||||
@property(nonatomic, weak) id <DoricNavigatorDelegate> navigator;
|
||||
@property(nonatomic, weak) id <DoricNavBarDelegate> navBar;
|
||||
@property(nonatomic, strong) NSString *contextId;
|
||||
@property(nonatomic, strong) DoricDriver *driver;
|
||||
@property(nonatomic, strong) NSMutableDictionary *pluginInstanceMap;
|
||||
@property(nonatomic, strong) NSString *source;
|
||||
@property(nonatomic, strong) NSString *script;;
|
||||
@property(nonatomic, strong) NSMutableDictionary *initialParams;
|
||||
@property(nonatomic, strong) DoricRootNode *rootNode;
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSString *, DoricViewNode *> *headNodes;
|
||||
|
||||
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source;
|
||||
|
||||
- (DoricAsyncResult *)callEntity:(NSString *)method, ...;
|
||||
|
||||
- (DoricAsyncResult *)callEntity:(NSString *)method withArguments:(va_list)args;
|
||||
|
||||
- (DoricAsyncResult *)callEntity:(NSString *)method withArgumentsArray:(NSArray *)args;
|
||||
|
||||
- (void)initContextWithWidth:(CGFloat)width height:(CGFloat)height;
|
||||
|
||||
- (void)reload:(NSString *)script;
|
||||
|
||||
- (void)onShow;
|
||||
|
||||
- (void)onHidden;
|
||||
|
||||
- (DoricViewNode *)targetViewNode:(NSString *)viewId;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
99
doric-iOS/Pod/Classes/DoricContext.m
Normal file
99
doric-iOS/Pod/Classes/DoricContext.m
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricContext.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
//
|
||||
|
||||
#import "DoricContext.h"
|
||||
#import "DoricContextManager.h"
|
||||
#import "DoricRootNode.h"
|
||||
#import "DoricConstant.h"
|
||||
#import "DoricExtensions.h"
|
||||
|
||||
@implementation DoricContext
|
||||
|
||||
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source {
|
||||
if (self = [super init]) {
|
||||
_driver = [DoricDriver instance];
|
||||
_pluginInstanceMap = [NSMutableDictionary new];
|
||||
[[DoricContextManager instance] createContext:self script:script source:source];
|
||||
_headNodes = [NSMutableDictionary new];
|
||||
DoricRootNode *rootNode = [[DoricRootNode alloc] initWithContext:self];
|
||||
_rootNode = rootNode;
|
||||
_script = script;
|
||||
_source = source;
|
||||
_initialParams = [@{@"width": @(0), @"height": @(0)} mutableCopy];
|
||||
[self callEntity:DORIC_ENTITY_CREATE, nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (DoricViewNode *)targetViewNode:(NSString *)viewId {
|
||||
if ([self.rootNode.viewId isEqualToString:viewId]) {
|
||||
return self.rootNode;
|
||||
} else {
|
||||
return self.headNodes[viewId];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self callEntity:DORIC_ENTITY_DESTROY, nil];
|
||||
[[DoricContextManager instance] destroyContext:self];
|
||||
}
|
||||
|
||||
- (DoricAsyncResult *)callEntity:(NSString *)method, ... {
|
||||
va_list args;
|
||||
va_start(args, method);
|
||||
DoricAsyncResult *ret = [self.driver invokeContextEntity:self.contextId method:method arguments:args];
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult *)callEntity:(NSString *)method withArguments:(va_list)args {
|
||||
return [self.driver invokeContextEntity:self.contextId method:method arguments:args];
|
||||
}
|
||||
|
||||
- (DoricAsyncResult *)callEntity:(NSString *)method withArgumentsArray:(NSArray *)args {
|
||||
return [self.driver invokeContextEntity:self.contextId method:method argumentsArray:args];
|
||||
}
|
||||
|
||||
- (void)initContextWithWidth:(CGFloat)width height:(CGFloat)height {
|
||||
[self.initialParams also:^(NSMutableDictionary *it) {
|
||||
it[@"width"] = @(width);
|
||||
it[@"height"] = @(height);
|
||||
}];
|
||||
[self callEntity:DORIC_ENTITY_INIT, self.initialParams, nil];
|
||||
}
|
||||
|
||||
- (void)reload:(NSString *)script {
|
||||
self.rootNode.viewId = nil;
|
||||
self.script = script;
|
||||
[self.driver createContext:self.contextId script:script source:self.source];
|
||||
[self callEntity:DORIC_ENTITY_INIT, self.initialParams, nil];
|
||||
}
|
||||
|
||||
- (void)onShow {
|
||||
[self callEntity:DORIC_ENTITY_SHOW, nil];
|
||||
}
|
||||
|
||||
- (void)onHidden {
|
||||
[self callEntity:DORIC_ENTITY_HIDDEN, nil];
|
||||
}
|
||||
|
||||
@end
|
35
doric-iOS/Pod/Classes/DoricContextHolder.h
Normal file
35
doric-iOS/Pod/Classes/DoricContextHolder.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricComponent.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricContext.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricContextHolder : NSObject
|
||||
@property(nonatomic, strong) DoricContext *doricContext;
|
||||
|
||||
- (instancetype)initWithContext:(DoricContext *)doricContext;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
34
doric-iOS/Pod/Classes/DoricContextHolder.m
Normal file
34
doric-iOS/Pod/Classes/DoricContextHolder.m
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricComponent.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import "DoricContextHolder.h"
|
||||
|
||||
@implementation DoricContextHolder
|
||||
|
||||
- (instancetype)initWithContext:(DoricContext *)doricContext {
|
||||
if (self = [self init]) {
|
||||
_doricContext = doricContext;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
40
doric-iOS/Pod/Classes/DoricContextManager.h
Normal file
40
doric-iOS/Pod/Classes/DoricContextManager.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricContextManager.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricContext.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricContextManager : NSObject
|
||||
+ (instancetype)instance;
|
||||
|
||||
- (void)createContext:(DoricContext *)context script:(NSString *)script source:(NSString *)source;
|
||||
|
||||
- (void)destroyContext:(DoricContext *)context;
|
||||
|
||||
- (DoricContext *)getContext:(NSString *)contextId;
|
||||
|
||||
- (NSArray *)aliveContexts;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
84
doric-iOS/Pod/Classes/DoricContextManager.m
Normal file
84
doric-iOS/Pod/Classes/DoricContextManager.m
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricContextManager.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import "DoricContextManager.h"
|
||||
#import "DoricContext.h"
|
||||
|
||||
@interface DoricContextManager ()
|
||||
|
||||
@property(nonatomic) NSInteger counter;
|
||||
@property(nonatomic, strong) NSMutableDictionary *doricContextMap;
|
||||
@property(nonatomic, strong) dispatch_queue_t mapQueue;
|
||||
@end
|
||||
|
||||
@implementation DoricContextManager
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_doricContextMap = [[NSMutableDictionary alloc] init];
|
||||
_counter = 0;
|
||||
_mapQueue = dispatch_queue_create("doric.contextmap", DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)instance {
|
||||
static DoricContextManager *_instance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
_instance = [[DoricContextManager alloc] init];
|
||||
});
|
||||
return _instance;
|
||||
}
|
||||
|
||||
- (void)createContext:(DoricContext *)context script:(NSString *)script source:(NSString *)source {
|
||||
context.contextId = [NSString stringWithFormat:@"%ld", (long) ++self.counter];
|
||||
[context.driver createContext:context.contextId script:script source:source];
|
||||
dispatch_sync(self.mapQueue, ^() {
|
||||
NSValue *value = [NSValue valueWithNonretainedObject:context];
|
||||
[self.doricContextMap setValue:value forKey:context.contextId];
|
||||
});
|
||||
}
|
||||
|
||||
- (DoricContext *)getContext:(NSString *)contextId {
|
||||
__block DoricContext *context;
|
||||
dispatch_sync(self.mapQueue, ^{
|
||||
NSValue *value = [self.doricContextMap valueForKey:contextId];
|
||||
context = value.nonretainedObjectValue;
|
||||
});
|
||||
return context;
|
||||
}
|
||||
|
||||
- (void)destroyContext:(DoricContext *)context {
|
||||
NSString *contextId = context.contextId;
|
||||
[context.driver destroyContext:contextId].finishCallback = ^{
|
||||
dispatch_sync(self.mapQueue, ^() {
|
||||
[self.doricContextMap removeObjectForKey:contextId];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
- (NSArray *)aliveContexts {
|
||||
return [self.doricContextMap allValues];
|
||||
}
|
||||
|
||||
@end
|
59
doric-iOS/Pod/Classes/DoricDriver.h
Normal file
59
doric-iOS/Pod/Classes/DoricDriver.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricDriver.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/26.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricAsyncResult.h"
|
||||
#import "DoricRegistry.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, QueueMode) {
|
||||
JS = 0,
|
||||
UI,
|
||||
INDEPENDENT
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricDriver : NSObject
|
||||
+ (instancetype)instance;
|
||||
|
||||
@property(nonatomic, strong) DoricRegistry *registry;
|
||||
|
||||
- (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source;
|
||||
|
||||
- (DoricAsyncResult *)destroyContext:(NSString *)contextId;
|
||||
|
||||
- (DoricAsyncResult *)invokeDoricMethod:(NSString *)method, ...;
|
||||
|
||||
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method, ...;
|
||||
|
||||
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method arguments:(va_list)args;
|
||||
|
||||
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method argumentsArray:(NSArray *)args;
|
||||
|
||||
- (void)connectDevKit:(NSString *)url;
|
||||
|
||||
- (void)disconnectDevKit;
|
||||
|
||||
- (void)ensureSyncInMainQueue:(dispatch_block_t)block;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
193
doric-iOS/Pod/Classes/DoricDriver.m
Normal file
193
doric-iOS/Pod/Classes/DoricDriver.m
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricDriver.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/26.
|
||||
//
|
||||
|
||||
#import "DoricDriver.h"
|
||||
#import "DoricJSEngine.h"
|
||||
#import "DoricConstant.h"
|
||||
#import "DoricWSClient.h"
|
||||
|
||||
@interface DoricDriver ()
|
||||
@property(nonatomic, strong) DoricJSEngine *jsExecutor;
|
||||
@property(nonatomic, strong) DoricWSClient *wsclient;
|
||||
@end
|
||||
|
||||
@implementation DoricDriver
|
||||
|
||||
@dynamic registry;
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_jsExecutor = [[DoricJSEngine alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (DoricRegistry *)registry {
|
||||
return self.jsExecutor.registry;
|
||||
}
|
||||
|
||||
+ (instancetype)instance {
|
||||
static DoricDriver *_instance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
_instance = [[DoricDriver alloc] init];
|
||||
});
|
||||
return _instance;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult<JSValue *> *)invokeDoricMethod:(NSString *)method, ... {
|
||||
va_list args;
|
||||
va_start(args, method);
|
||||
DoricAsyncResult *ret = [self invokeDoricMethod:method arguments:args];
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult<JSValue *> *)invokeDoricMethod:(NSString *)method arguments:(va_list)args {
|
||||
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
id arg;
|
||||
while ((arg = va_arg(args, id)) != nil) {
|
||||
[array addObject:arg];
|
||||
}
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_async(self.jsExecutor.jsQueue, ^() {
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return;
|
||||
@try {
|
||||
JSValue *jsValue = [self.jsExecutor invokeDoricMethod:method argumentsArray:array];
|
||||
[ret setupResult:jsValue];
|
||||
} @catch (NSException *exception) {
|
||||
[ret setupError:exception];
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult<JSValue *> *)invokeContextEntity:(NSString *)contextId method:(NSString *)method, ... {
|
||||
va_list args;
|
||||
va_start(args, method);
|
||||
DoricAsyncResult *ret = [self invokeContextEntity:contextId method:method arguments:args];
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method arguments:(va_list)args {
|
||||
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
[array addObject:contextId];
|
||||
[array addObject:method];
|
||||
id arg = va_arg(args, id);
|
||||
while (arg != nil) {
|
||||
[array addObject:arg];
|
||||
arg = va_arg(args, JSValue *);
|
||||
}
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_async(self.jsExecutor.jsQueue, ^() {
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return;
|
||||
@try {
|
||||
JSValue *jsValue = [self.jsExecutor invokeDoricMethod:DORIC_CONTEXT_INVOKE argumentsArray:array];
|
||||
[ret setupResult:jsValue];
|
||||
} @catch (NSException *exception) {
|
||||
[ret setupError:exception];
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method argumentsArray:(NSArray *)args {
|
||||
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
[array addObject:contextId];
|
||||
[array addObject:method];
|
||||
for (id arg in args) {
|
||||
[array addObject:arg];
|
||||
}
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_async(self.jsExecutor.jsQueue, ^() {
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return;
|
||||
@try {
|
||||
JSValue *jsValue = [self.jsExecutor invokeDoricMethod:DORIC_CONTEXT_INVOKE argumentsArray:array];
|
||||
[ret setupResult:jsValue];
|
||||
} @catch (NSException *exception) {
|
||||
[ret setupError:exception];
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source {
|
||||
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_async(self.jsExecutor.jsQueue, ^() {
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return;
|
||||
@try {
|
||||
[self.jsExecutor prepareContext:contextId script:script source:source];
|
||||
[ret setupResult:[NSNumber numberWithBool:YES]];
|
||||
} @catch (NSException *exception) {
|
||||
[ret setupError:exception];
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (DoricAsyncResult *)destroyContext:(NSString *)contextId {
|
||||
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_async(self.jsExecutor.jsQueue, ^() {
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return;
|
||||
@try {
|
||||
[self.jsExecutor destroyContext:contextId];
|
||||
[ret setupResult:[NSNumber numberWithBool:YES]];
|
||||
} @catch (NSException *exception) {
|
||||
[ret setupError:exception];
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)connectDevKit:(NSString *)url {
|
||||
if (self.wsclient) {
|
||||
[self.wsclient close];
|
||||
}
|
||||
self.wsclient = [[DoricWSClient alloc] initWithUrl:url];
|
||||
}
|
||||
|
||||
- (void)disconnectDevKit {
|
||||
if (self.wsclient) {
|
||||
[self.wsclient close];
|
||||
self.wsclient = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)ensureSyncInMainQueue:(dispatch_block_t)block {
|
||||
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {
|
||||
block();
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), block);
|
||||
}
|
||||
}
|
||||
@end
|
29
doric-iOS/Pod/Classes/DoricPanel.h
Normal file
29
doric-iOS/Pod/Classes/DoricPanel.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "DoricContext.h"
|
||||
#import "DoricNavigatorDelegate.h"
|
||||
|
||||
@interface DoricPanel : UIViewController
|
||||
@property(nonatomic, strong) DoricContext *doricContext;
|
||||
|
||||
- (void)config:(NSString *)script alias:(NSString *)alias;
|
||||
@end
|
54
doric-iOS/Pod/Classes/DoricPanel.m
Normal file
54
doric-iOS/Pod/Classes/DoricPanel.m
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import "DoricPanel.h"
|
||||
#import "Doric.h"
|
||||
|
||||
@implementation DoricPanel
|
||||
|
||||
- (void)config:(NSString *)script alias:(NSString *)alias {
|
||||
self.doricContext = [[[DoricContext alloc] initWithScript:script source:alias] also:^(DoricContext *it) {
|
||||
[it.rootNode setupRootView:[[DoricStackView new] also:^(DoricStackView *it) {
|
||||
[self.view addSubview:it];
|
||||
}]];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)viewWillLayoutSubviews {
|
||||
[super viewWillLayoutSubviews];
|
||||
[self.doricContext.rootNode.view also:^(DoricStackView *it) {
|
||||
if (it.width != self.view.width || it.height != self.view.height) {
|
||||
it.width = self.view.width;
|
||||
it.height = self.view.height;
|
||||
[self.doricContext initContextWithWidth:it.width height:it.height];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
[super viewDidAppear:animated];
|
||||
[self.doricContext onShow];
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear:(BOOL)animated {
|
||||
[super viewDidDisappear:animated];
|
||||
[self.doricContext onHidden];
|
||||
}
|
||||
|
||||
@end
|
43
doric-iOS/Pod/Classes/DoricRegistry.h
Normal file
43
doric-iOS/Pod/Classes/DoricRegistry.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricRegistry.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/27.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricRegistry : NSObject
|
||||
|
||||
- (NSString *)acquireJSBundle:(NSString *)name;
|
||||
|
||||
- (void)registerJSBundle:(NSString *)bundle withName:(NSString *)name;
|
||||
|
||||
|
||||
- (void)registerNativePlugin:(Class)pluginClass withName:(NSString *)name;
|
||||
|
||||
- (Class)acquireNativePlugin:(NSString *)name;
|
||||
|
||||
- (void)registerViewNode:(Class)nodeClass withName:(NSString *)name;
|
||||
|
||||
- (Class)acquireViewNode:(NSString *)name;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
115
doric-iOS/Pod/Classes/DoricRegistry.m
Normal file
115
doric-iOS/Pod/Classes/DoricRegistry.m
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricRegistry.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/27.
|
||||
//
|
||||
|
||||
#import "DoricRegistry.h"
|
||||
#import "DoricModalPlugin.h"
|
||||
#import "DoricNetworkPlugin.h"
|
||||
#import "DoricShaderPlugin.h"
|
||||
#import "DoricStackNode.h"
|
||||
#import "DoricVLayoutNode.h"
|
||||
#import "DoricHLayoutNode.h"
|
||||
#import "DoricTextNode.h"
|
||||
#import "DoricImageNode.h"
|
||||
#import "DoricListNode.h"
|
||||
#import "DoricListItemNode.h"
|
||||
#import "DoricScrollerNode.h"
|
||||
#import "DoricSliderNode.h"
|
||||
#import "DoricSlideItemNode.h"
|
||||
#import "DoricStoragePlugin.h"
|
||||
#import "DoricNavigatorPlugin.h"
|
||||
#import "DoricNavBarPlugin.h"
|
||||
#import "DoricRefreshableNode.h"
|
||||
#import "DoricFlowLayoutItemNode.h"
|
||||
#import "DoricFlowLayoutNode.h"
|
||||
#import "DoricPopoverPlugin.h"
|
||||
#import "DoricAnimatePlugin.h"
|
||||
|
||||
@interface DoricRegistry ()
|
||||
|
||||
@property(nonatomic, strong) NSMutableDictionary *bundles;
|
||||
@property(nonatomic, strong) NSMutableDictionary *plugins;
|
||||
@property(nonatomic, strong) NSMutableDictionary *nodes;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DoricRegistry
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_bundles = [[NSMutableDictionary alloc] init];
|
||||
_plugins = [[NSMutableDictionary alloc] init];
|
||||
_nodes = [[NSMutableDictionary alloc] init];
|
||||
[self innerRegister];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)innerRegister {
|
||||
[self registerNativePlugin:DoricShaderPlugin.class withName:@"shader"];
|
||||
[self registerNativePlugin:DoricModalPlugin.class withName:@"modal"];
|
||||
[self registerNativePlugin:DoricNetworkPlugin.class withName:@"network"];
|
||||
[self registerNativePlugin:DoricStoragePlugin.class withName:@"storage"];
|
||||
[self registerNativePlugin:DoricNavigatorPlugin.class withName:@"navigator"];
|
||||
[self registerNativePlugin:DoricNavBarPlugin.class withName:@"navbar"];
|
||||
[self registerNativePlugin:DoricPopoverPlugin.class withName:@"popover"];
|
||||
[self registerNativePlugin:DoricAnimatePlugin.class withName:@"animate"];
|
||||
|
||||
[self registerViewNode:DoricStackNode.class withName:@"Stack"];
|
||||
[self registerViewNode:DoricVLayoutNode.class withName:@"VLayout"];
|
||||
[self registerViewNode:DoricHLayoutNode.class withName:@"HLayout"];
|
||||
[self registerViewNode:DoricTextNode.class withName:@"Text"];
|
||||
[self registerViewNode:DoricImageNode.class withName:@"Image"];
|
||||
[self registerViewNode:DoricListNode.class withName:@"List"];
|
||||
[self registerViewNode:DoricListItemNode.class withName:@"ListItem"];
|
||||
[self registerViewNode:DoricScrollerNode.class withName:@"Scroller"];
|
||||
[self registerViewNode:DoricSliderNode.class withName:@"Slider"];
|
||||
[self registerViewNode:DoricSlideItemNode.class withName:@"SlideItem"];
|
||||
[self registerViewNode:DoricRefreshableNode.class withName:@"Refreshable"];
|
||||
[self registerViewNode:DoricFlowLayoutItemNode.class withName:@"FlowLayoutItem"];
|
||||
[self registerViewNode:DoricFlowLayoutNode.class withName:@"FlowLayout"];
|
||||
}
|
||||
|
||||
- (void)registerJSBundle:(NSString *)bundle withName:(NSString *)name {
|
||||
self.bundles[name] = bundle;
|
||||
}
|
||||
|
||||
- (NSString *)acquireJSBundle:(NSString *)name {
|
||||
return self.bundles[name];
|
||||
}
|
||||
|
||||
- (void)registerNativePlugin:(Class)pluginClass withName:(NSString *)name {
|
||||
self.plugins[name] = pluginClass;
|
||||
}
|
||||
|
||||
- (Class)acquireNativePlugin:(NSString *)name {
|
||||
return self.plugins[name];
|
||||
}
|
||||
|
||||
- (void)registerViewNode:(Class)nodeClass withName:(NSString *)name {
|
||||
self.nodes[name] = nodeClass;
|
||||
}
|
||||
|
||||
- (Class)acquireViewNode:(NSString *)name {
|
||||
return self.nodes[name];
|
||||
}
|
||||
|
||||
@end
|
26
doric-iOS/Pod/Classes/DoricViewController.h
Normal file
26
doric-iOS/Pod/Classes/DoricViewController.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricNavigatorDelegate.h"
|
||||
#import "DoricNavBarDelegate.h"
|
||||
|
||||
@interface DoricViewController : UIViewController <DoricNavigatorDelegate, DoricNavBarDelegate>
|
||||
- (instancetype)initWithScheme:(NSString *)scheme alias:(NSString *)alias;
|
||||
@end
|
107
doric-iOS/Pod/Classes/DoricViewController.m
Normal file
107
doric-iOS/Pod/Classes/DoricViewController.m
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import "DoricViewController.h"
|
||||
#import "DoricAsyncResult.h"
|
||||
#import "DoricJSLoaderManager.h"
|
||||
#import "DoricPanel.h"
|
||||
#import "UIView+Doric.h"
|
||||
#import "DoricExtensions.h"
|
||||
#import "DoricUtil.h"
|
||||
|
||||
@interface DoricViewController ()
|
||||
@property(nonatomic, strong) DoricPanel *doricPanel;
|
||||
@property(nonatomic) BOOL navBarHidden;
|
||||
@property(nonatomic, strong) UIImage *navBarImage;
|
||||
@end
|
||||
|
||||
@implementation DoricViewController
|
||||
- (instancetype)initWithScheme:(NSString *)scheme alias:(NSString *)alias {
|
||||
if (self = [super init]) {
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
DoricAsyncResult <NSString *> *result = [DoricJSLoaderManager.instance request:scheme];
|
||||
result.resultCallback = ^(NSString *result) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
DoricPanel *panel = [DoricPanel new];
|
||||
[panel.view also:^(UIView *it) {
|
||||
it.backgroundColor = [UIColor whiteColor];
|
||||
it.width = self.view.width;
|
||||
it.height = self.view.height;
|
||||
}];
|
||||
[self.view addSubview:panel.view];
|
||||
[self addChildViewController:panel];
|
||||
[panel config:result alias:alias];
|
||||
panel.doricContext.navigator = self;
|
||||
panel.doricContext.navBar = self;
|
||||
self.doricPanel = panel;
|
||||
});
|
||||
};
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
self.navBarHidden = self.navigationController.navigationBarHidden;
|
||||
self.navBarImage = [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
if (self.navigationController.navigationBarHidden != self.navBarHidden) {
|
||||
[self.navigationController setNavigationBarHidden:self.navBarHidden];
|
||||
}
|
||||
if (self.navBarImage != [self.navigationController.navigationBar backgroundImageForBarMetrics:UIBarMetricsDefault]) {
|
||||
[self.navigationController.navigationBar setBackgroundImage:self.navBarImage forBarMetrics:UIBarMetricsDefault];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillLayoutSubviews {
|
||||
[super viewWillLayoutSubviews];
|
||||
self.doricPanel.view.width = self.view.width;
|
||||
self.doricPanel.view.height = self.view.height;
|
||||
}
|
||||
|
||||
- (void)doric_navigator_push:(NSString *)scheme alias:(NSString *)alias animated:(BOOL)animated {
|
||||
DoricViewController *viewController = [[DoricViewController alloc] initWithScheme:scheme alias:alias];
|
||||
[self.navigationController pushViewController:viewController animated:animated];
|
||||
}
|
||||
|
||||
- (void)doric_navigator_pop:(BOOL)animated {
|
||||
[self.navigationController popViewControllerAnimated:animated];
|
||||
}
|
||||
|
||||
- (BOOL)doric_navBar_isHidden {
|
||||
return self.navigationController.navigationBarHidden;
|
||||
}
|
||||
|
||||
- (void)doric_navBar_setHidden:(BOOL)hidden {
|
||||
[self.navigationController setNavigationBarHidden:hidden];
|
||||
}
|
||||
|
||||
- (void)doric_navBar_setTitle:(NSString *)title {
|
||||
self.title = title;
|
||||
}
|
||||
|
||||
- (void)doric_navBar_setBackgroundColor:(UIColor *)color {
|
||||
[self.navigationController.navigationBar setBackgroundImage:UIImageWithColor(color) forBarMetrics:UIBarMetricsDefault];
|
||||
}
|
||||
|
||||
|
||||
@end
|
32
doric-iOS/Pod/Classes/Engine/DoricJSCoreExecutor.h
Normal file
32
doric-iOS/Pod/Classes/Engine/DoricJSCoreExecutor.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSCoreExecutor.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricJSExecutorProtocol.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricJSCoreExecutor : NSObject <DoricJSExecutorProtocol>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
64
doric-iOS/Pod/Classes/Engine/DoricJSCoreExecutor.m
Normal file
64
doric-iOS/Pod/Classes/Engine/DoricJSCoreExecutor.m
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSCoreExecutor.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
//
|
||||
|
||||
#import "DoricJSCoreExecutor.h"
|
||||
|
||||
@interface DoricJSCoreExecutor ()
|
||||
|
||||
@property(nonatomic, strong) JSContext *jsContext;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DoricJSCoreExecutor
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_jsContext = [[JSContext alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)checkJSException {
|
||||
if (self.jsContext.exception) {
|
||||
NSString *errMsg = [NSString stringWithFormat:@"%@ (line %@ in the generated bundle)\n/***StackTrace***/\n%@/***StackTrace***/", self.jsContext.exception, self.jsContext.exception[@"line"], self.jsContext.exception[@"stack"]];
|
||||
@throw [[NSException alloc] initWithName:@"DoricJS" reason:errMsg userInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)loadJSScript:(NSString *)script source:(NSString *)source {
|
||||
NSString *ret = [[self.jsContext evaluateScript:script withSourceURL:[NSURL URLWithString:source]] toString];
|
||||
[self checkJSException];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)injectGlobalJSObject:(NSString *)name obj:(id)obj {
|
||||
self.jsContext[name] = obj;
|
||||
[self checkJSException];
|
||||
}
|
||||
|
||||
- (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(NSArray *)args {
|
||||
JSValue *obj = [self.jsContext objectForKeyedSubscript:objName];
|
||||
JSValue *ret = [obj invokeMethod:funcName withArguments:args];
|
||||
[self checkJSException];
|
||||
return ret;
|
||||
}
|
||||
|
||||
@end
|
46
doric-iOS/Pod/Classes/Engine/DoricJSEngine.h
Normal file
46
doric-iOS/Pod/Classes/Engine/DoricJSEngine.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSEngine.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/26.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
#import "DoricRegistry.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricJSEngine : NSObject
|
||||
|
||||
@property(nonatomic, strong) dispatch_queue_t jsQueue;
|
||||
|
||||
@property(nonatomic, strong) DoricRegistry *registry;
|
||||
|
||||
- (void)prepareContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source;
|
||||
|
||||
- (void)destroyContext:(NSString *)contextId;
|
||||
|
||||
- (JSValue *)invokeDoricMethod:(NSString *)method, ...;
|
||||
|
||||
- (JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args;
|
||||
|
||||
- (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
181
doric-iOS/Pod/Classes/Engine/DoricJSEngine.m
Normal file
181
doric-iOS/Pod/Classes/Engine/DoricJSEngine.m
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSEngine.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/26.
|
||||
//
|
||||
|
||||
#import "DoricJSEngine.h"
|
||||
#import "DoricJSExecutorProtocol.h"
|
||||
#import "DoricJSCoreExecutor.h"
|
||||
#import "DoricJSRemoteExecutor.h"
|
||||
#import "DoricConstant.h"
|
||||
#import "DoricUtil.h"
|
||||
#import "DoricBridgeExtension.h"
|
||||
|
||||
@interface DoricJSEngine ()
|
||||
@property(nonatomic, strong) id <DoricJSExecutorProtocol> jsExecutor;
|
||||
@property(nonatomic, strong) NSMutableDictionary *timers;
|
||||
@property(nonatomic, strong) DoricBridgeExtension *bridgeExtension;
|
||||
@end
|
||||
|
||||
@implementation DoricJSEngine
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_jsQueue = dispatch_queue_create("doric.jsengine", DISPATCH_QUEUE_SERIAL);
|
||||
_bridgeExtension = [[DoricBridgeExtension alloc] init];
|
||||
dispatch_async(_jsQueue, ^() {
|
||||
self.timers = [[NSMutableDictionary alloc] init];
|
||||
// Debug: 切换
|
||||
// self.jsExecutor = [[DoricJSRemoteExecutor alloc] init];
|
||||
self.jsExecutor = [DoricJSCoreExecutor new];
|
||||
self.registry = [[DoricRegistry alloc] init];
|
||||
[self initJSExecutor];
|
||||
[self initDoricEnvironment];
|
||||
});
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)initJSExecutor {
|
||||
__weak typeof(self) _self = self;
|
||||
|
||||
[self.jsExecutor injectGlobalJSObject:INJECT_LOG obj:^(NSString *type, NSString *message) {
|
||||
DoricLog(@"JS:%@", message);
|
||||
}];
|
||||
[self.jsExecutor injectGlobalJSObject:INJECT_EMPTY obj:^() {
|
||||
|
||||
}];
|
||||
[self.jsExecutor injectGlobalJSObject:INJECT_REQUIRE obj:^(NSString *name) {
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return NO;
|
||||
NSString *content = [self.registry acquireJSBundle:name];
|
||||
if (!content) {
|
||||
DoricLog(@"require js bundle:%@ is empty", name);
|
||||
return NO;
|
||||
}
|
||||
@try {
|
||||
[self.jsExecutor loadJSScript:[self packageModuleScript:name content:content]
|
||||
source:[@"Module://" stringByAppendingString:name]];
|
||||
} @catch (NSException *e) {
|
||||
DoricLog(@"require js bundle:%@ error,for %@", name, e.reason);
|
||||
}
|
||||
return YES;
|
||||
}];
|
||||
[self.jsExecutor injectGlobalJSObject:INJECT_TIMER_SET
|
||||
obj:^(NSNumber *timerId, NSNumber *interval, NSNumber *isInterval) {
|
||||
__strong typeof(_self) self = _self;
|
||||
NSString *timerId_str = [timerId stringValue];
|
||||
BOOL repeat = [isInterval boolValue];
|
||||
NSTimer *timer = [NSTimer timerWithTimeInterval:[interval doubleValue] / 1000 target:self selector:@selector(callbackTimer:) userInfo:@{@"timerId": timerId, @"repeat": isInterval} repeats:repeat];
|
||||
[self.timers setValue:timer forKey:timerId_str];
|
||||
dispatch_async(dispatch_get_main_queue(), ^() {
|
||||
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
|
||||
});
|
||||
}];
|
||||
|
||||
[self.jsExecutor injectGlobalJSObject:INJECT_TIMER_CLEAR
|
||||
obj:^(NSString *timerId) {
|
||||
__strong typeof(_self) self = _self;
|
||||
NSTimer *timer = [self.timers valueForKey:timerId];
|
||||
if (timer) {
|
||||
[timer invalidate];
|
||||
[self.timers removeObjectForKey:timerId];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.jsExecutor injectGlobalJSObject:INJECT_BRIDGE obj:^(NSString *contextId, NSString *module, NSString *method, NSString *callbackId, id argument) {
|
||||
return [self.bridgeExtension callNativeWithContextId:contextId module:module method:method callbackId:callbackId argument:argument];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)initDoricEnvironment {
|
||||
[self loadBuiltinJS:DORIC_BUNDLE_SANDBOX];
|
||||
NSString *path = [DoricBundle() pathForResource:DORIC_BUNDLE_LIB ofType:@"js" inDirectory:@"bundle"];
|
||||
NSString *jsContent = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
|
||||
[self.jsExecutor loadJSScript:[self packageModuleScript:DORIC_MODULE_LIB content:jsContent]
|
||||
source:[@"Module://" stringByAppendingString:DORIC_MODULE_LIB]];
|
||||
}
|
||||
|
||||
- (void)loadBuiltinJS:(NSString *)fileName {
|
||||
NSString *path = [DoricBundle() pathForResource:DORIC_BUNDLE_SANDBOX ofType:@"js" inDirectory:@"bundle"];
|
||||
NSString *jsContent = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
|
||||
[self.jsExecutor loadJSScript:jsContent source:[@"Assets://" stringByAppendingString:fileName]];
|
||||
}
|
||||
|
||||
- (JSValue *)invokeDoricMethod:(NSString *)method, ... {
|
||||
va_list args;
|
||||
va_start(args, method);
|
||||
JSValue *ret = [self invokeDoricMethod:method arguments:args];
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args {
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
id arg = va_arg(args, id);
|
||||
while (arg != nil) {
|
||||
[array addObject:arg];
|
||||
arg = va_arg(args, JSValue *);
|
||||
}
|
||||
return [self.jsExecutor invokeObject:GLOBAL_DORIC method:method args:array];
|
||||
}
|
||||
|
||||
- (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args {
|
||||
return [self.jsExecutor invokeObject:GLOBAL_DORIC method:method args:args];
|
||||
}
|
||||
|
||||
- (NSString *)packageContextScript:(NSString *)contextId content:(NSString *)content {
|
||||
NSString *ret = [NSString stringWithFormat:TEMPLATE_CONTEXT_CREATE, content, contextId, contextId, contextId];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (NSString *)packageModuleScript:(NSString *)moduleName content:(NSString *)content {
|
||||
NSString *ret = [NSString stringWithFormat:TEMPLATE_MODULE, moduleName, content];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)prepareContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source {
|
||||
[self.jsExecutor loadJSScript:[self packageContextScript:contextId content:script]
|
||||
source:[@"Context://" stringByAppendingString:source]];
|
||||
}
|
||||
|
||||
- (void)destroyContext:(NSString *)contextId {
|
||||
[self.jsExecutor loadJSScript:[NSString stringWithFormat:TEMPLATE_CONTEXT_DESTROY, contextId]
|
||||
source:[@"_Context://" stringByAppendingString:contextId]];
|
||||
}
|
||||
|
||||
- (void)callbackTimer:(NSTimer *)timer {
|
||||
NSDictionary *userInfo = timer.userInfo;
|
||||
NSNumber *timerId = [userInfo valueForKey:@"timerId"];
|
||||
NSNumber *repeat = [userInfo valueForKey:@"repeat"];
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_async(self.jsQueue, ^() {
|
||||
__strong typeof(_self) self = _self;
|
||||
@try {
|
||||
[self invokeDoricMethod:DORIC_TIMER_CALLBACK, timerId, nil];
|
||||
} @catch (NSException *exception) {
|
||||
DoricLog(@"Timer Callback error:%@", exception.reason);
|
||||
}
|
||||
if (![repeat boolValue]) {
|
||||
[self.timers removeObjectForKey:[timerId stringValue]];
|
||||
}
|
||||
});
|
||||
}
|
||||
@end
|
38
doric-iOS/Pod/Classes/Engine/DoricJSExecutorProtocol.h
Normal file
38
doric-iOS/Pod/Classes/Engine/DoricJSExecutorProtocol.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSEngineProtocal.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/25.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol DoricJSExecutorProtocol <NSObject>
|
||||
|
||||
- (NSString *)loadJSScript:(NSString *)script source:(NSString *)source;
|
||||
|
||||
- (void)injectGlobalJSObject:(NSString *)name obj:(id)obj;
|
||||
|
||||
- (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(NSArray *)args;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
35
doric-iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.h
Normal file
35
doric-iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSRemoteExecutor.h
|
||||
// Pods
|
||||
//
|
||||
// Created by 王劲鹏 on 2019/10/31.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricJSExecutorProtocol.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricJSRemoteExecutor : NSObject <DoricJSExecutorProtocol>
|
||||
|
||||
@property(nonatomic, strong) dispatch_semaphore_t semaphore;
|
||||
|
||||
- (void)close;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
193
doric-iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.m
Normal file
193
doric-iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.m
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSRemoteExecutor.m
|
||||
// Doric
|
||||
//
|
||||
// Created by 王劲鹏 on 2019/10/31.
|
||||
//
|
||||
#import "DoricJSRemoteExecutor.h"
|
||||
#import <SocketRocket/SRWebSocket.h>
|
||||
#import "DoricUtil.h"
|
||||
#import "DoricJSRemoteArgType.h"
|
||||
#import "NSString+JsonString.h"
|
||||
|
||||
static NSString * const kUrlStr = @"ws://192.168.24.240:2080";
|
||||
|
||||
typedef id (^Block0)(void);
|
||||
typedef id (^Block1)(id arg0);
|
||||
typedef id (^Block2)(id arg0, id arg1);
|
||||
typedef id (^Block3)(id arg0, id arg1, id arg2);
|
||||
typedef id (^Block4)(id arg0, id arg1, id arg2, id arg3);
|
||||
typedef id (^Block5)(id arg0, id arg1, id arg2, id arg3, id arg4);
|
||||
|
||||
@interface DoricJSRemoteExecutor () <SRWebSocketDelegate>
|
||||
@property(nonatomic, strong) SRWebSocket *srWebSocket;
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSString *, id> *blockMDic;
|
||||
@property(nonatomic, strong) JSValue *temp;
|
||||
@end
|
||||
|
||||
@implementation DoricJSRemoteExecutor
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
[self srWebSocket];
|
||||
_semaphore = dispatch_semaphore_create(0);
|
||||
DC_LOCK(self.semaphore);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
|
||||
DoricLog(@"debugger webSocketDidOpen");
|
||||
DC_UNLOCK(self.semaphore);
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload {
|
||||
DoricLog(@"debugger webSocketdidReceivePong");
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
|
||||
NSData *jsonData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSError *err;
|
||||
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:NSJSONReadingMutableContainers
|
||||
error:&err];
|
||||
if (err) {
|
||||
DoricLog(@"debugger webSocketdidReceiveMessage parse error:%@", err);
|
||||
return;
|
||||
}
|
||||
NSString *cmd = [[dic valueForKey:@"cmd"] copy];
|
||||
|
||||
if ([cmd isEqualToString:@"injectGlobalJSFunction"]) {
|
||||
NSString *name = [dic valueForKey:@"name"];
|
||||
NSArray *argsArr = [dic valueForKey:@"arguments"];
|
||||
NSMutableArray *argsMarr = [NSMutableArray new];
|
||||
for (NSUInteger i = 0; i < argsArr.count; i++) {
|
||||
[argsMarr addObject:argsArr[i]];
|
||||
}
|
||||
|
||||
id result;
|
||||
id tmpBlk = self.blockMDic[name];
|
||||
if (argsArr.count == 0) {
|
||||
result = ((Block0) tmpBlk)();
|
||||
} else if (argsArr.count == 1) {
|
||||
result = ((Block1) tmpBlk)(argsArr[0]);
|
||||
} else if (argsArr.count == 2) {
|
||||
result = ((Block2)tmpBlk)(argsArr[0], argsArr[1]);
|
||||
} else if (argsArr.count == 3) {
|
||||
result = ((Block3)tmpBlk)(argsArr[0], argsArr[1], argsArr[2]);
|
||||
} else if (argsArr.count == 4) {
|
||||
result = ((Block4)tmpBlk)(argsArr[0], argsArr[1], argsArr[2], argsArr[3]);
|
||||
} else if (argsArr.count == 5) {
|
||||
result = ((Block5)tmpBlk)(argsArr[0], argsArr[1], argsArr[2], argsArr[3], argsArr[4]);
|
||||
}
|
||||
|
||||
} else if ([cmd isEqualToString:@"invokeMethod"]) {
|
||||
@try {
|
||||
self.temp = [JSValue valueWithObject:[dic valueForKey:@"result"] inContext:nil];
|
||||
} @catch (NSException *exception) {
|
||||
DoricLog(@"debugger ", NSStringFromSelector(_cmd), exception.reason);
|
||||
} @finally {
|
||||
DC_UNLOCK(self.semaphore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error {
|
||||
DoricLog(@"debugger webSocketdidFailWithError");
|
||||
DC_UNLOCK(self.semaphore);
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
|
||||
DoricLog(@"debugger webSocketdidCloseWithCode");
|
||||
}
|
||||
|
||||
- (NSString *)loadJSScript:(NSString *)script source:(NSString *)source {
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)injectGlobalJSObject:(NSString *)name obj:(id)obj {
|
||||
if ([obj isKindOfClass:NSClassFromString(@"NSBlock")]) {
|
||||
self.blockMDic[name] = obj;
|
||||
}
|
||||
NSDictionary *jsonDic = @{
|
||||
@"cmd": @"injectGlobalJSFunction",
|
||||
@"name": name
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
if (!jsonStr) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.srWebSocket send:jsonStr];
|
||||
}
|
||||
|
||||
- (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(NSArray *)args {
|
||||
|
||||
NSMutableArray *argsMArr = [NSMutableArray new];
|
||||
for (id arg in args) {
|
||||
NSDictionary *dic = @{
|
||||
@"type": @(DoricargTypeWithArg(arg)),
|
||||
@"value": arg
|
||||
};
|
||||
[argsMArr addObject:dic];
|
||||
}
|
||||
|
||||
NSArray *argsArr = [argsMArr copy];
|
||||
|
||||
NSDictionary *jsonDic = @{
|
||||
@"cmd": @"invokeMethod",
|
||||
@"objectName": objName,
|
||||
@"functionName": funcName,
|
||||
@"javaValues": argsArr
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
if (!jsonStr) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
[self.srWebSocket send:jsonStr];
|
||||
DC_LOCK(self.semaphore);
|
||||
|
||||
return self.temp;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
[self.srWebSocket close];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
- (SRWebSocket *)srWebSocket {
|
||||
if (!_srWebSocket) {
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kUrlStr] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];
|
||||
_srWebSocket = [[SRWebSocket alloc] initWithURLRequest:request];
|
||||
_srWebSocket.delegate = self;
|
||||
[_srWebSocket open];
|
||||
}
|
||||
return _srWebSocket;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)blockMDic {
|
||||
if (!_blockMDic) {
|
||||
_blockMDic = [NSMutableDictionary new];
|
||||
}
|
||||
return _blockMDic;
|
||||
}
|
||||
|
||||
@end
|
31
doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.h
Normal file
31
doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricBridgeExtension.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricBridgeExtension : NSObject
|
||||
- (id)callNativeWithContextId:(NSString *)contextId module:(NSString *)module method:(NSString *)method callbackId:(NSString *)callbackId argument:(id)argument;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
120
doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.m
Normal file
120
doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.m
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricBridgeExtension.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import "DoricBridgeExtension.h"
|
||||
#import "DoricRegistry.h"
|
||||
#import "DoricContextManager.h"
|
||||
#import "DoricNativePlugin.h"
|
||||
#import "DoricUtil.h"
|
||||
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@implementation DoricBridgeExtension
|
||||
|
||||
- (id)callNativeWithContextId:(NSString *)contextId module:(NSString *)module method:(NSString *)method callbackId:(NSString *)callbackId argument:(id)argument {
|
||||
DoricContext *context = [[DoricContextManager instance] getContext:contextId];
|
||||
DoricRegistry *registry = context.driver.registry;
|
||||
Class pluginClass = [registry acquireNativePlugin:module];
|
||||
DoricNativePlugin *nativePlugin = context.pluginInstanceMap[module];
|
||||
if (nativePlugin == nil) {
|
||||
nativePlugin = [(DoricNativePlugin *) [pluginClass alloc] initWithContext:context];
|
||||
context.pluginInstanceMap[module] = nativePlugin;
|
||||
}
|
||||
|
||||
return [self findClass:pluginClass target:nativePlugin context:context method:method callbackId:callbackId argument:argument];
|
||||
}
|
||||
|
||||
- (id)createParamWithMethodName:(NSString *)method context:(DoricContext *)context callbackId:(NSString *)callbackId argument:(id)argument {
|
||||
if ([method isEqualToString:@"withPromise"]) {
|
||||
return [[DoricPromise alloc] initWithContext:context callbackId:callbackId];
|
||||
}
|
||||
return argument;
|
||||
}
|
||||
|
||||
- (id)findClass:(Class)clz target:(id)target context:(DoricContext *)context method:(NSString *)name callbackId:(NSString *)callbackId argument:(id)argument {
|
||||
unsigned int count;
|
||||
id ret = nil;
|
||||
Method *methods = class_copyMethodList(clz, &count);
|
||||
BOOL isFound = NO;
|
||||
for (int i = 0; i < count; i++) {
|
||||
NSString *methodName = [NSString stringWithCString:sel_getName(method_getName(methods[i])) encoding:NSUTF8StringEncoding];
|
||||
NSArray *array = [methodName componentsSeparatedByString:@":"];
|
||||
if (array && [array count] > 0) {
|
||||
if ([array[0] isEqualToString:name]) {
|
||||
isFound = YES;
|
||||
SEL selector = NSSelectorFromString(methodName);
|
||||
NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector];
|
||||
if (methodSignature) {
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
||||
invocation.selector = selector;
|
||||
invocation.target = target;
|
||||
__weak __typeof__(self) _self = self;
|
||||
dispatch_block_t block = ^() {
|
||||
__strong __typeof__(_self) self = _self;
|
||||
@try {
|
||||
for (NSUInteger idx = 2; idx < methodSignature.numberOfArguments; idx++) {
|
||||
if (idx - 2 > [array count]) {
|
||||
break;
|
||||
}
|
||||
id args = [self createParamWithMethodName:array[idx - 2] context:context callbackId:callbackId argument:argument];
|
||||
[invocation setArgument:&args atIndex:idx];
|
||||
}
|
||||
[invocation invoke];
|
||||
} @catch (NSException *exception) {
|
||||
DoricLog(@"CallNative Error:%@", exception.reason);
|
||||
}
|
||||
};
|
||||
|
||||
const char *retType = methodSignature.methodReturnType;
|
||||
if (!strcmp(retType, @encode(void))) {
|
||||
ret = nil;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block);
|
||||
} else if (!strcmp(retType, @encode(id))) {
|
||||
void *retValue;
|
||||
block();
|
||||
[invocation getReturnValue:&retValue];
|
||||
id returnValue = (__bridge id) retValue;
|
||||
ret = [JSValue valueWithObject:[returnValue copy] inContext:[JSContext currentContext]];
|
||||
} else {
|
||||
DoricLog(@"CallNative Error:%@", @"Must return object type");
|
||||
ret = nil;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (methods) {
|
||||
free(methods);
|
||||
}
|
||||
if (!isFound) {
|
||||
Class superclass = class_getSuperclass(clz);
|
||||
if (superclass && superclass != [NSObject class]) {
|
||||
return [self findClass:superclass target:target context:context method:name callbackId:callbackId argument:argument];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
@end
|
25
doric-iOS/Pod/Classes/Loader/DoricHttpJSLoader.h
Normal file
25
doric-iOS/Pod/Classes/Loader/DoricHttpJSLoader.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "DoricLoaderProtocol.h"
|
||||
|
||||
@interface DoricHttpJSLoader : NSObject <DoricLoaderProtocol>
|
||||
@end
|
45
doric-iOS/Pod/Classes/Loader/DoricHttpJSLoader.m
Normal file
45
doric-iOS/Pod/Classes/Loader/DoricHttpJSLoader.m
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import "DoricHttpJSLoader.h"
|
||||
|
||||
|
||||
@implementation DoricHttpJSLoader
|
||||
|
||||
- (BOOL)filter:(NSString *)scheme {
|
||||
return [scheme hasPrefix:@"http"];
|
||||
}
|
||||
|
||||
- (DoricAsyncResult <NSString *> *)request:(NSString *)scheme {
|
||||
DoricAsyncResult *ret = [DoricAsyncResult new];
|
||||
NSURL *URL = [NSURL URLWithString:scheme];
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
|
||||
[[[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]
|
||||
dataTaskWithRequest:request
|
||||
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||
if (!error) {
|
||||
NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
[ret setupResult:dataStr];
|
||||
} else {
|
||||
[ret setupError:[[NSException alloc] initWithName:@"DoricJSLoaderManager Exception" reason:error.description userInfo:nil]];
|
||||
}
|
||||
}] resume];
|
||||
return ret;
|
||||
}
|
||||
@end
|
33
doric-iOS/Pod/Classes/Loader/DoricJSLoaderManager.h
Normal file
33
doric-iOS/Pod/Classes/Loader/DoricJSLoaderManager.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSLoaderManager.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricLoaderProtocol.h"
|
||||
#import "DoricAsyncResult.h"
|
||||
|
||||
@interface DoricJSLoaderManager : NSObject
|
||||
+ (instancetype)instance;
|
||||
|
||||
- (void)addJSLoader:(id <DoricLoaderProtocol>)loader;
|
||||
|
||||
- (DoricAsyncResult <NSString *> *)request:(NSString *)scheme;
|
||||
@end
|
68
doric-iOS/Pod/Classes/Loader/DoricJSLoaderManager.m
Normal file
68
doric-iOS/Pod/Classes/Loader/DoricJSLoaderManager.m
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSLoaderManager.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import "DoricJSLoaderManager.h"
|
||||
#import "DoricMainBundleJSLoader.h"
|
||||
#import "DoricHttpJSLoader.h"
|
||||
#import "Doric.h"
|
||||
|
||||
@interface DoricJSLoaderManager ()
|
||||
@property(nonatomic, copy) NSSet <id <DoricLoaderProtocol>> *loaders;
|
||||
@end
|
||||
|
||||
@implementation DoricJSLoaderManager
|
||||
+ (instancetype)instance {
|
||||
static DoricJSLoaderManager *_instance;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
_instance = [DoricJSLoaderManager new];
|
||||
});
|
||||
return _instance;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_loaders = [[NSSet alloc] initWithArray:@[
|
||||
[DoricMainBundleJSLoader new],
|
||||
[DoricHttpJSLoader new],
|
||||
]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addJSLoader:(id <DoricLoaderProtocol>)loader {
|
||||
self.loaders = [[self.loaders mutableCopy] also:^(NSMutableSet *it) {
|
||||
[it addObject:loader];
|
||||
}];
|
||||
}
|
||||
|
||||
- (DoricAsyncResult <NSString *> *)request:(NSString *)scheme {
|
||||
__block DoricAsyncResult *ret;
|
||||
[self.loaders enumerateObjectsUsingBlock:^(id <DoricLoaderProtocol> obj, BOOL *stop) {
|
||||
if ([obj filter:scheme]) {
|
||||
ret = [obj request:scheme];
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
return ret;
|
||||
}
|
||||
@end
|
27
doric-iOS/Pod/Classes/Loader/DoricLoaderProtocol.h
Normal file
27
doric-iOS/Pod/Classes/Loader/DoricLoaderProtocol.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricAsyncResult.h"
|
||||
|
||||
@protocol DoricLoaderProtocol <NSObject>
|
||||
- (BOOL)filter:(NSString *)scheme;
|
||||
|
||||
- (DoricAsyncResult <NSString *> *)request:(NSString *)scheme;
|
||||
@end
|
25
doric-iOS/Pod/Classes/Loader/DoricMainBundleJSLoader.h
Normal file
25
doric-iOS/Pod/Classes/Loader/DoricMainBundleJSLoader.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "DoricLoaderProtocol.h"
|
||||
|
||||
@interface DoricMainBundleJSLoader : NSObject <DoricLoaderProtocol>
|
||||
@end
|
42
doric-iOS/Pod/Classes/Loader/DoricMainBundleJSLoader.m
Normal file
42
doric-iOS/Pod/Classes/Loader/DoricMainBundleJSLoader.m
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import "DoricMainBundleJSLoader.h"
|
||||
|
||||
|
||||
@implementation DoricMainBundleJSLoader
|
||||
- (BOOL)filter:(NSString *)scheme {
|
||||
return [scheme hasPrefix:@"assets"];
|
||||
}
|
||||
|
||||
- (DoricAsyncResult <NSString *> *)request:(NSString *)scheme {
|
||||
DoricAsyncResult <NSString *> *ret = [DoricAsyncResult new];
|
||||
NSString *path = [[NSBundle mainBundle] bundlePath];
|
||||
NSString *fullPath = [path stringByAppendingPathComponent:[scheme substringFromIndex:@"assets://".length]];
|
||||
NSError *error;
|
||||
NSString *jsContent = [NSString stringWithContentsOfFile:fullPath encoding:NSUTF8StringEncoding error:&error];
|
||||
if (error) {
|
||||
[ret setupError:[NSException new]];
|
||||
} else {
|
||||
[ret setupResult:jsContent];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@end
|
31
doric-iOS/Pod/Classes/NavBar/DoricNavBarDelegate.h
Normal file
31
doric-iOS/Pod/Classes/NavBar/DoricNavBarDelegate.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/25.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@protocol DoricNavBarDelegate <NSObject>
|
||||
- (BOOL)doric_navBar_isHidden;
|
||||
|
||||
- (void)doric_navBar_setHidden:(BOOL)hidden;
|
||||
|
||||
- (void)doric_navBar_setTitle:(NSString *)title;
|
||||
|
||||
- (void)doric_navBar_setBackgroundColor:(UIColor *)color;
|
||||
@end
|
26
doric-iOS/Pod/Classes/Navigator/DoricNavigatorDelegate.h
Normal file
26
doric-iOS/Pod/Classes/Navigator/DoricNavigatorDelegate.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol DoricNavigatorDelegate <NSObject>
|
||||
- (void)doric_navigator_push:(NSString *)scheme alias:(NSString *)alias animated:(BOOL)animated;
|
||||
|
||||
- (void)doric_navigator_pop:(BOOL)animated;
|
||||
@end
|
10
doric-iOS/Pod/Classes/Plugin/DoricAnimatePlugin.h
Normal file
10
doric-iOS/Pod/Classes/Plugin/DoricAnimatePlugin.h
Normal file
@@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
@interface DoricAnimatePlugin : DoricNativePlugin
|
||||
@end
|
33
doric-iOS/Pod/Classes/Plugin/DoricAnimatePlugin.m
Normal file
33
doric-iOS/Pod/Classes/Plugin/DoricAnimatePlugin.m
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/29.
|
||||
//
|
||||
|
||||
#import "DoricAnimatePlugin.h"
|
||||
#import "DoricRootNode.h"
|
||||
|
||||
@implementation DoricAnimatePlugin
|
||||
|
||||
- (void)submit:(NSDictionary *)args withPromise:(DoricPromise *)promise {
|
||||
[promise resolve:nil];
|
||||
}
|
||||
|
||||
- (void)animateRender:(NSDictionary *)args withPromise:(DoricPromise *)promise {
|
||||
NSNumber *duration = args[@"duration"];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSString *viewId = args[@"id"];
|
||||
[UIView animateWithDuration:[duration floatValue] / 1000
|
||||
animations:^{
|
||||
if (self.doricContext.rootNode.viewId == nil) {
|
||||
self.doricContext.rootNode.viewId = viewId;
|
||||
[self.doricContext.rootNode blend:args[@"props"]];
|
||||
} else {
|
||||
DoricViewNode *viewNode = [self.doricContext targetViewNode:viewId];
|
||||
[viewNode blend:args[@"props"]];
|
||||
}
|
||||
}
|
||||
completion:^(BOOL finished) {
|
||||
[promise resolve:nil];
|
||||
}];
|
||||
});
|
||||
}
|
||||
@end
|
32
doric-iOS/Pod/Classes/Plugin/DoricModalPlugin.h
Normal file
32
doric-iOS/Pod/Classes/Plugin/DoricModalPlugin.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricModalPlugin.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricModalPlugin : DoricNativePlugin
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
115
doric-iOS/Pod/Classes/Plugin/DoricModalPlugin.m
Normal file
115
doric-iOS/Pod/Classes/Plugin/DoricModalPlugin.m
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricModalPlugin.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Doric/Doric.h>
|
||||
#import "DoricModalPlugin.h"
|
||||
#import "DoricUtil.h"
|
||||
|
||||
@implementation DoricModalPlugin
|
||||
|
||||
- (void)toast:(NSDictionary *)dic withPromise:(DoricPromise *)promise {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
__block DoricGravity gravity = BOTTOM;
|
||||
[dic[@"gravity"] also:^(NSNumber *it) {
|
||||
gravity = (DoricGravity) [it integerValue];
|
||||
}];
|
||||
ShowToast(dic[@"msg"], gravity);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)alert:(NSDictionary *)dic withPromise:(DoricPromise *)promise {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:dic[@"title"]
|
||||
message:dic[@"msg"]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *action = [UIAlertAction actionWithTitle:dic[@"okLabel"] ?: NSLocalizedString(@"OK", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
[promise resolve:nil];
|
||||
}];
|
||||
[alert addAction:action];
|
||||
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
|
||||
[vc presentViewController:alert animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)confirm:(NSDictionary *)dic withPromise:(DoricPromise *)promise {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:dic[@"title"]
|
||||
message:dic[@"msg"]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *okAction = [UIAlertAction actionWithTitle:dic[@"okLabel"] ?: NSLocalizedString(@"Ok", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
[promise resolve:nil];
|
||||
}];
|
||||
[alert addAction:okAction];
|
||||
|
||||
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:dic[@"cancelLabel"] ?: NSLocalizedString(@"Cancel", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
[promise reject:nil];
|
||||
}];
|
||||
[alert addAction:cancelAction];
|
||||
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
|
||||
[vc presentViewController:alert animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)prompt:(NSDictionary *)dic withPromise:(DoricPromise *)promise {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:dic[@"title"]
|
||||
message:dic[@"msg"]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
NSString *placeholder = dic[@"defaultText"];
|
||||
NSString *preText = dic[@"text"];
|
||||
[alert addTextFieldWithConfigurationHandler:^(UITextField *_Nonnull textField) {
|
||||
if (placeholder.length > 0) {
|
||||
textField.placeholder = placeholder;
|
||||
}
|
||||
if (preText.length > 0) {
|
||||
textField.text = preText;
|
||||
}
|
||||
}];
|
||||
__weak typeof(alert) _alert = alert;
|
||||
UIAlertAction *okAction = [UIAlertAction actionWithTitle:dic[@"okLabel"] ?: NSLocalizedString(@"Ok", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
__strong typeof(_alert) alert = _alert;
|
||||
[promise resolve:alert.textFields.lastObject.text];
|
||||
}];
|
||||
[alert addAction:okAction];
|
||||
|
||||
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:dic[@"cancelLabel"] ?: NSLocalizedString(@"Cancel", nil)
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
__strong typeof(_alert) alert = _alert;
|
||||
[promise reject:alert.textFields.lastObject.text];
|
||||
}];
|
||||
[alert addAction:cancelAction];
|
||||
|
||||
|
||||
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
|
||||
[vc presentViewController:alert animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
@end
|
34
doric-iOS/Pod/Classes/Plugin/DoricNativePlugin.h
Normal file
34
doric-iOS/Pod/Classes/Plugin/DoricNativePlugin.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricNativePlugin.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricContextHolder.h"
|
||||
#import "DoricPromise.h"
|
||||
#import "DoricRegistry.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricNativePlugin : DoricContextHolder
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
27
doric-iOS/Pod/Classes/Plugin/DoricNativePlugin.m
Normal file
27
doric-iOS/Pod/Classes/Plugin/DoricNativePlugin.m
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricNativePlugin.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
@implementation DoricNativePlugin
|
||||
|
||||
@end
|
26
doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.h
Normal file
26
doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/25.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
@interface DoricNavBarPlugin : DoricNativePlugin
|
||||
|
||||
@end
|
68
doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.m
Normal file
68
doric-iOS/Pod/Classes/Plugin/DoricNavBarPlugin.m
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/25.
|
||||
//
|
||||
|
||||
#import "DoricNavBarPlugin.h"
|
||||
#import "DoricUtil.h"
|
||||
|
||||
@implementation DoricNavBarPlugin
|
||||
- (void)isHidden:(NSDictionary *)param withPromise:(DoricPromise *)promise {
|
||||
if (self.doricContext.navBar) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[promise resolve:@([self.doricContext.navBar doric_navBar_isHidden])];
|
||||
});
|
||||
} else {
|
||||
[promise reject:@"Not implement NavBar"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setHidden:(NSDictionary *)param withPromise:(DoricPromise *)promise {
|
||||
if (self.doricContext.navBar) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.doricContext.navBar doric_navBar_setHidden:[param[@"hidden"] boolValue]];
|
||||
[promise resolve:nil];
|
||||
});
|
||||
} else {
|
||||
[promise reject:@"Not implement NavBar"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTitle:(NSDictionary *)param withPromise:(DoricPromise *)promise {
|
||||
if (self.doricContext.navBar) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.doricContext.navBar doric_navBar_setTitle:param[@"title"]];
|
||||
[promise resolve:nil];
|
||||
});
|
||||
} else {
|
||||
[promise reject:@"Not implement NavBar"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setBgColor:(NSDictionary *)param withPromise:(DoricPromise *)promise {
|
||||
if (self.doricContext.navBar) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIColor *color = DoricColor(param[@"color"]);
|
||||
[self.doricContext.navBar doric_navBar_setBackgroundColor:color];
|
||||
[promise resolve:nil];
|
||||
});
|
||||
} else {
|
||||
[promise reject:@"Not implement NavBar"];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
24
doric-iOS/Pod/Classes/Plugin/DoricNavigatorPlugin.h
Normal file
24
doric-iOS/Pod/Classes/Plugin/DoricNavigatorPlugin.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
@interface DoricNavigatorPlugin : DoricNativePlugin
|
||||
@end
|
43
doric-iOS/Pod/Classes/Plugin/DoricNavigatorPlugin.m
Normal file
43
doric-iOS/Pod/Classes/Plugin/DoricNavigatorPlugin.m
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/23.
|
||||
//
|
||||
|
||||
#import "DoricNavigatorPlugin.h"
|
||||
|
||||
|
||||
@implementation DoricNavigatorPlugin
|
||||
- (void)push:(NSDictionary *)params {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
BOOL animated = YES;
|
||||
if (params[@"animated"]) {
|
||||
animated = [params[@"animated"] boolValue];
|
||||
}
|
||||
[self.doricContext.navigator doric_navigator_push:params[@"scheme"] alias:params[@"alias"] animated:animated];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)pop:(NSDictionary *)params {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
BOOL animated = YES;
|
||||
if (params[@"animated"]) {
|
||||
animated = [params[@"animated"] boolValue];
|
||||
}
|
||||
[self.doricContext.navigator doric_navigator_pop:animated];
|
||||
});
|
||||
}
|
||||
@end
|
24
doric-iOS/Pod/Classes/Plugin/DoricNetworkPlugin.h
Normal file
24
doric-iOS/Pod/Classes/Plugin/DoricNetworkPlugin.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/21.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
@interface DoricNetworkPlugin : DoricNativePlugin
|
||||
@end
|
59
doric-iOS/Pod/Classes/Plugin/DoricNetworkPlugin.m
Normal file
59
doric-iOS/Pod/Classes/Plugin/DoricNetworkPlugin.m
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/21.
|
||||
//
|
||||
|
||||
#import "DoricNetworkPlugin.h"
|
||||
|
||||
|
||||
@implementation DoricNetworkPlugin
|
||||
- (void)request:(NSDictionary *)dic withPromise:(DoricPromise *)promise {
|
||||
NSString *url = dic[@"url"];
|
||||
NSString *method = dic[@"method"];
|
||||
NSDictionary <NSString *, NSString *> *headers = dic[@"headers"];
|
||||
NSNumber *timeout = dic[@"timeout"];
|
||||
NSString *data = dic[@"data"];
|
||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
|
||||
request.HTTPMethod = method.uppercaseString;
|
||||
if (timeout) {
|
||||
request.timeoutInterval = [timeout floatValue] / 1000;
|
||||
}
|
||||
if (headers) {
|
||||
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
|
||||
[request setValue:obj forHTTPHeaderField:key];
|
||||
}];
|
||||
}
|
||||
if (data) {
|
||||
[request setHTTPBody:[data dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
[[[NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]
|
||||
dataTaskWithRequest:request
|
||||
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||
if (!error) {
|
||||
NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
NSDictionary *resDic = @{
|
||||
@"status": @(((NSHTTPURLResponse *) response).statusCode),
|
||||
@"headers": ((NSHTTPURLResponse *) response).allHeaderFields,
|
||||
@"data": dataStr,
|
||||
};
|
||||
[promise resolve:resDic];
|
||||
} else {
|
||||
[promise reject:error.description];
|
||||
}
|
||||
}] resume];
|
||||
}
|
||||
@end
|
9
doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.h
Normal file
9
doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.h
Normal file
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/28.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
@interface DoricPopoverPlugin : DoricNativePlugin
|
||||
@end
|
70
doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.m
Normal file
70
doric-iOS/Pod/Classes/Plugin/DoricPopoverPlugin.m
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/28.
|
||||
//
|
||||
|
||||
#import "DoricPopoverPlugin.h"
|
||||
#import "DoricRootNode.h"
|
||||
#import "Doric.h"
|
||||
|
||||
@interface DoricPopoverPlugin ()
|
||||
@property(nonatomic, strong) UIView *fullScreenView;
|
||||
@end
|
||||
|
||||
@implementation DoricPopoverPlugin
|
||||
- (void)show:(NSDictionary *)params withPromise:(DoricPromise *)promise {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIView *superView = [UIApplication sharedApplication].windows.lastObject;
|
||||
if (!self.fullScreenView) {
|
||||
self.fullScreenView = [[DoricStackView new] also:^(UIView *it) {
|
||||
it.width = superView.width;
|
||||
it.height = superView.height;
|
||||
it.top = it.left = 0;
|
||||
[superView addSubview:it];
|
||||
}];
|
||||
}
|
||||
[superView bringSubviewToFront:self.fullScreenView];
|
||||
self.fullScreenView.hidden = NO;
|
||||
NSString *viewId = params[@"id"];
|
||||
NSString *type = params[@"type"];
|
||||
DoricViewNode *viewNode = [self.doricContext targetViewNode:viewId];
|
||||
if (!viewNode) {
|
||||
viewNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||
it.viewId = viewId;
|
||||
[it initWithSuperNode:nil];
|
||||
it.view.layoutConfig = [DoricLayoutConfig new];
|
||||
[self.fullScreenView addSubview:it.view];
|
||||
self.doricContext.headNodes[viewId] = it;
|
||||
}];
|
||||
}
|
||||
[viewNode blend:params[@"props"]];
|
||||
[promise resolve:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)dismiss:(NSDictionary *)params withPromise:(DoricPromise *)promise {
|
||||
NSString *viewId = params[@"id"];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (viewId) {
|
||||
DoricViewNode *viewNode = [self.doricContext targetViewNode:viewId];
|
||||
[self dismissViewNode:viewNode];
|
||||
} else {
|
||||
[self dismissPopover];
|
||||
}
|
||||
[promise resolve:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)dismissViewNode:(DoricViewNode *)node {
|
||||
[self.doricContext.headNodes removeObjectForKey:node.viewId];
|
||||
[node.view removeFromSuperview];
|
||||
if (self.doricContext.headNodes.count == 0) {
|
||||
self.fullScreenView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismissPopover {
|
||||
for (DoricViewNode *node in self.doricContext.headNodes.allValues) {
|
||||
[self dismissViewNode:node];
|
||||
}
|
||||
}
|
||||
@end
|
32
doric-iOS/Pod/Classes/Plugin/DoricPromise.h
Normal file
32
doric-iOS/Pod/Classes/Plugin/DoricPromise.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricPromise.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricContext.h"
|
||||
|
||||
@interface DoricPromise : NSObject
|
||||
- (instancetype)initWithContext:(DoricContext *)context callbackId:(NSString *)callbackId;
|
||||
|
||||
- (void)resolve:(id)result;
|
||||
|
||||
- (void)reject:(id)result;
|
||||
@end
|
49
doric-iOS/Pod/Classes/Plugin/DoricPromise.m
Normal file
49
doric-iOS/Pod/Classes/Plugin/DoricPromise.m
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricPromise.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import "DoricPromise.h"
|
||||
#import "DoricConstant.h"
|
||||
|
||||
@interface DoricPromise ()
|
||||
@property(nonatomic, strong) DoricContext *context;
|
||||
@property(nonatomic, strong) NSString *callbackId;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DoricPromise
|
||||
|
||||
- (instancetype)initWithContext:(DoricContext *)context callbackId:(NSString *)callbackId {
|
||||
if (self = [super init]) {
|
||||
_context = context;
|
||||
_callbackId = callbackId;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)resolve:(id)result {
|
||||
[self.context.driver invokeDoricMethod:DORIC_BRIDGE_RESOLVE, self.context.contextId, self.callbackId, result, nil];
|
||||
}
|
||||
|
||||
- (void)reject:(id)result {
|
||||
[self.context.driver invokeDoricMethod:DORIC_BRIDGE_REJECT, self.context.contextId, self.callbackId, result, nil];
|
||||
}
|
||||
@end
|
32
doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.h
Normal file
32
doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricShaderPlugin.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricShaderPlugin : DoricNativePlugin
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
143
doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.m
Normal file
143
doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.m
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricShaderPlugin.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/29.
|
||||
//
|
||||
|
||||
#import "DoricShaderPlugin.h"
|
||||
#import "DoricRootNode.h"
|
||||
#import "DoricUtil.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@implementation DoricShaderPlugin
|
||||
|
||||
- (void)render:(NSDictionary *)argument {
|
||||
if (!argument) {
|
||||
return;
|
||||
}
|
||||
__weak typeof(self) _self = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
__strong typeof(_self) self = _self;
|
||||
|
||||
NSString *viewId = argument[@"id"];
|
||||
|
||||
if (self.doricContext.rootNode.viewId == nil) {
|
||||
self.doricContext.rootNode.viewId = viewId;
|
||||
[self.doricContext.rootNode blend:argument[@"props"]];
|
||||
} else {
|
||||
DoricViewNode *viewNode = [self.doricContext targetViewNode:viewId];
|
||||
[viewNode blend:argument[@"props"]];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (id)command:(NSDictionary *)argument withPromise:(DoricPromise *)promise {
|
||||
NSArray *viewIds = argument[@"viewIds"];
|
||||
id args = argument[@"args"];
|
||||
NSString *name = argument[@"name"];
|
||||
DoricViewNode *viewNode = nil;
|
||||
for (NSString *viewId in viewIds) {
|
||||
if (!viewNode) {
|
||||
viewNode = [self.doricContext targetViewNode:viewId];
|
||||
} else {
|
||||
if ([viewNode isKindOfClass:[DoricSuperNode class]]) {
|
||||
viewNode = [((DoricSuperNode *) viewNode) subNodeWithViewId:viewId];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!viewNode) {
|
||||
[promise reject:@"Cannot find opposite view"];
|
||||
return nil;
|
||||
} else {
|
||||
return [self findClass:[viewNode class] target:viewNode method:name promise:promise argument:args];
|
||||
}
|
||||
}
|
||||
|
||||
- (id)createParamWithMethodName:(NSString *)method promise:(DoricPromise *)promise argument:(id)argument {
|
||||
if ([method isEqualToString:@"withPromise"]) {
|
||||
return promise;
|
||||
}
|
||||
return argument;
|
||||
}
|
||||
|
||||
- (id)findClass:(Class)clz target:(id)target method:(NSString *)name promise:(DoricPromise *)promise argument:(id)argument {
|
||||
unsigned int count;
|
||||
id ret = nil;
|
||||
Method *methods = class_copyMethodList(clz, &count);
|
||||
BOOL isFound = NO;
|
||||
for (int i = 0; i < count; i++) {
|
||||
NSString *methodName = [NSString stringWithCString:sel_getName(method_getName(methods[i])) encoding:NSUTF8StringEncoding];
|
||||
NSArray *array = [methodName componentsSeparatedByString:@":"];
|
||||
if (array && [array count] > 0) {
|
||||
if ([array[0] isEqualToString:name]) {
|
||||
isFound = YES;
|
||||
SEL selector = NSSelectorFromString(methodName);
|
||||
NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector];
|
||||
if (methodSignature) {
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
||||
invocation.selector = selector;
|
||||
invocation.target = target;
|
||||
__weak __typeof__(self) _self = self;
|
||||
dispatch_block_t block = ^() {
|
||||
__strong __typeof__(_self) self = _self;
|
||||
@try {
|
||||
for (NSUInteger idx = 2; idx < methodSignature.numberOfArguments; idx++) {
|
||||
if (idx - 2 > [array count]) {
|
||||
break;
|
||||
}
|
||||
id param = [self createParamWithMethodName:array[idx - 2] promise:promise argument:argument];
|
||||
[invocation setArgument:¶m atIndex:idx];
|
||||
}
|
||||
[invocation invoke];
|
||||
} @catch (NSException *exception) {
|
||||
DoricLog(@"CallNative Error:%@", exception.reason);
|
||||
}
|
||||
};
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
void *retValue;
|
||||
block();
|
||||
const char *retType = methodSignature.methodReturnType;
|
||||
if (!strcmp(retType, @encode(void))) {
|
||||
} else {
|
||||
[invocation getReturnValue:&retValue];
|
||||
id returnValue = (__bridge id) retValue;
|
||||
[promise resolve:returnValue];
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (methods) {
|
||||
free(methods);
|
||||
}
|
||||
if (!isFound) {
|
||||
Class superclass = class_getSuperclass(clz);
|
||||
if (superclass && superclass != [NSObject class]) {
|
||||
return [self findClass:superclass target:target method:name promise:promise argument:argument];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@end
|
24
doric-iOS/Pod/Classes/Plugin/DoricStoragePlugin.h
Normal file
24
doric-iOS/Pod/Classes/Plugin/DoricStoragePlugin.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/22.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricNativePlugin.h"
|
||||
|
||||
@interface DoricStoragePlugin : DoricNativePlugin
|
||||
@end
|
98
doric-iOS/Pod/Classes/Plugin/DoricStoragePlugin.m
Normal file
98
doric-iOS/Pod/Classes/Plugin/DoricStoragePlugin.m
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/22.
|
||||
//
|
||||
|
||||
#import "DoricStoragePlugin.h"
|
||||
#import "YYDiskCache.h"
|
||||
|
||||
static NSString *doric_prefix = @"pref";
|
||||
|
||||
@interface DoricStoragePlugin ()
|
||||
@property(atomic, strong) NSMutableDictionary <NSString *, YYDiskCache *> *cachedMap;
|
||||
@property(nonatomic, strong) YYDiskCache *defaultCache;
|
||||
@property(nonatomic, copy) NSString *basePath;
|
||||
@end
|
||||
|
||||
@implementation DoricStoragePlugin
|
||||
- (instancetype)initWithContext:(DoricContext *)doricContext {
|
||||
if (self = [super initWithContext:doricContext]) {
|
||||
_basePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
|
||||
stringByAppendingPathComponent:@"doric"];
|
||||
_cachedMap = [NSMutableDictionary new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (YYDiskCache *)defaultCache {
|
||||
if (!_defaultCache) {
|
||||
_defaultCache = [[YYDiskCache alloc] initWithPath:[self.basePath stringByAppendingPathComponent:doric_prefix]];
|
||||
}
|
||||
return _defaultCache;
|
||||
}
|
||||
|
||||
- (YYDiskCache *)getDiskCache:(NSString *)zone {
|
||||
YYDiskCache *diskCache;
|
||||
if (zone) {
|
||||
diskCache = self.cachedMap[zone];
|
||||
if (!diskCache) {
|
||||
diskCache = [[YYDiskCache alloc] initWithPath:[self.basePath
|
||||
stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@", doric_prefix, zone]]];
|
||||
self.cachedMap[zone] = diskCache;
|
||||
}
|
||||
} else {
|
||||
diskCache = self.defaultCache;
|
||||
}
|
||||
return diskCache;
|
||||
}
|
||||
|
||||
- (void)setItem:(NSDictionary *)argument withPromise:(DoricPromise *)promise {
|
||||
NSString *zone = argument[@"zone"];
|
||||
NSString *key = argument[@"key"];
|
||||
NSString *value = argument[@"value"];
|
||||
YYDiskCache *diskCache = [self getDiskCache:zone];
|
||||
[diskCache setObject:value forKey:key withBlock:^{
|
||||
[promise resolve:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)getItem:(NSDictionary *)argument withPromise:(DoricPromise *)promise {
|
||||
NSString *zone = argument[@"zone"];
|
||||
NSString *key = argument[@"key"];
|
||||
YYDiskCache *diskCache = [self getDiskCache:zone];
|
||||
[diskCache objectForKey:key withBlock:^(NSString *key, NSString *value) {
|
||||
[promise resolve:value];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)remove:(NSDictionary *)argument withPromise:(DoricPromise *)promise {
|
||||
NSString *zone = argument[@"zone"];
|
||||
NSString *key = argument[@"key"];
|
||||
YYDiskCache *diskCache = [self getDiskCache:zone];
|
||||
[diskCache removeObjectForKey:key withBlock:^(NSString *key) {
|
||||
[promise resolve:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)clear:(NSDictionary *)argument withPromise:(DoricPromise *)promise {
|
||||
NSString *zone = argument[@"zone"];
|
||||
YYDiskCache *diskCache = [self getDiskCache:zone];
|
||||
[diskCache removeAllObjectsWithBlock:^{
|
||||
[promise resolve:nil];
|
||||
}];
|
||||
}
|
||||
@end
|
25
doric-iOS/Pod/Classes/Refresh/DoricRefreshableNode.h
Normal file
25
doric-iOS/Pod/Classes/Refresh/DoricRefreshableNode.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/26.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricSuperNode.h"
|
||||
#import "DoricSwipeRefreshLayout.h"
|
||||
|
||||
@interface DoricRefreshableNode : DoricSuperNode<DoricSwipeRefreshLayout *>
|
||||
@end
|
176
doric-iOS/Pod/Classes/Refresh/DoricRefreshableNode.m
Normal file
176
doric-iOS/Pod/Classes/Refresh/DoricRefreshableNode.m
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/26.
|
||||
//
|
||||
|
||||
#import "DoricRefreshableNode.h"
|
||||
#import "Doric.h"
|
||||
|
||||
@interface DoricRefreshableNode () <DoricSwipePullingDelegate>
|
||||
@property(nonatomic, strong) DoricViewNode *contentNode;
|
||||
@property(nonatomic, copy) NSString *contentViewId;
|
||||
@property(nonatomic, strong) DoricViewNode *headerNode;
|
||||
@property(nonatomic, copy) NSString *headerViewId;
|
||||
@end
|
||||
|
||||
@implementation DoricRefreshableNode
|
||||
- (DoricSwipeRefreshLayout *)build {
|
||||
return [[DoricSwipeRefreshLayout new] also:^(DoricSwipeRefreshLayout *it) {
|
||||
it.swipePullingDelegate = self;
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)blendView:(DoricSwipeRefreshLayout *)view forPropName:(NSString *)name propValue:(id)prop {
|
||||
if ([@"content" isEqualToString:name]) {
|
||||
self.contentViewId = prop;
|
||||
} else if ([@"header" isEqualToString:name]) {
|
||||
self.headerViewId = prop;
|
||||
} else if ([@"onRefresh" isEqualToString:name]) {
|
||||
__weak typeof(self) _self = self;
|
||||
NSString *funcId = prop;
|
||||
self.view.onRefreshBlock = ^{
|
||||
__strong typeof(_self) self = _self;
|
||||
[self callJSResponse:funcId, nil];
|
||||
};
|
||||
} else {
|
||||
[super blendView:view forPropName:name propValue:prop];
|
||||
}
|
||||
}
|
||||
|
||||
- (DoricViewNode *)subNodeWithViewId:(NSString *)viewId {
|
||||
if ([viewId isEqualToString:self.contentViewId]) {
|
||||
return self.contentNode;
|
||||
} else if ([viewId isEqualToString:self.headerViewId]) {
|
||||
return self.headerNode;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)blend:(NSDictionary *)props {
|
||||
[super blend:props];
|
||||
[self blendContent];
|
||||
[self blendHeader];
|
||||
}
|
||||
|
||||
- (void)blendContent {
|
||||
NSDictionary *contentModel = [self subModelOf:self.contentViewId];
|
||||
if (!contentModel) {
|
||||
return;
|
||||
}
|
||||
NSString *viewId = contentModel[@"id"];
|
||||
NSString *type = contentModel[@"type"];
|
||||
NSDictionary *childProps = contentModel[@"props"];
|
||||
if (self.contentNode) {
|
||||
if ([self.contentNode.viewId isEqualToString:viewId]) {
|
||||
//skip
|
||||
} else {
|
||||
if (self.reusable && [type isEqualToString:self.contentNode.type]) {
|
||||
[self.contentNode also:^(DoricViewNode *it) {
|
||||
it.viewId = viewId;
|
||||
[it blend:childProps];
|
||||
}];
|
||||
} else {
|
||||
self.contentNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||
it.viewId = viewId;
|
||||
[it initWithSuperNode:self];
|
||||
[it blend:childProps];
|
||||
self.view.contentView = it.view;
|
||||
}];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.contentNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||
it.viewId = viewId;
|
||||
[it initWithSuperNode:self];
|
||||
[it blend:childProps];
|
||||
self.view.contentView = it.view;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)blendHeader {
|
||||
NSDictionary *headerModel = [self subModelOf:self.headerViewId];
|
||||
if (!headerModel) {
|
||||
return;
|
||||
}
|
||||
NSString *viewId = headerModel[@"id"];
|
||||
NSString *type = headerModel[@"type"];
|
||||
NSDictionary *childProps = headerModel[@"props"];
|
||||
if (self.headerNode) {
|
||||
if ([self.headerNode.viewId isEqualToString:viewId]) {
|
||||
//skip
|
||||
} else {
|
||||
if (self.reusable && [type isEqualToString:self.headerNode.type]) {
|
||||
[self.headerNode also:^(DoricViewNode *it) {
|
||||
it.viewId = viewId;
|
||||
[it blend:childProps];
|
||||
}];
|
||||
} else {
|
||||
self.headerNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||
it.viewId = viewId;
|
||||
[it initWithSuperNode:self];
|
||||
[it blend:childProps];
|
||||
self.view.headerView = it.view;
|
||||
}];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.headerNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
||||
it.viewId = viewId;
|
||||
[it initWithSuperNode:self];
|
||||
[it blend:childProps];
|
||||
self.view.headerView = it.view;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)blendSubNode:(NSDictionary *)subModel {
|
||||
[[self subNodeWithViewId:subModel[@"id"]] blend:subModel[@"props"]];
|
||||
}
|
||||
|
||||
- (void)startAnimation {
|
||||
[self.headerNode callJSResponse:@"startAnimation", nil];
|
||||
}
|
||||
|
||||
- (void)stopAnimation {
|
||||
[self.headerNode callJSResponse:@"stopAnimation", nil];
|
||||
}
|
||||
|
||||
- (void)setPullingDistance:(CGFloat)distance {
|
||||
[self.headerNode callJSResponse:@"setPullingDistance", @(distance), nil];
|
||||
}
|
||||
|
||||
- (void)setRefreshing:(NSNumber *)refreshable withPromise:(DoricPromise *)promise {
|
||||
self.view.refreshing = [refreshable boolValue];
|
||||
[promise resolve:nil];
|
||||
}
|
||||
|
||||
- (void)setRefreshable:(NSNumber *)refreshing withPromise:(DoricPromise *)promise {
|
||||
self.view.refreshable = [refreshing boolValue];
|
||||
[promise resolve:nil];
|
||||
}
|
||||
|
||||
- (NSNumber *)isRefreshing {
|
||||
return @(self.view.refreshing);
|
||||
}
|
||||
|
||||
- (NSNumber *)isRefreshable {
|
||||
return @(self.view.refreshable);
|
||||
}
|
||||
@end
|
22
doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.h
Normal file
22
doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/26.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol DoricSwipePullingDelegate <NSObject>
|
||||
- (void)startAnimation;
|
||||
|
||||
- (void)stopAnimation;
|
||||
|
||||
- (void)setPullingDistance:(CGFloat)rotation;
|
||||
@end
|
||||
|
||||
@interface DoricSwipeRefreshLayout : UIScrollView
|
||||
@property(nonatomic, strong) UIView *contentView;
|
||||
@property(nonatomic, strong) UIView *headerView;
|
||||
@property(nonatomic, assign) BOOL refreshable;
|
||||
@property(nonatomic, assign) BOOL refreshing;
|
||||
@property(nonatomic, strong) void (^onRefreshBlock)(void);
|
||||
@property(nonatomic, weak) id <DoricSwipePullingDelegate> swipePullingDelegate;
|
||||
@end
|
159
doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m
Normal file
159
doric-iOS/Pod/Classes/Refresh/DoricSwipeRefreshLayout.m
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/26.
|
||||
//
|
||||
|
||||
#import "DoricSwipeRefreshLayout.h"
|
||||
#import "UIView+Doric.h"
|
||||
#import "DoricLayouts.h"
|
||||
#import "Doric.h"
|
||||
|
||||
@interface DoricSwipeRefreshLayout () <UIScrollViewDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@implementation DoricSwipeRefreshLayout
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
self.showsHorizontalScrollIndicator = NO;
|
||||
self.showsVerticalScrollIndicator = NO;
|
||||
self.alwaysBounceVertical = YES;
|
||||
self.delegate = self;
|
||||
if (@available(iOS 11, *)) {
|
||||
self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
self.showsHorizontalScrollIndicator = NO;
|
||||
self.showsVerticalScrollIndicator = NO;
|
||||
self.alwaysBounceVertical = YES;
|
||||
self.delegate = self;
|
||||
if (@available(iOS 11, *)) {
|
||||
self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CGSize)sizeThatFits:(CGSize)size {
|
||||
if (self.contentView) {
|
||||
return [self.contentView measureSize:size];
|
||||
}
|
||||
return CGSizeZero;
|
||||
}
|
||||
|
||||
- (BOOL)requestFromSubview:(UIView *)subview {
|
||||
if (subview == self.headerView) {
|
||||
return NO;
|
||||
}
|
||||
return [super requestFromSubview:subview];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
}
|
||||
|
||||
- (void)layoutSelf:(CGSize)targetSize {
|
||||
if (self.contentOffset.y != 0) {
|
||||
return;
|
||||
}
|
||||
self.width = targetSize.width;
|
||||
self.height = targetSize.height;
|
||||
[self.headerView also:^(UIView *it) {
|
||||
[it layoutSelf:[it measureSize:targetSize]];
|
||||
it.bottom = 0;
|
||||
it.centerX = self.centerX;
|
||||
}];
|
||||
[self.contentView also:^(UIView *it) {
|
||||
[it layoutSelf:targetSize];
|
||||
}];
|
||||
self.contentSize = self.frame.size;
|
||||
}
|
||||
|
||||
- (void)setContentView:(UIView *)contentView {
|
||||
if (_contentView) {
|
||||
[_contentView removeFromSuperview];
|
||||
}
|
||||
_contentView = contentView;
|
||||
[self addSubview:contentView];
|
||||
}
|
||||
|
||||
- (void)setHeaderView:(UIView *)headerView {
|
||||
if (_headerView) {
|
||||
[_headerView removeFromSuperview];
|
||||
}
|
||||
_headerView = headerView;
|
||||
[self addSubview:headerView];
|
||||
self.refreshable = YES;
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
|
||||
if (-scrollView.contentOffset.y >= self.headerView.height) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self.refreshing = YES;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
||||
if (scrollView.contentOffset.y <= 0) {
|
||||
[self.swipePullingDelegate setPullingDistance:-scrollView.contentOffset.y];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setContentOffset:(CGPoint)contentOffset {
|
||||
[super setContentOffset:contentOffset];
|
||||
}
|
||||
|
||||
- (void)setRefreshing:(BOOL)refreshing {
|
||||
if (_refreshing == refreshing) {
|
||||
return;
|
||||
}
|
||||
if (refreshing) {
|
||||
[self setContentOffset:CGPointMake(0, -self.headerView.height) animated:YES];
|
||||
self.scrollEnabled = NO;
|
||||
if (self.onRefreshBlock) {
|
||||
self.onRefreshBlock();
|
||||
}
|
||||
} else {
|
||||
[self setContentOffset:(CGPoint) {0, 0} animated:YES];
|
||||
self.scrollEnabled = YES;
|
||||
}
|
||||
_refreshing = refreshing;
|
||||
}
|
||||
|
||||
- (void)setRefreshable:(BOOL)refreshable {
|
||||
self.scrollEnabled = refreshable;
|
||||
if (refreshable) {
|
||||
self.contentOffset = (CGPoint) {0, 0};
|
||||
self.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)refreshable {
|
||||
return self.scrollEnabled;
|
||||
}
|
||||
|
||||
- (void)setContentSize:(CGSize)contentSize {
|
||||
[super setContentSize:contentSize];
|
||||
}
|
||||
@end
|
25
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.h
Normal file
25
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/28.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricStackNode.h"
|
||||
|
||||
|
||||
@interface DoricFlowLayoutItemNode : DoricStackNode
|
||||
@end
|
48
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.m
Normal file
48
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutItemNode.m
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/28.
|
||||
//
|
||||
|
||||
#import "DoricFlowLayoutItemNode.h"
|
||||
|
||||
@interface DoricFlowLayoutItemView : DoricStackView
|
||||
@end
|
||||
|
||||
@implementation DoricFlowLayoutItemView
|
||||
@end
|
||||
|
||||
@interface DoricFlowLayoutItemNode ()
|
||||
@end
|
||||
|
||||
|
||||
@implementation DoricFlowLayoutItemNode
|
||||
- (instancetype)initWithContext:(DoricContext *)doricContext {
|
||||
if (self = [super initWithContext:doricContext]) {
|
||||
self.reusable = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)initWithSuperNode:(DoricSuperNode *)superNode {
|
||||
[super initWithSuperNode:superNode];
|
||||
self.reusable = YES;
|
||||
}
|
||||
|
||||
- (DoricStackView *)build {
|
||||
return [DoricFlowLayoutItemView new];
|
||||
}
|
||||
@end
|
24
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.h
Normal file
24
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/28.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricSuperNode.h"
|
||||
|
||||
@interface DoricFlowLayoutNode : DoricSuperNode<UICollectionView *>
|
||||
@end
|
322
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m
Normal file
322
doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/28.
|
||||
//
|
||||
|
||||
#import "DoricFlowLayoutNode.h"
|
||||
#import "DoricFlowLayoutItemNode.h"
|
||||
#import "DoricExtensions.h"
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
@protocol DoricFlowLayoutDelegate
|
||||
- (CGFloat)doricFlowLayoutItemHeightAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
- (CGFloat)doricFlowLayoutColumnSpace;
|
||||
|
||||
- (CGFloat)doricFlowLayoutRowSpace;
|
||||
|
||||
- (NSInteger)doricFlowLayoutColumnCount;
|
||||
|
||||
@end
|
||||
|
||||
@interface DoricFlowLayout : UICollectionViewLayout
|
||||
@property(nonatomic, readonly) NSInteger columnCount;
|
||||
@property(nonatomic, readonly) CGFloat columnSpace;
|
||||
@property(nonatomic, readonly) CGFloat rowSpace;
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSNumber *, NSNumber *> *columnHeightInfo;
|
||||
@property(nonatomic, weak) id <DoricFlowLayoutDelegate> delegate;
|
||||
@end
|
||||
|
||||
@implementation DoricFlowLayout
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_columnHeightInfo = [NSMutableDictionary new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)columnCount {
|
||||
return self.delegate.doricFlowLayoutColumnCount ?: 2;
|
||||
}
|
||||
|
||||
- (CGFloat)columnSpace {
|
||||
return self.delegate.doricFlowLayoutColumnSpace ?: 0;
|
||||
}
|
||||
|
||||
- (CGFloat)rowSpace {
|
||||
return self.delegate.doricFlowLayoutRowSpace ?: 0;
|
||||
}
|
||||
|
||||
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)prepareLayout {
|
||||
[super prepareLayout];
|
||||
for (int i = 0; i < self.columnCount; i++) {
|
||||
self.columnHeightInfo[@(i)] = @(0);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
|
||||
for (int i = 0; i < self.columnCount; i++) {
|
||||
self.columnHeightInfo[@(i)] = @(0);
|
||||
}
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
NSInteger count = [self.collectionView numberOfItemsInSection:0];
|
||||
for (int i = 0; i < count; i++) {
|
||||
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
|
||||
[array addObject:attrs];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSNumber *minYOfColumn = @(0);
|
||||
for (NSNumber *key in self.columnHeightInfo.allKeys) {
|
||||
if ([self.columnHeightInfo[key] floatValue] < [self.columnHeightInfo[minYOfColumn] floatValue]) {
|
||||
minYOfColumn = key;
|
||||
}
|
||||
}
|
||||
|
||||
CGFloat width = (self.collectionView.width - self.columnSpace * (self.columnCount - 1)) / self.columnCount;
|
||||
CGFloat height = [self.delegate doricFlowLayoutItemHeightAtIndexPath:indexPath];
|
||||
CGFloat x = (width + self.columnSpace) * [minYOfColumn integerValue];
|
||||
CGFloat y = [self.columnHeightInfo[minYOfColumn] floatValue];
|
||||
if (y > 0) {
|
||||
y += self.rowSpace;
|
||||
}
|
||||
self.columnHeightInfo[minYOfColumn] = @(y + height);
|
||||
|
||||
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
|
||||
attrs.frame = CGRectMake(x, y, width, height);
|
||||
return attrs;
|
||||
}
|
||||
|
||||
- (CGSize)collectionViewContentSize {
|
||||
CGFloat width = self.collectionView.width;
|
||||
CGFloat height = 0;
|
||||
for (NSNumber *column in self.columnHeightInfo.allValues) {
|
||||
height = MAX(height, [column floatValue]);
|
||||
}
|
||||
return CGSizeMake(width, height);
|
||||
}
|
||||
@end
|
||||
|
||||
@interface DoricFlowLayoutViewCell : UICollectionViewCell
|
||||
@property(nonatomic, strong) DoricFlowLayoutItemNode *viewNode;
|
||||
@end
|
||||
|
||||
@implementation DoricFlowLayoutViewCell
|
||||
@end
|
||||
|
||||
@interface DoricFlowLayoutView : UICollectionView
|
||||
@end
|
||||
|
||||
@implementation DoricFlowLayoutView
|
||||
- (CGSize)sizeThatFits:(CGSize)size {
|
||||
if (self.subviews.count > 0) {
|
||||
CGFloat width = size.width;
|
||||
CGFloat height = size.height;
|
||||
for (UIView *child in self.subviews) {
|
||||
CGSize childSize = [child measureSize:size];
|
||||
width = MAX(childSize.width, width);
|
||||
height = MAX(childSize.height, height);
|
||||
}
|
||||
return CGSizeMake(width, height);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
- (void)layoutSelf:(CGSize)targetSize {
|
||||
[super layoutSelf:targetSize];
|
||||
[self reloadData];
|
||||
}
|
||||
@end
|
||||
|
||||
@interface DoricFlowLayoutNode () <UICollectionViewDataSource, UICollectionViewDelegate, DoricFlowLayoutDelegate>
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSNumber *, NSString *> *itemViewIds;
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSNumber *, NSValue *> *itemSizeInfo;
|
||||
@property(nonatomic, assign) NSUInteger itemCount;
|
||||
@property(nonatomic, assign) NSUInteger batchCount;
|
||||
@property(nonatomic, assign) NSUInteger columnCount;
|
||||
@property(nonatomic, assign) CGFloat columnSpace;
|
||||
@property(nonatomic, assign) CGFloat rowSpace;
|
||||
@end
|
||||
|
||||
@implementation DoricFlowLayoutNode
|
||||
- (instancetype)initWithContext:(DoricContext *)doricContext {
|
||||
if (self = [super initWithContext:doricContext]) {
|
||||
_itemViewIds = [NSMutableDictionary new];
|
||||
_itemSizeInfo = [NSMutableDictionary new];
|
||||
_batchCount = 15;
|
||||
_columnCount = 2;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UICollectionView *)build {
|
||||
DoricFlowLayout *flowLayout = [[DoricFlowLayout alloc] init];
|
||||
flowLayout.delegate = self;
|
||||
return [[[DoricFlowLayoutView alloc] initWithFrame:CGRectZero
|
||||
collectionViewLayout:flowLayout]
|
||||
also:^(UICollectionView *it) {
|
||||
it.backgroundColor = [UIColor whiteColor];
|
||||
it.pagingEnabled = YES;
|
||||
it.delegate = self;
|
||||
it.dataSource = self;
|
||||
[it registerClass:[DoricFlowLayoutViewCell class] forCellWithReuseIdentifier:@"doricCell"];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)blendView:(UICollectionView *)view forPropName:(NSString *)name propValue:(id)prop {
|
||||
if ([@"columnSpace" isEqualToString:name]) {
|
||||
self.columnSpace = [prop floatValue];
|
||||
[self.view.collectionViewLayout invalidateLayout];
|
||||
} else if ([@"rowSpace" isEqualToString:name]) {
|
||||
self.rowSpace = [prop floatValue];
|
||||
[self.view.collectionViewLayout invalidateLayout];
|
||||
} else if ([@"columnCount" isEqualToString:name]) {
|
||||
self.columnCount = [prop unsignedIntegerValue];
|
||||
[self.view reloadData];
|
||||
[self.view.collectionViewLayout invalidateLayout];
|
||||
} else if ([@"itemCount" isEqualToString:name]) {
|
||||
self.itemCount = [prop unsignedIntegerValue];
|
||||
[self.view reloadData];
|
||||
} else if ([@"renderItem" isEqualToString:name]) {
|
||||
[self.itemViewIds removeAllObjects];
|
||||
[self clearSubModel];
|
||||
[self.view reloadData];
|
||||
} else if ([@"batchCount" isEqualToString:name]) {
|
||||
self.batchCount = [prop unsignedIntegerValue];
|
||||
} else {
|
||||
[super blendView:view forPropName:name propValue:prop];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)itemModelAt:(NSUInteger)position {
|
||||
NSString *viewId = self.itemViewIds[@(position)];
|
||||
if (viewId && viewId.length > 0) {
|
||||
return [self subModelOf:viewId];
|
||||
} else {
|
||||
DoricAsyncResult *result = [self callJSResponse:@"renderBunchedItems", @(position), @(self.batchCount), nil];
|
||||
JSValue *models = [result waitUntilResult];
|
||||
NSArray *array = [models toArray];
|
||||
[array enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
|
||||
NSString *thisViewId = obj[@"id"];
|
||||
[self setSubModel:obj in:thisViewId];
|
||||
NSUInteger pos = position + idx;
|
||||
self.itemViewIds[@(pos)] = thisViewId;
|
||||
}];
|
||||
return array[0];
|
||||
}
|
||||
}
|
||||
|
||||
- (DoricViewNode *)subNodeWithViewId:(NSString *)viewId {
|
||||
__block DoricViewNode *ret = nil;
|
||||
[self.doricContext.driver ensureSyncInMainQueue:^{
|
||||
for (UICollectionViewCell *collectionViewCell in self.view.visibleCells) {
|
||||
if ([collectionViewCell isKindOfClass:[DoricFlowLayoutViewCell class]]) {
|
||||
DoricFlowLayoutItemNode *node = ((DoricFlowLayoutViewCell *) collectionViewCell).viewNode;
|
||||
if ([viewId isEqualToString:node.viewId]) {
|
||||
ret = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)blendSubNode:(NSDictionary *)subModel {
|
||||
NSString *viewId = subModel[@"id"];
|
||||
DoricViewNode *viewNode = [self subNodeWithViewId:viewId];
|
||||
if (viewNode) {
|
||||
[viewNode blend:subModel[@"props"]];
|
||||
} else {
|
||||
NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy];
|
||||
[self recursiveMixin:subModel to:model];
|
||||
[self setSubModel:model in:viewId];
|
||||
}
|
||||
[self.itemViewIds enumerateKeysAndObjectsUsingBlock:^(NSNumber *_Nonnull key, NSString *_Nonnull obj, BOOL *_Nonnull stop) {
|
||||
if ([viewId isEqualToString:obj]) {
|
||||
*stop = YES;
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[key integerValue] inSection:0];
|
||||
[UIView performWithoutAnimation:^{
|
||||
[self.view reloadItemsAtIndexPaths:@[indexPath]];
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)callItem:(NSUInteger)position size:(CGSize)size {
|
||||
NSValue *old = self.itemSizeInfo[@(position)];
|
||||
if (old && CGSizeEqualToSize([old CGSizeValue], size)) {
|
||||
return;
|
||||
}
|
||||
self.itemSizeInfo[@(position)] = [NSValue valueWithCGSize:size];
|
||||
[self.view.collectionViewLayout invalidateLayout];
|
||||
}
|
||||
|
||||
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
||||
return self.itemCount;
|
||||
}
|
||||
|
||||
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSUInteger position = (NSUInteger) indexPath.row;
|
||||
NSDictionary *model = [self itemModelAt:position];
|
||||
NSDictionary *props = model[@"props"];
|
||||
DoricFlowLayoutViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"doricCell" forIndexPath:indexPath];
|
||||
if (!cell.viewNode) {
|
||||
DoricFlowLayoutItemNode *itemNode = [[DoricFlowLayoutItemNode alloc] initWithContext:self.doricContext];
|
||||
[itemNode initWithSuperNode:self];
|
||||
cell.viewNode = itemNode;
|
||||
[cell.contentView addSubview:itemNode.view];
|
||||
}
|
||||
DoricFlowLayoutItemNode *node = cell.viewNode;
|
||||
node.viewId = model[@"id"];
|
||||
[node blend:props];
|
||||
CGFloat width = (collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount;
|
||||
CGSize size = [node.view measureSize:CGSizeMake(width, collectionView.height)];
|
||||
[node.view layoutSelf:size];
|
||||
[self callItem:position size:size];
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (CGFloat)doricFlowLayoutItemHeightAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSUInteger position = (NSUInteger) indexPath.row;
|
||||
NSValue *value = self.itemSizeInfo[@(position)];
|
||||
if (value) {
|
||||
return [value CGSizeValue].height;
|
||||
} else {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)doricFlowLayoutColumnSpace {
|
||||
return self.columnSpace;
|
||||
}
|
||||
|
||||
- (CGFloat)doricFlowLayoutRowSpace {
|
||||
return self.rowSpace;
|
||||
}
|
||||
|
||||
- (NSInteger)doricFlowLayoutColumnCount {
|
||||
return self.columnCount;
|
||||
}
|
||||
|
||||
@end
|
30
doric-iOS/Pod/Classes/Shader/DoricGroupNode.h
Normal file
30
doric-iOS/Pod/Classes/Shader/DoricGroupNode.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricGroupNode.h
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/30.
|
||||
//
|
||||
|
||||
#import "DoricSuperNode.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricGroupNode <V:UIView *> : DoricSuperNode<V>
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
171
doric-iOS/Pod/Classes/Shader/DoricGroupNode.m
Normal file
171
doric-iOS/Pod/Classes/Shader/DoricGroupNode.m
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricGroupNode.m
|
||||
// Doric
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/7/30.
|
||||
//
|
||||
|
||||
#import <Doric/DoricExtensions.h>
|
||||
#import "DoricGroupNode.h"
|
||||
|
||||
@interface DoricGroupNode ()
|
||||
@property(nonatomic, copy) NSArray<DoricViewNode *> *childNodes;
|
||||
@property(nonatomic, copy) NSArray <NSString *> *childViewIds;
|
||||
@end
|
||||
|
||||
@implementation DoricGroupNode
|
||||
|
||||
- (instancetype)initWithContext:(DoricContext *)doricContext {
|
||||
if (self = [super initWithContext:doricContext]) {
|
||||
_childNodes = @[];
|
||||
_childViewIds = @[];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UIView *)build {
|
||||
UIView *ret = [[UIView alloc] init];
|
||||
ret.clipsToBounds = YES;
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop {
|
||||
if ([@"children" isEqualToString:name]) {
|
||||
self.childViewIds = prop;
|
||||
} else {
|
||||
[super blendView:view forPropName:name propValue:prop];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)blend:(NSDictionary *)props {
|
||||
[super blend:props];
|
||||
[self configChildNodes];
|
||||
}
|
||||
|
||||
- (DoricLayoutConfig *)generateDefaultLayoutParams {
|
||||
DoricLayoutConfig *params = [[DoricLayoutConfig alloc] init];
|
||||
return params;
|
||||
}
|
||||
|
||||
- (void)configChildNodes {
|
||||
NSMutableArray *childNodes = [self.childNodes mutableCopy];
|
||||
for (NSUInteger idx = 0; idx < self.childViewIds.count; idx++) {
|
||||
NSString *viewId = self.childViewIds[idx];
|
||||
NSDictionary *model = [self subModelOf:viewId];
|
||||
NSString *type = model[@"type"];
|
||||
if (idx < self.childNodes.count) {
|
||||
DoricViewNode *oldNode = childNodes[idx];
|
||||
if ([viewId isEqualToString:oldNode.viewId]) {
|
||||
///Same,skip
|
||||
} else {
|
||||
if (self.reusable) {
|
||||
if ([oldNode.type isEqualToString:type]) {
|
||||
///Same type,can be reused
|
||||
oldNode.viewId = viewId;
|
||||
[oldNode blend:model[@"props"]];
|
||||
} else {
|
||||
///Replace this view
|
||||
[childNodes removeObjectAtIndex:idx];
|
||||
[oldNode.view removeFromSuperview];
|
||||
DoricViewNode *viewNode = [DoricViewNode create:self.doricContext withType:type];
|
||||
if ([viewNode isKindOfClass:[DoricGroupNode class]]) {
|
||||
((DoricGroupNode *) viewNode).reusable = self.reusable;
|
||||
}
|
||||
viewNode.viewId = viewId;
|
||||
[viewNode initWithSuperNode:self];
|
||||
[viewNode blend:model[@"props"]];
|
||||
[childNodes insertObject:viewNode atIndex:idx];
|
||||
[self.view insertSubview:viewNode.view atIndex:idx];
|
||||
}
|
||||
} else {
|
||||
///Find in remain nodes
|
||||
NSInteger position = -1;
|
||||
for (NSUInteger start = idx + 1; start < childNodes.count; start++) {
|
||||
DoricViewNode *node = childNodes[start];
|
||||
if ([viewId isEqualToString:node.viewId]) {
|
||||
position = start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (position >= 0) {
|
||||
///Found ,swap idx,position
|
||||
DoricViewNode *reused = childNodes[(NSUInteger) position];
|
||||
[childNodes removeObjectAtIndex:(NSUInteger) position];
|
||||
[childNodes removeObjectAtIndex:idx];
|
||||
[childNodes insertObject:reused atIndex:idx];
|
||||
[childNodes insertObject:oldNode atIndex:(NSUInteger) position];
|
||||
|
||||
///View swap index
|
||||
[reused.view removeFromSuperview];
|
||||
[oldNode.view removeFromSuperview];
|
||||
[self.view insertSubview:reused.view atIndex:idx];
|
||||
[self.view insertSubview:oldNode.view atIndex:position];
|
||||
} else {
|
||||
///Not found,insert
|
||||
DoricViewNode *viewNode = [DoricViewNode create:self.doricContext withType:type];
|
||||
viewNode.viewId = viewId;
|
||||
[viewNode initWithSuperNode:self];
|
||||
[viewNode blend:model[@"props"]];
|
||||
[childNodes insertObject:viewNode atIndex:idx];
|
||||
[self.view insertSubview:viewNode.view atIndex:idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/// Insert
|
||||
DoricViewNode *viewNode = [DoricViewNode create:self.doricContext withType:type];
|
||||
if ([viewNode isKindOfClass:[DoricGroupNode class]]) {
|
||||
((DoricGroupNode *) viewNode).reusable = self.reusable;
|
||||
}
|
||||
viewNode.viewId = viewId;
|
||||
[viewNode initWithSuperNode:self];
|
||||
[viewNode blend:model[@"props"]];
|
||||
[childNodes addObject:viewNode];
|
||||
[self.view addSubview:viewNode.view];
|
||||
}
|
||||
}
|
||||
|
||||
NSUInteger count = childNodes.count;
|
||||
for (NSUInteger idx = self.childViewIds.count; idx < count; idx++) {
|
||||
DoricViewNode *viewNode = childNodes.lastObject;
|
||||
[childNodes removeLastObject];
|
||||
[viewNode.view removeFromSuperview];
|
||||
}
|
||||
self.childNodes = [childNodes copy];
|
||||
}
|
||||
|
||||
- (void)blendSubNode:(NSDictionary *)subModel {
|
||||
NSString *viewId = subModel[@"id"];
|
||||
[self.childNodes enumerateObjectsUsingBlock:^(DoricViewNode *obj, NSUInteger idx, BOOL *stop) {
|
||||
if ([viewId isEqualToString:obj.viewId]) {
|
||||
[obj blend:subModel[@"props"]];
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (DoricViewNode *)subNodeWithViewId:(NSString *)viewId {
|
||||
for (DoricViewNode *viewNode in self.childNodes) {
|
||||
if ([viewId isEqualToString:viewNode.viewId]) {
|
||||
return viewNode;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user