Merge branch 'iOS_master' into combine

This commit is contained in:
pengfei.zhou 2019-12-21 23:09:37 +08:00
commit 8fa2b69e5a
56 changed files with 1055 additions and 260 deletions

54
doric-iOS/.gitignore vendored
View File

@ -1,8 +1,12 @@
# OS X
.DS_Store
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
@ -11,27 +15,43 @@ build/
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
xcuserdata
*.xcscheme
## Other
*.xccheckout
profile
*.moved-aside
DerivedData
*.xcuserstate
*.xcscmblueprint
.idea
.svn
.DS_Store
## Obj-C/Swift specific
*.hmap
*.ipa
Example/Pods
# Bundler
.bundle
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
Pods/
Podfile.lock
# Carthage
#
# 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/
*.lock
.clang-format
settings.json
Podfile.local
Podfile
ModulesDebug

View File

@ -0,0 +1,28 @@
Pod::Spec.new do |s|
s.name = 'DoricCore'
s.version = '0.1.2'
s.summary = 'Doric iOS SDK'
s.description = <<-DESC
Doric iOS SDK for cross platform develpment
DESC
s.homepage = 'https://github.com/doric-pub/doric'
s.license = { :type => 'Apache-2.0', :file => 'LICENSE' }
s.author = { 'pengfei.zhou' => 'pengfeizhou@foxmail.com' }
s.source = { :git => 'https://github.com/doric-pub/doric-iOS.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'Pod/Classes/**/*'
s.resource_bundles = {
'Doric' => ['Pod/Assets/**/*']
}
s.public_header_files = 'Pod/Classes/**/*.h'
s.dependency 'YYWebImage', '~>1.0.5'
s.dependency 'YYImage/WebP'
s.dependency 'SocketRocket', '~> 0.5.1'
s.dependency 'YYCache', '~> 1.0.4'
end

View File

@ -3,15 +3,15 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 50;
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 */; };
26047AF7D618FF60281DC778 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92C4B99C431BD381198935DE /* Pods_Example.framework */; };
C6AF7EB0B40D76A46B2BB384 /* Pods_ExampleUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF50786B1D1793EC3228133B /* Pods_ExampleUITests.framework */; };
D751D4B065D8D4FA6594B5EE /* DemoVC.m in Sources */ = {isa = PBXBuildFile; fileRef = D751D19E97EF4EDD7588FEBE /* DemoVC.m */; };
D751D4FCC0A2322211DE3D55 /* QRScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D751DA399F1ADB6D34563B5D /* QRScanViewController.m */; };
D751DDB012BAF476A252CD93 /* DemoLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = D751D2175D09F2C10691FB81 /* DemoLibrary.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 */; };
@ -21,6 +21,7 @@
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 */; };
E778063CA90E2DD797D11D7C /* Pods_ExampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00A2FF6380A526AB267988ED /* Pods_ExampleTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -41,17 +42,19 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
00A2FF6380A526AB267988ED /* Pods_ExampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ExampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
92C4B99C431BD381198935DE /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
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; };
BF50786B1D1793EC3228133B /* Pods_ExampleUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ExampleUITests.framework; 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>"; };
D751D2175D09F2C10691FB81 /* DemoLibrary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoLibrary.m; sourceTree = "<group>"; };
D751DA399F1ADB6D34563B5D /* QRScanViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRScanViewController.m; sourceTree = "<group>"; };
D751DB0CB3009E12990F661E /* DemoLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoLibrary.h; 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; };
@ -78,7 +81,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2EB14575543B0285648B858D /* libPods-Example.a in Frameworks */,
26047AF7D618FF60281DC778 /* Pods_Example.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -86,7 +89,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1B5560FDC1A57040A84A35AB /* libPods-ExampleTests.a in Frameworks */,
E778063CA90E2DD797D11D7C /* Pods_ExampleTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -94,7 +97,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
835F4CD080BABFE95A6BFD16 /* libPods-ExampleUITests.a in Frameworks */,
C6AF7EB0B40D76A46B2BB384 /* Pods_ExampleUITests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -117,9 +120,9 @@
D80A9B07B39AD04027CAE17B /* Frameworks */ = {
isa = PBXGroup;
children = (
C3CFA4394FF1344386170022 /* libPods-Example.a */,
30CF3CCBAF1F8AD594763E4A /* libPods-ExampleTests.a */,
563C5AC823878F4913BBCDF2 /* libPods-ExampleUITests.a */,
92C4B99C431BD381198935DE /* Pods_Example.framework */,
00A2FF6380A526AB267988ED /* Pods_ExampleTests.framework */,
BF50786B1D1793EC3228133B /* Pods_ExampleUITests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -163,6 +166,8 @@
D751DDEC114E037231257E64 /* DemoVC.h */,
D751DA399F1ADB6D34563B5D /* QRScanViewController.m */,
D751D18AD6496F4A9BE1AB45 /* QRScanViewController.h */,
D751D2175D09F2C10691FB81 /* DemoLibrary.m */,
D751DB0CB3009E12990F661E /* DemoLibrary.h */,
);
path = Example;
sourceTree = "<group>";
@ -197,8 +202,8 @@
E2334AE722E9D2060098A085 /* Sources */,
E2334AE822E9D2060098A085 /* Frameworks */,
E2334AE922E9D2060098A085 /* Resources */,
2719DACF05C7A7C1EB4AD553 /* [CP] Embed Pods Frameworks */,
C232600D894D85358A6ABF4D /* [CP] Copy Pods Resources */,
223E53E328880489770F8C93 /* [CP] Embed Pods Frameworks */,
EEF1C3B3FE5FE92E603C3B08 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -217,8 +222,8 @@
E2334AFF22E9D2070098A085 /* Sources */,
E2334B0022E9D2070098A085 /* Frameworks */,
E2334B0122E9D2070098A085 /* Resources */,
68729F70B03CECDBAD2022E4 /* [CP] Embed Pods Frameworks */,
D5C1C722575685F99C382E01 /* [CP] Copy Pods Resources */,
9908F148F5F00DD2EB349A08 /* [CP] Embed Pods Frameworks */,
17E0A19B8E5C4C4883C8AB85 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -238,8 +243,8 @@
E2334B0A22E9D2070098A085 /* Sources */,
E2334B0B22E9D2070098A085 /* Frameworks */,
E2334B0C22E9D2070098A085 /* Resources */,
AC45D4A1B85D5D5A2F6E3DBD /* [CP] Embed Pods Frameworks */,
F0AA1A5ADB99F5ECA1F9331E /* [CP] Copy Pods Resources */,
5FE5475A2ECF1794CBF57C61 /* [CP] Embed Pods Frameworks */,
C09BD0B68592DA6641E3B65D /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -344,7 +349,7 @@
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 */ = {
17E0A19B8E5C4C4883C8AB85 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -353,10 +358,40 @@
);
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;
};
223E53E328880489770F8C93 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/DoricCore/DoricCore.framework",
"${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework",
"${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework",
"${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
"${BUILT_PRODUCTS_DIR}/YYWebImage/YYWebImage.framework",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DoricCore.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketRocket.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYCache.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYWebImage.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@ -385,26 +420,7 @@
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 */ = {
5FE5475A2ECF1794CBF57C61 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -423,6 +439,25 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ExampleUITests/Pods-ExampleUITests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9908F148F5F00DD2EB349A08 /* [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;
};
BE34CD8291B20D26F2ADE3E1 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -445,66 +480,7 @@
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 */ = {
C09BD0B68592DA6641E3B65D /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -523,6 +499,43 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ExampleUITests/Pods-ExampleUITests-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\nsh ../../bundle.sh\n";
};
EEF1C3B3FE5FE92E603C3B08 /* [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-Example/Pods-Example-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -535,6 +548,7 @@
E2334AF022E9D2060098A085 /* AppDelegate.m in Sources */,
D751D4B065D8D4FA6594B5EE /* DemoVC.m in Sources */,
D751D4FCC0A2322211DE3D55 /* QRScanViewController.m in Sources */,
D751DDB012BAF476A252CD93 /* DemoLibrary.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Example.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -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>

View File

@ -0,0 +1,10 @@
//
// Created by pengfei.zhou on 2019/12/11.
// Copyright (c) 2019 pengfei.zhou. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <DoricCore/Doric.h>
@interface DemoLibrary : DoricLibrary
@end

View File

@ -0,0 +1,24 @@
//
// Created by pengfei.zhou on 2019/12/11.
// Copyright (c) 2019 pengfei.zhou. All rights reserved.
//
#import "DemoLibrary.h"
@interface DoricDemoPlugin : DoricNativePlugin
@end
@implementation DoricDemoPlugin
- (void)test {
dispatch_async(dispatch_get_main_queue(), ^{
ShowToast(@"Test called", CENTER);
});
}
@end
@implementation DemoLibrary
- (void)load:(DoricRegistry *)registry {
[registry registerNativePlugin:[DoricDemoPlugin class] withName:@"demo"];
}
@end

View File

@ -4,7 +4,7 @@
//
#import "DemoVC.h"
#import "Doric.h"
#import <DoricCore/Doric.h>
@interface DemoVC ()
@property(nonatomic, copy) NSString *filePath;
@ -33,7 +33,7 @@ - (void)viewDidLoad {
[self.view addSubview:it];
}];
[self addChildViewController:panel];
[panel config:jsContent alias:self.filePath];
[panel config:jsContent alias:self.filePath extra:nil];
}
@end

View File

@ -5,7 +5,7 @@
#import "QRScanViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "Doric.h"
#import <DoricCore/Doric.h>
@interface QRScanViewController () <AVCaptureMetadataOutputObjectsDelegate>
@property(strong, nonatomic) AVCaptureDevice *device;

View File

@ -7,9 +7,10 @@
//
#import "ViewController.h"
#import "Doric.h"
#import <DoricCore/Doric.h>
#import "DemoVC.h"
#import "QRScanViewController.h"
#import "DemoLibrary.h"
@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
@property(nonatomic, copy) NSArray <NSString *> *demoFilePaths;
@ -27,6 +28,11 @@ - (void)viewDidLoad {
return ![obj containsString:@".map"];
}];
NSMutableArray <NSString *> *tmp = [self.demoFilePaths mutableCopy];
NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch;
[tmp sortUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
NSRange range = NSMakeRange(0, obj1.length);
return [obj1 compare:obj2 options:comparisonOptions range:range];
}];
[tmp insertObject:@"Dev Kit" atIndex:0];
self.demoFilePaths = tmp;
[self.view addSubview:[[UITableView new] also:^(UITableView *it) {
@ -36,6 +42,7 @@ - (void)viewDidLoad {
it.dataSource = self;
it.delegate = self;
}]];
[DoricRegistry register:[DemoLibrary new]];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
@ -72,7 +79,9 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
if ([file containsString:@"NavigatorDemo"]) {
DoricViewController *doricViewController = [[DoricViewController alloc]
initWithScheme:[NSString stringWithFormat:@"assets://demo/%@", file]
alias:self.demoFilePaths[(NSUInteger) indexPath.row]];
alias:self.demoFilePaths[(NSUInteger) indexPath.row]
extra:nil
];
[self.navigationController pushViewController:doricViewController animated:NO];
} else {
DemoVC *demoVC = [[DemoVC alloc] initWithPath:file];

View File

@ -1 +0,0 @@
../../../demo/bundle/src/

View File

@ -0,0 +1 @@
*.js

View File

@ -1 +0,0 @@
../../../js-framework/bundle

View File

@ -0,0 +1 @@
*.js

View File

@ -26,3 +26,5 @@
#import "DoricNavBarDelegate.h"
#import "DoricViewController.h"
#import "DoricPromise.h"
#import "DoricLibrary.h"
#import "DoricNativePlugin.h"

View File

@ -41,8 +41,9 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, strong) NSMutableDictionary *initialParams;
@property(nonatomic, strong) DoricRootNode *rootNode;
@property(nonatomic, strong) NSMutableDictionary <NSString *, DoricViewNode *> *headNodes;
@property(nonatomic, copy) NSString *extra;
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source;
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source extra:(NSString *)extra;
- (DoricAsyncResult *)callEntity:(NSString *)method, ...;

View File

@ -28,7 +28,7 @@
@implementation DoricContext
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source {
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source extra:(NSString *)extra {
if (self = [super init]) {
_driver = [DoricDriver instance];
_pluginInstanceMap = [NSMutableDictionary new];
@ -39,6 +39,7 @@ - (instancetype)initWithScript:(NSString *)script source:(NSString *)source {
_script = script;
_source = source;
_initialParams = [@{@"width": @(0), @"height": @(0)} mutableCopy];
_extra = extra;
[self callEntity:DORIC_ENTITY_CREATE, nil];
}
return self;
@ -78,7 +79,7 @@ - (void)initContextWithWidth:(CGFloat)width height:(CGFloat)height {
it[@"width"] = @(width);
it[@"height"] = @(height);
}];
[self callEntity:DORIC_ENTITY_INIT, self.initialParams, nil];
[self callEntity:DORIC_ENTITY_INIT, self.initialParams, self.extra, nil];
}
- (void)reload:(NSString *)script {
@ -86,6 +87,7 @@ - (void)reload:(NSString *)script {
self.script = script;
[self.driver createContext:self.contextId script:script source:self.source];
[self callEntity:DORIC_ENTITY_INIT, self.initialParams, nil];
[self onShow];
}
- (void)onShow {

View File

@ -26,7 +26,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface DoricContextHolder : NSObject
@property(nonatomic, strong) DoricContext *doricContext;
@property(nonatomic, weak) DoricContext *doricContext;
- (instancetype)initWithContext:(DoricContext *)doricContext;

View 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/12/11.
//
#import <Foundation/Foundation.h>
#import "DoricRegistry.h"
@interface DoricLibrary : NSObject
- (void)load:(DoricRegistry *)registry;
@end

View 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/12/11.
//
#import "DoricLibrary.h"
@implementation DoricLibrary
- (void)load:(DoricRegistry *)registry {
}
@end

View File

@ -25,5 +25,5 @@
@interface DoricPanel : UIViewController
@property(nonatomic, strong) DoricContext *doricContext;
- (void)config:(NSString *)script alias:(NSString *)alias;
- (void)config:(NSString *)script alias:(NSString *)alias extra:(NSString *)extra;
@end

View File

@ -22,8 +22,8 @@
@implementation DoricPanel
- (void)config:(NSString *)script alias:(NSString *)alias {
self.doricContext = [[[DoricContext alloc] initWithScript:script source:alias] also:^(DoricContext *it) {
- (void)config:(NSString *)script alias:(NSString *)alias extra:(NSString *)extra {
self.doricContext = [[[DoricContext alloc] initWithScript:script source:alias extra:extra] also:^(DoricContext *it) {
[it.rootNode setupRootView:[[DoricStackView new] also:^(DoricStackView *it) {
[self.view addSubview:it];
}]];

View File

@ -23,6 +23,7 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class DoricLibrary;
@interface DoricRegistry : NSObject
@ -38,6 +39,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)registerViewNode:(Class)nodeClass withName:(NSString *)name;
- (Class)acquireViewNode:(NSString *)name;
+ (void)register:(DoricLibrary *)library;
@end
NS_ASSUME_NONNULL_END

View File

@ -42,6 +42,35 @@
#import "DoricFlowLayoutNode.h"
#import "DoricPopoverPlugin.h"
#import "DoricAnimatePlugin.h"
#import "DoricNestedSliderNode.h"
#import "DoricInputNode.h"
#import "DoricLibrary.h"
@interface DoricLibraries : NSObject
@property(nonatomic, strong) NSMutableSet <DoricLibrary *> *libraries;
+ (instancetype)instance;
@end
@implementation DoricLibraries
- (instancetype)init {
if (self = [super init]) {
_libraries = [NSMutableSet new];
}
return self;
}
+ (instancetype)instance {
static DoricLibraries *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[DoricLibraries alloc] init];
});
return _instance;
}
@end
@interface DoricRegistry ()
@ -53,12 +82,19 @@ @interface DoricRegistry ()
@implementation DoricRegistry
+ (void)register:(DoricLibrary *)library {
[DoricLibraries.instance.libraries addObject:library];
}
- (instancetype)init {
if (self = [super init]) {
_bundles = [[NSMutableDictionary alloc] init];
_plugins = [[NSMutableDictionary alloc] init];
_nodes = [[NSMutableDictionary alloc] init];
[self innerRegister];
[DoricLibraries.instance.libraries enumerateObjectsUsingBlock:^(DoricLibrary *obj, BOOL *stop) {
[obj load:self];
}];
}
return self;
}
@ -86,6 +122,8 @@ - (void)innerRegister {
[self registerViewNode:DoricRefreshableNode.class withName:@"Refreshable"];
[self registerViewNode:DoricFlowLayoutItemNode.class withName:@"FlowLayoutItem"];
[self registerViewNode:DoricFlowLayoutNode.class withName:@"FlowLayout"];
[self registerViewNode:DoricNestedSliderNode.class withName:@"NestedSlider"];
[self registerViewNode:DoricInputNode.class withName:@"Input"];
}
- (void)registerJSBundle:(NSString *)bundle withName:(NSString *)name {

View File

@ -8,7 +8,7 @@
* 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,
* distributed under the License is distributed onO 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.
@ -22,5 +22,5 @@
#import "DoricNavBarDelegate.h"
@interface DoricViewController : UIViewController <DoricNavigatorDelegate, DoricNavBarDelegate>
- (instancetype)initWithScheme:(NSString *)scheme alias:(NSString *)alias;
- (instancetype)initWithScheme:(NSString *)scheme alias:(NSString *)alias extra:(NSString *)extra;
@end

View File

@ -32,7 +32,7 @@ @interface DoricViewController ()
@end
@implementation DoricViewController
- (instancetype)initWithScheme:(NSString *)scheme alias:(NSString *)alias {
- (instancetype)initWithScheme:(NSString *)scheme alias:(NSString *)alias extra:(NSString *)extra {
if (self = [super init]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
DoricAsyncResult <NSString *> *result = [DoricJSLoaderManager.instance request:scheme];
@ -46,7 +46,7 @@ - (instancetype)initWithScheme:(NSString *)scheme alias:(NSString *)alias {
}];
[self.view addSubview:panel.view];
[self addChildViewController:panel];
[panel config:result alias:alias];
[panel config:result alias:alias extra:extra];
panel.doricContext.navigator = self;
panel.doricContext.navBar = self;
self.doricPanel = panel;
@ -78,8 +78,8 @@ - (void)viewWillLayoutSubviews {
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];
- (void)doric_navigator_push:(NSString *)scheme alias:(NSString *)alias animated:(BOOL)animated extra:(NSString *)extra {
DoricViewController *viewController = [[DoricViewController alloc] initWithScheme:scheme alias:alias extra:extra];
[self.navigationController pushViewController:viewController animated:animated];
}

View File

@ -55,7 +55,15 @@ - (instancetype)init {
- (void)initJSExecutor {
__weak typeof(self) _self = self;
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
[self.jsExecutor injectGlobalJSObject:INJECT_ENVIRONMENT obj:@{
@"platform": @"iOS",
@"platformVersion": [[UIDevice currentDevice] systemVersion],
@"appName": infoDictionary[@"CFBundleName"],
@"appVersion": infoDictionary[@"CFBundleShortVersionString"],
@"screenWidth": @([[UIScreen mainScreen] bounds].size.width),
@"screenHeight": @([[UIScreen mainScreen] bounds].size.height),
}];
[self.jsExecutor injectGlobalJSObject:INJECT_LOG obj:^(NSString *type, NSString *message) {
DoricLog(@"JS:%@", message);
}];

View File

@ -50,6 +50,7 @@ - (instancetype)init {
return self;
}
#pragma mark - SRWebSocketDelegate
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
DoricLog(@"debugger webSocketDidOpen");
DC_UNLOCK(self.semaphore);
@ -93,6 +94,8 @@ - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
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 {
DoricLog(@"error:args to more than 5. args:%@",argsArr);
}
} else if ([cmd isEqualToString:@"invokeMethod"]) {
@ -115,6 +118,7 @@ - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reas
DoricLog(@"debugger webSocketdidCloseWithCode");
}
#pragma mark - DoricJSExecutorProtocol
- (NSString *)loadJSScript:(NSString *)script source:(NSString *)source {
return nil;
@ -141,10 +145,7 @@ - (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(
NSMutableArray *argsMArr = [NSMutableArray new];
for (id arg in args) {
NSDictionary *dic = @{
@"type": @(DoricargTypeWithArg(arg)),
@"value": arg
};
NSDictionary *dic = [self dicForArg:arg];
[argsMArr addObject:dic];
}
@ -168,6 +169,19 @@ - (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(
return self.temp;
}
- (NSDictionary *)dicForArg:(id)arg {
DoricJSRemoteArgType type = DoricargTypeWithArg(arg);
if (type == DoricJSRemoteArgTypeObject || type == DoricJSRemoteArgTypeArray) {
NSString *jsonStr = [NSString dc_convertToJsonWithDic:(NSDictionary *)arg];
arg = jsonStr;
}
NSDictionary *dic = @{
@"type": @(type),
@"value": arg
};
return dic;
}
- (void)close {
[self.srWebSocket close];
}

View File

@ -73,11 +73,15 @@ - (id)findClass:(Class)clz target:(id)target context:(DoricContext *)context met
dispatch_block_t block = ^() {
__strong __typeof__(_self) self = _self;
@try {
NSMutableArray *tempArray = [NSMutableArray new];
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];
if (args) {
[tempArray addObject:args];
}
[invocation setArgument:&args atIndex:idx];
}
[invocation invoke];

View File

@ -18,7 +18,7 @@
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol DoricNavBarDelegate <NSObject>
- (BOOL)doric_navBar_isHidden;

View File

@ -20,7 +20,7 @@
#import <Foundation/Foundation.h>
@protocol DoricNavigatorDelegate <NSObject>
- (void)doric_navigator_push:(NSString *)scheme alias:(NSString *)alias animated:(BOOL)animated;
- (void)doric_navigator_push:(NSString *)scheme alias:(NSString *)alias animated:(BOOL)animated extra:(NSString *)extra;
- (void)doric_navigator_pop:(BOOL)animated;
@end

View File

@ -20,9 +20,9 @@
// Created by pengfei.zhou on 2019/7/29.
//
#import <Doric/Doric.h>
#import "DoricModalPlugin.h"
#import "DoricUtil.h"
#import "DoricExtensions.h"
@implementation DoricModalPlugin

View File

@ -24,10 +24,19 @@ @implementation DoricNavigatorPlugin
- (void)push:(NSDictionary *)params {
dispatch_async(dispatch_get_main_queue(), ^{
BOOL animated = YES;
if (params[@"animated"]) {
animated = [params[@"animated"] boolValue];
NSString *scheme = params[@"scheme"];
NSString *alias = scheme;
NSDictionary *config = params[@"config"];
if (config) {
if (config[@"animated"]) {
animated = [config[@"animated"] boolValue];
}
if (config[@"alias"]) {
alias = config[@"alias"];
}
}
[self.doricContext.navigator doric_navigator_push:params[@"scheme"] alias:params[@"alias"] animated:animated];
[self.doricContext.navigator doric_navigator_push:scheme alias:alias animated:animated extra:config[@"extra"]];
});
}

View File

@ -25,6 +25,8 @@
@protocol DoricFlowLayoutDelegate
- (CGFloat)doricFlowLayoutItemHeightAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)doricFlowLayoutItemWidthAtIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)doricFlowLayoutColumnSpace;
- (CGFloat)doricFlowLayoutRowSpace;
@ -93,15 +95,23 @@ - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSInde
}
}
CGFloat width = (self.collectionView.width - self.columnSpace * (self.columnCount - 1)) / self.columnCount;
CGFloat width = [self.delegate doricFlowLayoutItemWidthAtIndexPath:indexPath];
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);
if (width == self.collectionView.width) {
CGFloat maxY = 0;
for (NSNumber *column in self.columnHeightInfo.allValues) {
maxY = MAX(maxY, [column floatValue]);
}
y = maxY + self.rowSpace;
} else {
self.columnHeightInfo[minYOfColumn] = @(y + height);
}
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attrs.frame = CGRectMake(x, y, width, height);
return attrs;
@ -156,6 +166,11 @@ @interface DoricFlowLayoutNode () <UICollectionViewDataSource, UICollectionViewD
@property(nonatomic, assign) NSUInteger columnCount;
@property(nonatomic, assign) CGFloat columnSpace;
@property(nonatomic, assign) CGFloat rowSpace;
@property(nonatomic, copy) NSString *renderItemFuncId;
@property(nonatomic, copy) NSString *onLoadMoreFuncId;
@property(nonatomic, copy) NSString *loadMoreViewId;
@property(nonatomic, assign) BOOL loadMore;
@end
@implementation DoricFlowLayoutNode
@ -180,6 +195,7 @@ - (UICollectionView *)build {
it.delegate = self;
it.dataSource = self;
[it registerClass:[DoricFlowLayoutViewCell class] forCellWithReuseIdentifier:@"doricCell"];
[it registerClass:[DoricFlowLayoutViewCell class] forCellWithReuseIdentifier:@"doricLoadMoreCell"];
}];
}
@ -198,17 +214,31 @@ - (void)blendView:(UICollectionView *)view forPropName:(NSString *)name propValu
self.itemCount = [prop unsignedIntegerValue];
[self.view reloadData];
} else if ([@"renderItem" isEqualToString:name]) {
[self.itemViewIds removeAllObjects];
[self clearSubModel];
[self.view reloadData];
if ([self.renderItemFuncId isEqualToString:prop]) {
} else {
[self.itemViewIds removeAllObjects];
[self clearSubModel];
[self.view reloadData];
self.renderItemFuncId = prop;
}
} else if ([@"batchCount" isEqualToString:name]) {
self.batchCount = [prop unsignedIntegerValue];
} else if ([@"onLoadMore" isEqualToString:name]) {
self.onLoadMoreFuncId = prop;
} else if ([@"loadMoreView" isEqualToString:name]) {
self.loadMoreViewId = prop;
} else if ([@"loadMore" isEqualToString:name]) {
self.loadMore = [prop boolValue];
} else {
[super blendView:view forPropName:name propValue:prop];
}
}
- (NSDictionary *)itemModelAt:(NSUInteger)position {
if (position >= self.itemCount) {
return [self subModelOf:self.loadMoreViewId];
}
NSString *viewId = self.itemViewIds[@(position)];
if (viewId && viewId.length > 0) {
return [self subModelOf:viewId];
@ -243,24 +273,26 @@ - (DoricViewNode *)subNodeWithViewId:(NSString *)viewId {
}
- (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]];
}];
dispatch_async(dispatch_get_main_queue(), ^{
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 {
@ -273,13 +305,14 @@ - (void)callItem:(NSUInteger)position size:(CGSize)size {
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.itemCount;
return self.itemCount + (self.loadMore ? 1 : 0);
}
- (__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];
@ -287,11 +320,17 @@ - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collection
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)];
if (position > 0 && position >= self.itemCount && self.onLoadMoreFuncId) {
size = CGSizeMake(collectionView.width, size.height);
[self callJSResponse:self.onLoadMoreFuncId, nil];
}
[node.view layoutSelf:size];
[self callItem:position size:size];
return cell;
@ -307,6 +346,17 @@ - (CGFloat)doricFlowLayoutItemHeightAtIndexPath:(NSIndexPath *)indexPath {
}
}
- (CGFloat)doricFlowLayoutItemWidthAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger position = (NSUInteger) indexPath.row;
NSValue *value = self.itemSizeInfo[@(position)];
if (value) {
return [value CGSizeValue].width;
} else {
return 100;
}
}
- (CGFloat)doricFlowLayoutColumnSpace {
return self.columnSpace;
}

View File

@ -20,7 +20,6 @@
// Created by pengfei.zhou on 2019/7/30.
//
#import <Doric/DoricExtensions.h>
#import "DoricGroupNode.h"
@interface DoricGroupNode ()

View File

@ -26,6 +26,7 @@
@interface DoricImageNode ()
@property(nonatomic, copy) NSString *loadCallbackId;
@property(nonatomic, assign) BOOL isBlur;
@end
@implementation DoricImageNode
@ -36,6 +37,15 @@ - (UIImageView *)build {
}];
}
- (void)blend:(NSDictionary *)props {
NSInteger value = [props[@"isBlur"] intValue];
if(value == 1) {
self.isBlur = YES;
}
[super blend:props];
}
- (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id)prop {
if ([@"imageUrl" isEqualToString:name]) {
__weak typeof(self) _self = self;
@ -53,6 +63,13 @@ - (void)blendView:(UIImageView *)view forPropName:(NSString *)name propValue:(id
}
[self requestLayout];
}
if(self.isBlur) {
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *effectView = [[UIVisualEffectView alloc]initWithEffect:blurEffect];
effectView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
[view addSubview:effectView];
}
}];
} else if ([@"scaleType" isEqualToString:name]) {
switch ([prop integerValue]) {

View 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.
*/
//
// DoricInputNode.h
// Doric
//
// Created by 姜腾 on 2019/12/11.
//
#import "DoricViewNode.h"
NS_ASSUME_NONNULL_BEGIN
@interface DoricInputNode : DoricViewNode<UITextView *>
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,173 @@
/*
* 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.
*/
//
// DoricInputNode.m
// Doric
//
// Created by on 2019/12/11.
//
#import "DoricInputNode.h"
#import "DoricUtil.h"
#import "DoricPromise.h"
typedef void (^onTextChangeBlock)(NSString *text,DoricInputNode *node);
typedef void (^onFocusChangeBlock)(BOOL focused,DoricInputNode *node);
@interface DoricInputNode()<UITextViewDelegate>
@property(nonatomic, copy) onTextChangeBlock onTextChange;
@property(nonatomic, copy) onFocusChangeBlock onFocusShange;
@property(nonatomic, strong) UILabel *placeholderLabel;
@end
@implementation DoricInputNode
- (UITextView *)build {
UITextView *v = [[UITextView alloc] init];
v.delegate = self;
return v;
}
- (void)blendView:(UITextView *)view forPropName:(NSString *)name propValue:(id)prop {
if ([name isEqualToString:@"text"]) {
view.text = prop;
} else if ([name isEqualToString:@"textSize"]) {
view.font = [UIFont systemFontOfSize:[(NSNumber *) prop floatValue]];
} else if ([name isEqualToString:@"textColor"]) {
view.textColor = DoricColor(prop);
} else if ([name isEqualToString:@"textAlignment"]) {
DoricGravity gravity = (DoricGravity) [(NSNumber *) prop integerValue];
NSTextAlignment alignment = NSTextAlignmentCenter;
if ((gravity & LEFT) == LEFT) {
alignment = NSTextAlignmentLeft;
} else if ((gravity & RIGHT) == RIGHT) {
alignment = NSTextAlignmentRight;
}
view.textAlignment = alignment;
} else if ([name isEqualToString:@"multiline"]) {
BOOL mutilin = [(NSNumber *) prop boolValue];
if (!mutilin) {
view.textContainer.maximumNumberOfLines = 1;
}else {
view.textContainer.maximumNumberOfLines = 0;
}
} else if ([name isEqualToString:@"hintText"]) {
self.placeholderLabel.text = (NSString *)prop;
} else if ([name isEqualToString:@"hintTextColor"]) {
self.placeholderLabel.textColor = DoricColor(prop);
} else if ([name isEqualToString:@"onTextChange"]) {
if ([prop isKindOfClass:[NSString class]]) {
self.onTextChange = ^(NSString *text, DoricInputNode *node) {
[node callJSResponse:prop,text,nil];
};
}else {
self.onTextChange = nil;
}
} else if ([name isEqualToString:@"onFocusChange"]) {
if ([prop isKindOfClass:[NSString class]]) {
self.onFocusShange = ^(BOOL focused, DoricInputNode *node) {
[node callJSResponse:prop,@(focused),nil];
};
}else {
self.onFocusShange = nil;
}
} else{
[super blendView:view forPropName:name propValue:prop];
}
}
- (void)blend:(NSDictionary *)props {
[super blend:props];
[self updatePlaceholderLabel];
[self.view.superview setNeedsLayout];
}
#pragma mark - Doric-JS api
- (NSString *)getText {
return self.view.text;
}
- (void)setSelection:(NSDictionary *)params withPromise:(DoricPromise *)promise {
NSString *start = params[@"start"];
NSString *end = params[@"end"];
if (([start isKindOfClass:[NSString class]] || [start isKindOfClass:[NSNumber class]]) &&
([start isKindOfClass:[NSString class]] || [start isKindOfClass:[NSNumber class]])) {
self.view.selectedRange = NSMakeRange(start.intValue, end.intValue - start.intValue);
}
[promise resolve:nil];
}
- (void)requestFocus {
[self.view becomeFirstResponder];
}
- (void)releaseFocus {
[self.view resignFirstResponder];
}
#pragma mark - UITextViewDelegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
if (self.onFocusShange) {
self.onFocusShange(YES, self);
}
return YES;
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView {
if (self.onFocusShange) {
self.onFocusShange(NO, self);
}
return YES;
}
- (void)textViewDidChange:(UITextView *)textView {
if (self.onTextChange) {
self.onTextChange(textView.text, self);
}
[self updatePlaceholderLabel];
}
#pragma mark - placeholderLabel
- (UILabel *)placeholderLabel {
if (!_placeholderLabel) {
_placeholderLabel = [[UILabel alloc] init];
_placeholderLabel.numberOfLines = 0;
_placeholderLabel.userInteractionEnabled = NO;
}
return _placeholderLabel;
}
- (void)updatePlaceholderLabel {
if (self.view.text.length) {
[self.placeholderLabel removeFromSuperview];
return;
} else {
[self.view insertSubview:self.placeholderLabel atIndex:0];
}
self.placeholderLabel.textAlignment = self.view.textAlignment;
CGFloat lineFragmentPadding = self.view.textContainer.lineFragmentPadding;
UIEdgeInsets textContainerInset = self.view.textContainerInset;
CGFloat x = lineFragmentPadding + textContainerInset.left;
CGFloat y = textContainerInset.top;
CGFloat width = CGRectGetWidth(self.view.bounds) - x - lineFragmentPadding - textContainerInset.right;
CGFloat height = [self.placeholderLabel sizeThatFits:CGSizeMake(width, 0)].height;
self.placeholderLabel.frame = CGRectMake(x, y, width, height);
}
@end

View File

@ -18,8 +18,11 @@
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKit.h>
typedef UIEdgeInsets DoricMargin;
typedef UIEdgeInsets DoricPadding;
DoricMargin DoricMarginMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom);
@ -82,6 +85,10 @@ typedef NS_ENUM(NSInteger, DoricGravity) {
@property(nonatomic, strong) DoricLayoutConfig *layoutConfig;
@end
@interface UIView (DoricPadding)
@property(nonatomic, assign) DoricPadding padding;
@end
@interface UIView (DoricTag)
@property(nonatomic, copy) NSString *tagString;

View File

@ -19,7 +19,6 @@
#import "DoricLayouts.h"
#import <objc/runtime.h>
#import <Doric/DoricLayouts.h>
#import "UIView+Doric.h"
static const void *kLayoutConfig = &kLayoutConfig;
@ -37,6 +36,24 @@ - (DoricLayoutConfig *)layoutConfig {
@end
static const void *kLayoutPadding = &kLayoutPadding;
@implementation UIView (DoricPadding)
@dynamic padding;
- (void)setPadding:(DoricPadding)padding {
objc_setAssociatedObject(self, kLayoutPadding, [NSValue value:&padding withObjCType:@encode(DoricPadding)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (DoricPadding)padding {
DoricPadding value;
value.left = value.right = value.top = value.bottom = 0;
[objc_getAssociatedObject(self, kLayoutPadding) getValue:&value];
return value;
}
@end
static const void *kTagString = &kTagString;
@implementation UIView (DoricTag)
@ -79,13 +96,15 @@ - (CGSize)measureSize:(CGSize)targetSize {
|| config.heightSpec == DoricLayoutWrapContent) {
height = targetSize.height - config.margin.top - config.margin.bottom;
}
CGSize contentSize = [self sizeThatFits:CGSizeMake(width, height)];
DoricPadding padding = self.padding;
CGSize contentSize = [self sizeThatFits:CGSizeMake(
width - padding.left - padding.right,
height - padding.top - padding.bottom)];
if (config.widthSpec == DoricLayoutWrapContent) {
width = contentSize.width;
width = contentSize.width + padding.left + padding.right;
}
if (config.heightSpec == DoricLayoutWrapContent) {
height = contentSize.height;
height = contentSize.height + padding.left + padding.top + padding.bottom;
}
return CGSizeMake(width, height);
}
@ -208,6 +227,8 @@ - (CGSize)sizeThatFits:(CGSize)size {
- (void)layoutSelf:(CGSize)targetSize {
self.width = targetSize.width;
self.height = targetSize.height;
DoricPadding padding = self.padding;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
@ -219,33 +240,35 @@ - (void)layoutSelf:(CGSize)targetSize {
if (!childConfig) {
childConfig = [DoricLayoutConfig new];
}
CGSize size = [child measureSize:CGSizeMake(targetSize.width, targetSize.height)];
CGSize size = [child measureSize:CGSizeMake(
targetSize.width - padding.left - padding.right,
targetSize.height - padding.top - padding.bottom)];
[child layoutSelf:size];
DoricGravity gravity = childConfig.alignment;
if ((gravity & LEFT) == LEFT) {
child.left = 0;
child.left = padding.left;
} else if ((gravity & RIGHT) == RIGHT) {
child.right = targetSize.width;
child.right = targetSize.width - padding.right;
} else if ((gravity & CENTER_X) == CENTER_X) {
child.centerX = targetSize.width / 2;
} else {
if (childConfig.margin.left) {
child.left = childConfig.margin.left;
child.left = childConfig.margin.left + padding.left;
} else if (childConfig.margin.right) {
child.right = targetSize.width - childConfig.margin.right;
child.right = targetSize.width - childConfig.margin.right - padding.right;
}
}
if ((gravity & TOP) == TOP) {
child.top = 0;
child.top = padding.top;
} else if ((gravity & BOTTOM) == BOTTOM) {
child.bottom = targetSize.height;
child.bottom = targetSize.height - padding.bottom;
} else if ((gravity & CENTER_Y) == CENTER_Y) {
child.centerY = targetSize.height / 2;
} else {
if (childConfig.margin.top) {
child.top = childConfig.margin.top;
child.top = childConfig.margin.top + padding.top;
} else if (childConfig.margin.bottom) {
child.bottom = targetSize.height - childConfig.margin.bottom;
child.bottom = targetSize.height - childConfig.margin.bottom - padding.bottom;
}
}
}
@ -292,15 +315,16 @@ - (CGSize)sizeThatFits:(CGSize)size {
- (void)layoutSelf:(CGSize)targetSize {
self.width = targetSize.width;
self.height = targetSize.height;
CGFloat yStart = 0;
DoricPadding padding = self.padding;
CGFloat yStart = padding.top;
if ((self.gravity & TOP) == TOP) {
yStart = 0;
yStart = padding.top;
} else if ((self.gravity & BOTTOM) == BOTTOM) {
yStart = targetSize.height - self.contentHeight;
yStart = targetSize.height - self.contentHeight - padding.bottom;
} else if ((self.gravity & CENTER_Y) == CENTER_Y) {
yStart = (targetSize.height - self.contentHeight) / 2;
yStart = (targetSize.height - self.contentHeight - padding.top - padding.bottom) / 2 + padding.top;
}
CGFloat remain = targetSize.height - self.contentHeight;
CGFloat remain = targetSize.height - self.contentHeight - padding.top - padding.bottom;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
@ -313,24 +337,26 @@ - (void)layoutSelf:(CGSize)targetSize {
childConfig = [DoricLayoutConfig new];
}
CGSize size = [child measureSize:CGSizeMake(targetSize.width, targetSize.height - yStart)];
CGSize size = [child measureSize:CGSizeMake(
targetSize.width - padding.left - padding.right,
targetSize.height - yStart - padding.bottom)];
if (childConfig.weight) {
size.height += remain / self.contentWeight * childConfig.weight;
}
[child layoutSelf:size];
DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & LEFT) == LEFT) {
child.left = 0;
child.left = padding.left;
} else if ((gravity & RIGHT) == RIGHT) {
child.right = self.width;
child.right = self.width - padding.right;
} else if ((gravity & CENTER_X) == CENTER_X) {
child.centerX = targetSize.width / 2;
} else if (childConfig.margin.left) {
child.left = childConfig.margin.left + padding.left;
} else if (childConfig.margin.right) {
child.right = targetSize.width - childConfig.margin.right - padding.right;
} else {
if (childConfig.margin.left) {
child.left = childConfig.margin.left;
} else if (childConfig.margin.right) {
child.right = targetSize.width - childConfig.margin.right;
}
child.left = padding.left;
}
if (childConfig.margin.top) {
yStart += childConfig.margin.top;
@ -380,17 +406,16 @@ - (CGSize)sizeThatFits:(CGSize)size {
- (void)layoutSelf:(CGSize)targetSize {
self.width = targetSize.width;
self.height = targetSize.height;
CGFloat xStart = 0;
if (self.contentWeight) {
xStart = 0;
} else if ((self.gravity & LEFT) == LEFT) {
xStart = 0;
DoricPadding padding = self.padding;
CGFloat xStart = padding.left;
if ((self.gravity & LEFT) == LEFT) {
xStart = padding.left;
} else if ((self.gravity & RIGHT) == RIGHT) {
xStart = targetSize.width - self.contentWidth;
xStart = targetSize.width - self.contentWidth - padding.right;
} else if ((self.gravity & CENTER_X) == CENTER_X) {
xStart = (targetSize.width - self.contentWidth) / 2;
xStart = (targetSize.width - self.contentWidth - padding.left - padding.right) / 2 + padding.left;
}
CGFloat remain = targetSize.width - self.contentWidth;
CGFloat remain = targetSize.width - self.contentWidth - padding.left - padding.right;
for (UIView *child in self.subviews) {
if (child.isHidden) {
continue;
@ -403,7 +428,9 @@ - (void)layoutSelf:(CGSize)targetSize {
childConfig = [DoricLayoutConfig new];
}
CGSize size = [child measureSize:CGSizeMake(targetSize.width - xStart, targetSize.height)];
CGSize size = [child measureSize:CGSizeMake(
targetSize.width - xStart - padding.right,
targetSize.height - padding.top - padding.bottom)];
if (childConfig.weight) {
size.width += remain / self.contentWeight * childConfig.weight;
}
@ -412,17 +439,17 @@ - (void)layoutSelf:(CGSize)targetSize {
DoricGravity gravity = childConfig.alignment | self.gravity;
if ((gravity & TOP) == TOP) {
child.top = 0;
child.top = padding.top;
} else if ((gravity & BOTTOM) == BOTTOM) {
child.bottom = targetSize.height;
child.bottom = targetSize.height - padding.bottom;
} else if ((gravity & CENTER_Y) == CENTER_Y) {
child.centerY = targetSize.height / 2;
} else if (childConfig.margin.top) {
child.top = childConfig.margin.top + padding.top;
} else if (childConfig.margin.bottom) {
child.bottom = targetSize.height - childConfig.margin.bottom - padding.bottom;
} else {
if (childConfig.margin.top) {
child.top = childConfig.margin.top;
} else if (childConfig.margin.bottom) {
child.bottom = targetSize.height - childConfig.margin.bottom;
}
child.top = padding.top;
}
if (childConfig.margin.left) {

View File

@ -62,6 +62,10 @@ @interface DoricListNode () <UITableViewDataSource, UITableViewDelegate>
@property(nonatomic, strong) NSMutableDictionary <NSNumber *, NSNumber *> *itemHeights;
@property(nonatomic, assign) NSUInteger itemCount;
@property(nonatomic, assign) NSUInteger batchCount;
@property(nonatomic, copy) NSString *onLoadMoreFuncId;
@property(nonatomic, copy) NSString *renderItemFuncId;
@property(nonatomic, copy) NSString *loadMoreViewId;
@property(nonatomic, assign) BOOL loadMore;
@end
@implementation DoricListNode
@ -86,6 +90,7 @@ - (UITableView *)build {
it.dataSource = self;
it.delegate = self;
it.separatorStyle = UITableViewCellSeparatorStyleNone;
it.allowsSelection = NO;
}];
}
@ -94,11 +99,22 @@ - (void)blendView:(UITableView *)view forPropName:(NSString *)name propValue:(id
self.itemCount = [prop unsignedIntegerValue];
[self.view reloadData];
} else if ([@"renderItem" isEqualToString:name]) {
[self.itemViewIds removeAllObjects];
[self clearSubModel];
[self.view reloadData];
if (![self.renderItemFuncId isEqualToString:prop]) {
self.renderItemFuncId = prop;
[self.itemViewIds.allValues forEach:^(NSString *obj) {
[self removeSubModel:obj];
}];
[self.itemViewIds removeAllObjects];
[self.view reloadData];
}
} else if ([@"batchCount" isEqualToString:name]) {
self.batchCount = [prop unsignedIntegerValue];
} else if ([@"onLoadMore" isEqualToString:name]) {
self.onLoadMoreFuncId = prop;
} else if ([@"loadMoreView" isEqualToString:name]) {
self.loadMoreViewId = prop;
} else if ([@"loadMore" isEqualToString:name]) {
self.loadMore = [prop boolValue];
} else {
[super blendView:view forPropName:name propValue:prop];
}
@ -109,7 +125,7 @@ - (void)blend:(NSDictionary *)props {
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.itemCount;
return self.itemCount + (self.loadMore ? 1 : 0);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -117,7 +133,10 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
NSDictionary *model = [self itemModelAt:position];
NSDictionary *props = model[@"props"];
NSString *reuseId = props[@"identifier"];
if (position > 0 && position >= self.itemCount && self.onLoadMoreFuncId) {
reuseId = @"doricLoadMoreCell";
[self callJSResponse:self.onLoadMoreFuncId, nil];
}
DoricTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId ?: @"doriccell"];
if (!cell) {
cell = [[DoricTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseId ?: @"doriccell"];
@ -147,6 +166,9 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa
}
- (NSDictionary *)itemModelAt:(NSUInteger)position {
if (position >= self.itemCount) {
return [self subModelOf:self.loadMoreViewId];
}
NSString *viewId = self.itemViewIds[@(position)];
if (viewId && viewId.length > 0) {
return [self subModelOf:viewId];
@ -160,29 +182,37 @@ - (NSDictionary *)itemModelAt:(NSUInteger)position {
NSUInteger pos = position + idx;
self.itemViewIds[@(pos)] = thisViewId;
}];
return array[0];
if (array.count > 0) {
return array[0];
} else {
return nil;
}
}
}
- (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 reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
///Here async blend sub node because the item count need to be applied first.
dispatch_async(dispatch_get_main_queue(), ^{
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 reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
}
}];
});
}
- (void)callItem:(NSUInteger)position height:(CGFloat)height {

View 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/12/7.
//
#import <Foundation/Foundation.h>
#import "DoricGroupNode.h"
@interface DoricNestedSliderNode : DoricGroupNode<UIScrollView *>
@end

View File

@ -0,0 +1,101 @@
/*
* 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/12/7.
//
#import "DoricNestedSliderNode.h"
#import "Doric.h"
@interface DoricNestedSliderView : UIScrollView
@end
@implementation DoricNestedSliderView
- (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.subviews forEachIndexed:^(__kindof UIView *obj, NSUInteger idx) {
obj.left = idx * self.width;
}];
[self setContentSize:CGSizeMake(self.subviews.count * self.width, self.height)];
}
@end
@interface DoricNestedSliderNode () <UIScrollViewDelegate>
@property(nonatomic, copy) NSString *onPageSelectedFuncId;
@property(nonatomic, assign) NSUInteger lastPosition;
@end
@implementation DoricNestedSliderNode
- (UIScrollView *)build {
return [[DoricNestedSliderView new] also:^(DoricNestedSliderView *it) {
it.delegate = self;
it.pagingEnabled = YES;
[it setShowsVerticalScrollIndicator:NO];
[it setShowsHorizontalScrollIndicator:NO];
}];
}
- (void)blendView:(UIScrollView *)view forPropName:(NSString *)name propValue:(id)prop {
if ([@"onPageSlided" isEqualToString:name]) {
self.onPageSelectedFuncId = prop;
} else {
[super blendView:view forPropName:name propValue:prop];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSUInteger pageIndex = (NSUInteger) (scrollView.contentOffset.x / scrollView.width);
[scrollView setContentOffset:CGPointMake(pageIndex * scrollView.width, scrollView.contentOffset.y) animated:YES];
if (self.onPageSelectedFuncId && self.onPageSelectedFuncId.length > 0) {
if (pageIndex != self.lastPosition) {
[self callJSResponse:self.onPageSelectedFuncId, @(pageIndex), nil];
}
}
self.lastPosition = pageIndex;
}
- (void)slidePage:(NSDictionary *)params withPromise:(DoricPromise *)promise {
NSUInteger pageIndex = [params[@"page"] unsignedIntegerValue];
BOOL smooth = [params[@"smooth"] boolValue];
[self.view setContentOffset:CGPointMake(pageIndex * self.view.width, self.view.contentOffset.y) animated:smooth];
[promise resolve:nil];
self.lastPosition = pageIndex;
if (self.onPageSelectedFuncId && self.onPageSelectedFuncId.length > 0) {
[self callJSResponse:self.onPageSelectedFuncId, @(pageIndex), nil];
}
}
- (NSNumber *)getSlidedPage {
NSUInteger pageIndex = (NSUInteger) (self.view.contentOffset.x / self.view.width);
return @(pageIndex);
}
@end

View File

@ -54,7 +54,11 @@ @interface DoricScrollerNode ()
@implementation DoricScrollerNode
- (DoricScrollView *)build {
return [DoricScrollView new];
return [[DoricScrollView new] also:^(DoricScrollView *it) {
if (@available(iOS 11, *)) {
it.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
}];
}
- (void)initWithSuperNode:(DoricSuperNode *)superNode {

View File

@ -35,6 +35,9 @@ @interface DoricSliderNode () <UICollectionViewDataSource, UICollectionViewDeleg
@property(nonatomic, strong) NSMutableDictionary <NSNumber *, NSString *> *itemViewIds;
@property(nonatomic, assign) NSUInteger itemCount;
@property(nonatomic, assign) NSUInteger batchCount;
@property(nonatomic, copy) NSString *onPageSelectedFuncId;
@property(nonatomic, assign) NSUInteger lastPosition;
@property(nonatomic, copy) NSString *renderPageFuncId;
@end
@interface DoricSliderView : UICollectionView
@ -90,11 +93,18 @@ - (void)blendView:(UICollectionView *)view forPropName:(NSString *)name propValu
self.itemCount = [prop unsignedIntegerValue];
[self.view reloadData];
} else if ([@"renderPage" isEqualToString:name]) {
[self.itemViewIds removeAllObjects];
[self clearSubModel];
[self.view reloadData];
if ([self.renderPageFuncId isEqualToString:prop]) {
} else {
[self.itemViewIds removeAllObjects];
[self clearSubModel];
[self.view reloadData];
self.renderPageFuncId = prop;
}
} else if ([@"batchCount" isEqualToString:name]) {
self.batchCount = [prop unsignedIntegerValue];
} else if ([@"onPageSlided" isEqualToString:name]) {
self.onPageSelectedFuncId = prop;
} else {
[super blendView:view forPropName:name propValue:prop];
}
@ -197,5 +207,28 @@ - (void)blendSubNode:(NSDictionary *)subModel {
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSUInteger pageIndex = (NSUInteger) (scrollView.contentOffset.x / scrollView.width);
scrollView.contentOffset = CGPointMake(pageIndex * scrollView.width, scrollView.contentOffset.y);
if (self.onPageSelectedFuncId && self.onPageSelectedFuncId.length > 0) {
if (pageIndex != self.lastPosition) {
[self callJSResponse:self.onPageSelectedFuncId, @(pageIndex), nil];
}
}
self.lastPosition = pageIndex;
}
- (void)slidePage:(NSDictionary *)params withPromise:(DoricPromise *)promise {
NSUInteger pageIndex = [params[@"page"] unsignedIntegerValue];
BOOL smooth = [params[@"smooth"] boolValue];
[self.view setContentOffset:CGPointMake(pageIndex * self.view.width, self.view.contentOffset.y) animated:smooth];
[promise resolve:nil];
self.lastPosition = pageIndex;
if (self.onPageSelectedFuncId && self.onPageSelectedFuncId.length > 0) {
[self callJSResponse:self.onPageSelectedFuncId, @(pageIndex), nil];
}
}
- (NSNumber *)getSlidedPage {
NSUInteger pageIndex = (NSUInteger) (self.view.contentOffset.x / self.view.width);
return @(pageIndex);
}
@end

View File

@ -35,6 +35,8 @@
- (void)clearSubModel;
- (void)removeSubModel:(NSString *)viewId;
- (DoricViewNode *)subNodeWithViewId:(NSString *)viewId;
- (void)recursiveMixin:(NSDictionary *)srcModel to:(NSMutableDictionary *)targetModel;

View File

@ -62,7 +62,6 @@ - (void)mixin:(NSDictionary *)srcModel to:(NSMutableDictionary *)targetModel {
targetProp[key] = obj;
}
}];
targetModel[@"props"] = targetProp;
}
- (void)recursiveMixin:(NSDictionary *)srcModel to:(NSMutableDictionary *)targetModel {
@ -149,11 +148,16 @@ - (void)clearSubModel {
[self.subNodes removeAllObjects];
}
- (void)removeSubModel:(NSString *)viewId {
[self.subNodes removeObjectForKey:viewId];
}
- (DoricViewNode *)subNodeWithViewId:(NSString *)viewId {
NSAssert(NO, @"Should override class:%@ ,method:%@.", NSStringFromClass([self class]),
NSStringFromSelector(_cmd));
NSStringFromSelector(_cmd));
return nil;
}
- (void)requestLayout {
[self.view setNeedsLayout];
}

View File

@ -48,6 +48,8 @@ - (void)blendView:(UILabel *)view forPropName:(NSString *)name propValue:(id)pro
alignment = NSTextAlignmentRight;
}
view.textAlignment = alignment;
} else if ([name isEqualToString:@"maxLines"]) {
view.numberOfLines = [prop integerValue];
} else {
[super blendView:view forPropName:name propValue:prop];
}

View File

@ -235,7 +235,6 @@ - (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop
} else {
view.clipsToBounds = YES;
}
} else if ([name isEqualToString:@"translationX"]) {
self.translationX = prop;
} else if ([name isEqualToString:@"translationY"]) {
@ -250,6 +249,19 @@ - (void)blendView:(UIView *)view forPropName:(NSString *)name propValue:(id)prop
self.pivotY = prop;
} else if ([name isEqualToString:@"rotation"]) {
self.rotation = prop;
} else if ([name isEqualToString:@"padding"]) {
DoricPadding padding;
padding.left = padding.right = padding.top = padding.bottom = 0;
if ([prop isKindOfClass:[NSDictionary class]]) {
NSDictionary *dictionary = prop;
padding.left = [dictionary[@"left"] floatValue];
padding.right = [dictionary[@"right"] floatValue];
padding.top = [dictionary[@"top"] floatValue];
padding.bottom = [dictionary[@"bottom"] floatValue];
}
self.view.padding = padding;
} else if ([name isEqualToString:@"hidden"]) {
self.view.hidden = [prop boolValue];
} else {
DoricLog(@"Blend View error for View Type :%@, prop is %@", self.class, name);
}
@ -305,6 +317,11 @@ - (NSNumber *)getHeight {
return @(self.view.height);
}
- (NSDictionary *)getLocationOnScreen {
CGPoint point = [self.view convertPoint:CGPointMake(0, 0) toView:[UIApplication sharedApplication].windows.lastObject];
return @{@"x": @(point.x), @"y": @(point.y)};
}
- (void)blendLayoutConfig:(NSDictionary *)params {
[params[@"widthSpec"] also:^(NSNumber *it) {
if (it) {
@ -357,6 +374,8 @@ - (NSDictionary *)transformation {
return dictionary;
}
#pragma animations
- (void)doAnimation:(id)params withPromise:(DoricPromise *)promise {
CAAnimation *animation = [self parseAnimation:params];
AnimationCallback *originDelegate = animation.delegate;
@ -371,6 +390,7 @@ - (void)doAnimation:(id)params withPromise:(DoricPromise *)promise {
if (originDelegate) {
originDelegate.endBlock(callback);
}
[self.view.layer removeAllAnimations];
[self transformProperties];
[promise resolve:self.transformation];
};
@ -379,6 +399,8 @@ - (void)doAnimation:(id)params withPromise:(DoricPromise *)promise {
if (params[@"delay"]) {
animation.beginTime = CACurrentMediaTime() + [params[@"delay"] floatValue] / 1000;
}
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.view.layer addAnimation:animation forKey:nil];
}

View File

@ -49,7 +49,7 @@ - (void)setupError:(NSException *)exception {
}
- (BOOL)hasResult {
return self.result;
return self.result != nil;
}
- (id)getResult {

View File

@ -26,7 +26,7 @@ extern NSString *const DORIC_BUNDLE_SANDBOX;
extern NSString *const DORIC_BUNDLE_LIB;
extern NSString *const DORIC_MODULE_LIB;
extern NSString *const INJECT_ENVIRONMENT;
extern NSString *const INJECT_LOG;
extern NSString *const INJECT_REQUIRE;
extern NSString *const INJECT_TIMER_SET;

View File

@ -26,6 +26,7 @@
NSString *const DORIC_BUNDLE_LIB = @"doric-lib";
NSString *const DORIC_MODULE_LIB = @"doric";
NSString *const INJECT_ENVIRONMENT = @"Environment";
NSString *const INJECT_LOG = @"nativeLog";
NSString *const INJECT_REQUIRE = @"nativeRequire";

View File

@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, DoricJSRemoteArgType) {
DoricJSRemoteArgTypeNil = 0,
DoricJSRemoteArgTypeInteger,
DoricJSRemoteArgTypeNumber,
DoricJSRemoteArgTypeBool,
DoricJSRemoteArgTypeString,
DoricJSRemoteArgTypeObject,
@ -20,4 +20,5 @@ typedef NS_ENUM(NSUInteger, DoricJSRemoteArgType) {
DoricJSRemoteArgType DoricargTypeWithArg(id arg);
NS_ASSUME_NONNULL_END

View File

@ -7,6 +7,15 @@
#import "DoricJSRemoteArgType.h"
DoricJSRemoteArgType DoricargTypeWithArg(id arg) {
// TODO:
return DoricJSRemoteArgTypeString;
DoricJSRemoteArgType type = DoricJSRemoteArgTypeNil;
if ([arg isKindOfClass:[NSNumber class]]) {
type = DoricJSRemoteArgTypeNumber;
}else if ([arg isKindOfClass:[NSString class]]) {
type = DoricJSRemoteArgTypeString;
}else if ([arg isKindOfClass:[NSDictionary class]]) {
type = DoricJSRemoteArgTypeObject;
}else if ([arg isKindOfClass:[NSMutableArray class]]) {
type = DoricJSRemoteArgTypeArray;
}
return type;
}

View File

@ -39,4 +39,4 @@ NSBundle *_Nonnull DoricBundle(void);
void ShowToast(NSString *_Nonnull text, DoricGravity gravity);
UIImage *_Nonnull UIImageWithColor(UIColor *color);
UIImage *_Nonnull UIImageWithColor(UIColor * _Nonnull color);

3
doric-iOS/README.md Normal file
View File

@ -0,0 +1,3 @@
# Doric iOS SDK
## Usages