From 01b30f48bb853e9620ab7c609e94ffb5e97cddd4 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Fri, 7 Jul 2023 18:31:06 +0800 Subject: [PATCH] iOS: support swift plugin and library --- .../Example/Example.xcodeproj/project.pbxproj | 16 ++++++++ .../Example/Example/DemoSwiftLibrary.swift | 28 ++++++++++++++ doric-iOS/Example/Example/DemoVC.swift | 38 +++++++++++++++++++ .../Example/Example/Example-Bridging-Header.h | 8 ++++ doric-iOS/Example/Example/ViewController.m | 13 ++++--- .../Classes/Extension/DoricBridgeExtension.m | 8 +++- .../Pod/Classes/Plugin/DoricShaderPlugin.m | 8 +++- 7 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 doric-iOS/Example/Example/DemoSwiftLibrary.swift create mode 100644 doric-iOS/Example/Example/DemoVC.swift create mode 100644 doric-iOS/Example/Example/Example-Bridging-Header.h diff --git a/doric-iOS/Example/Example.xcodeproj/project.pbxproj b/doric-iOS/Example/Example.xcodeproj/project.pbxproj index da50dc58..d9c19af9 100644 --- a/doric-iOS/Example/Example.xcodeproj/project.pbxproj +++ b/doric-iOS/Example/Example.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 8BCADA7C23CD5B65005EEF96 /* NavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCADA7B23CD5B64005EEF96 /* NavigationController.m */; }; 8BE3A340287C098100D399FA /* DoricPanelListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BE3A33E287C098000D399FA /* DoricPanelListViewController.m */; }; D751D4B065D8D4FA6594B5EE /* DemoVC.m in Sources */ = {isa = PBXBuildFile; fileRef = D751D19E97EF4EDD7588FEBE /* DemoVC.m */; }; + D751D7B06B4A1305879FCAA0 /* DemoSwiftLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D751D9EDC0E8CEFFABAF3DEA /* DemoSwiftLibrary.swift */; }; 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 */; }; @@ -23,6 +24,7 @@ E2334B0822E9D2070098A085 /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334B0722E9D2070098A085 /* ExampleTests.m */; }; E2334B1322E9D2070098A085 /* ExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334B1222E9D2070098A085 /* ExampleUITests.m */; }; E24217DA287E999900F4DBEA /* DoricEmbeddedExampleVC.m in Sources */ = {isa = PBXBuildFile; fileRef = E24217D9287E999900F4DBEA /* DoricEmbeddedExampleVC.m */; }; + E29908682A57C48A00272415 /* DemoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E29908672A57C48A00272415 /* DemoVC.swift */; }; E2C9315923B0A263007933D9 /* src in Resources */ = {isa = PBXBuildFile; fileRef = E2C9315823B0A263007933D9 /* src */; }; E2EF0C0F275F6702007801C5 /* iconfont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E2EF0C0E275F6702007801C5 /* iconfont.ttf */; }; E2EF0C13275F6934007801C5 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = E2EF0C12275F6934007801C5 /* assets */; }; @@ -60,6 +62,7 @@ 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 = ""; }; D751D19E97EF4EDD7588FEBE /* DemoVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoVC.m; sourceTree = ""; }; D751D2175D09F2C10691FB81 /* DemoLibrary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoLibrary.m; sourceTree = ""; }; + D751D9EDC0E8CEFFABAF3DEA /* DemoSwiftLibrary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DemoSwiftLibrary.swift; sourceTree = ""; }; D751DB0CB3009E12990F661E /* DemoLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoLibrary.h; sourceTree = ""; }; D751DDEC114E037231257E64 /* DemoVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoVC.h; sourceTree = ""; }; 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 = ""; }; @@ -81,6 +84,8 @@ E2334B1422E9D2070098A085 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E24217D9287E999900F4DBEA /* DoricEmbeddedExampleVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DoricEmbeddedExampleVC.m; sourceTree = ""; }; E24217DB287E99D100F4DBEA /* DoricEmbeddedExampleVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DoricEmbeddedExampleVC.h; sourceTree = ""; }; + E29908672A57C48A00272415 /* DemoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoVC.swift; sourceTree = ""; }; + E29908692A57C4DF00272415 /* Example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Example-Bridging-Header.h"; sourceTree = ""; }; E2C9315823B0A263007933D9 /* src */ = {isa = PBXFileReference; lastKnownFileType = folder; name = src; path = "../../../doric-demo/bundle/src"; sourceTree = ""; }; E2EF0C0E275F6702007801C5 /* iconfont.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = iconfont.ttf; path = "../../doric-demo/bundle/assets/iconfont.ttf"; sourceTree = ""; }; E2EF0C12275F6934007801C5 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = assets; path = "../../../doric-demo/bundle/assets"; sourceTree = ""; }; @@ -189,6 +194,9 @@ E24217DB287E99D100F4DBEA /* DoricEmbeddedExampleVC.h */, E2F3CCAF2918B44800772FF1 /* DemoSSRVC.m */, E2F3CCB12918B49500772FF1 /* DemoSSRVC.h */, + E29908672A57C48A00272415 /* DemoVC.swift */, + E29908692A57C4DF00272415 /* Example-Bridging-Header.h */, + D751D9EDC0E8CEFFABAF3DEA /* DemoSwiftLibrary.swift */, ); path = Example; sourceTree = ""; @@ -457,12 +465,14 @@ 8BE3A340287C098100D399FA /* DoricPanelListViewController.m in Sources */, E2334AF322E9D2060098A085 /* ViewController.m in Sources */, E2334AFE22E9D2070098A085 /* main.m in Sources */, + E29908682A57C48A00272415 /* DemoVC.swift in Sources */, E24217DA287E999900F4DBEA /* DoricEmbeddedExampleVC.m in Sources */, E2334AF022E9D2060098A085 /* AppDelegate.m in Sources */, E2F3CCB02918B44800772FF1 /* DemoSSRVC.m in Sources */, D751D4B065D8D4FA6594B5EE /* DemoVC.m in Sources */, D751DDB012BAF476A252CD93 /* DemoLibrary.m in Sources */, 8BCADA7C23CD5B65005EEF96 /* NavigationController.m in Sources */, + D751D7B06B4A1305879FCAA0 /* DemoSwiftLibrary.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -636,6 +646,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 7EE2RX3L3P; GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; INFOPLIST_FILE = Example/Info.plist; @@ -660,6 +671,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 7EE2RX3L3P; GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp; INFOPLIST_FILE = Example/Info.plist; @@ -680,6 +692,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = D91241144B5A3356A3C60644 /* Pods-ExampleTests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ExampleTests/Info.plist; @@ -699,6 +712,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = B93D4DB00FD244178B7CE7C4 /* Pods-ExampleTests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ExampleTests/Info.plist; @@ -718,6 +732,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 016E930415B91D826F9FFF47 /* Pods-ExampleUITests.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ExampleUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -736,6 +751,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = B93423722F2E06DC238CDD18 /* Pods-ExampleUITests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ExampleUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/doric-iOS/Example/Example/DemoSwiftLibrary.swift b/doric-iOS/Example/Example/DemoSwiftLibrary.swift new file mode 100644 index 00000000..0aa2b135 --- /dev/null +++ b/doric-iOS/Example/Example/DemoSwiftLibrary.swift @@ -0,0 +1,28 @@ +// +// Created by pengfei.zhou on 2023/7/7. +// Copyright (c) 2023 pengfei.zhou. All rights reserved. +// + +import Foundation + +class DemoSwiftPlugin: DoricNativePlugin { + @objc func test() { + print("Here at test") + } + + @objc func testData(data: String) { + print("Here at test, data is " + data) + } + + @objc func testReturn(data: String,promise: DoricPromise) { + print("Here at test, promise ") + promise.resolve("This is from native") + } +} + + +class DemoSwiftLibrary: DoricLibrary { + override func load(_ registry: DoricRegistry!) { + registry.registerNativePlugin(DemoSwiftPlugin.self, withName: "demoSwift"); + } +} diff --git a/doric-iOS/Example/Example/DemoVC.swift b/doric-iOS/Example/Example/DemoVC.swift new file mode 100644 index 00000000..9a2ffdde --- /dev/null +++ b/doric-iOS/Example/Example/DemoVC.swift @@ -0,0 +1,38 @@ +// +// DemoVC.swift +// Example +// +// Created by pengfei.zhou on 2023/7/7. +// Copyright © 2023 pengfei.zhou. All rights reserved. +// + +import UIKit + +class DemoVC: UIViewController { + let filePath: String + + @objc init(path: String) { + filePath = path; + super.init(nibName: nil, bundle: nil) + + } + + required init?(coder: NSCoder) { + filePath = ""; + super.init(coder: coder) + } + + override func viewDidLoad() { + super.viewDidLoad(); + title = filePath; + view.backgroundColor = UIColor.white; + let jsContent = try? String(contentsOfFile: Bundle.main.bundlePath + "/src/" + filePath, + encoding: String.Encoding.utf8) + let doricPanel = DoricPanel() + doricPanel.view.width = view.width + doricPanel.view.height = view.height + view.addSubview(doricPanel.view) + addChild(doricPanel) + doricPanel.config(jsContent, alias: filePath, extra: nil) + } +} diff --git a/doric-iOS/Example/Example/Example-Bridging-Header.h b/doric-iOS/Example/Example/Example-Bridging-Header.h new file mode 100644 index 00000000..2fc7c462 --- /dev/null +++ b/doric-iOS/Example/Example/Example-Bridging-Header.h @@ -0,0 +1,8 @@ +// +// Example-Bridging-Header.h +// Example +// +// Created by pengfei.zhou on 2023/7/7. +// Copyright © 2023 pengfei.zhou. All rights reserved. +// +#import diff --git a/doric-iOS/Example/Example/ViewController.m b/doric-iOS/Example/Example/ViewController.m index 76b44e47..f3f28b80 100644 --- a/doric-iOS/Example/Example/ViewController.m +++ b/doric-iOS/Example/Example/ViewController.m @@ -13,6 +13,7 @@ #import "DoricPanelListViewController.h" #import "DoricEmbeddedExampleVC.h" #import "DemoSSRVC.h" +#import "Doric_Playground-Swift.h" @interface ViewController () @property(nonatomic, copy) NSArray *demoFilePaths; @@ -44,6 +45,7 @@ - (void)viewDidLoad { self.demoFilePaths = tmp; [Doric registerLibrary:[DemoLibrary new]]; + [Doric registerLibrary:[DemoSwiftLibrary new]]; [Doric enablePerformance:YES]; [Doric enableRenderSnapshot:YES]; @@ -118,11 +120,12 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath DemoSSRVC *vc = [[DemoSSRVC alloc] initWithPath:file]; [self.navigationController pushViewController:vc animated:NO]; } else { - DoricViewController *doricViewController = [[DoricViewController alloc] - initWithSource:[NSString stringWithFormat:@"assets://src/%@", file] - alias:@"__dev__"//self.demoFilePaths[(NSUInteger) indexPath.row] - extra:nil - ]; + DemoVC *doricViewController = [[DemoVC alloc] initWithPath:file]; +// DemoVC *doricViewController = [[DemoVC alloc] +// initWithSource:[NSString stringWithFormat:@"assets://src/%@", file] +// alias:@"__dev__"//self.demoFilePaths[(NSUInteger) indexPath.row] +// extra:nil +// ]; UIBarButtonItem *rightBarItem = [[UIBarButtonItem alloc] initWithTitle:@"Devkit" style:UIBarButtonItemStylePlain target:self action:@selector(onOpenDevkit)]; doricViewController.navigationItem.rightBarButtonItem = rightBarItem; [self.navigationController pushViewController:doricViewController animated:NO]; diff --git a/doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.m b/doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.m index edf8f273..25c0d407 100644 --- a/doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.m +++ b/doric-iOS/Pod/Classes/Extension/DoricBridgeExtension.m @@ -54,7 +54,7 @@ - (id)callNativeWithContextId:(NSString *)contextId module:(NSString *)module me } - (id)createParamWithMethodName:(NSString *)method context:(DoricContext *)context callbackId:(NSString *)callbackId argument:(id)argument { - if ([method isEqualToString:@"withPromise"]) { + if ([method isEqualToString:@"withPromise"] || [method isEqualToString:@"promise"]) { return [[DoricPromise alloc] initWithContext:context callbackId:callbackId]; } return argument; @@ -71,7 +71,11 @@ - (id)findClass:(Class)clz target:(id)target context:(DoricContext *)context met 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]) { + NSString *firstPart = array[0]; + if (![firstPart isEqualToString:name]) { + firstPart = [firstPart componentsSeparatedByString:@"With"][0]; + } + if ([firstPart isEqualToString:name]) { isFound = YES; SEL selector = NSSelectorFromString(methodName); NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector]; diff --git a/doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.m b/doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.m index 2fd7b77a..320e6520 100644 --- a/doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.m +++ b/doric-iOS/Pod/Classes/Plugin/DoricShaderPlugin.m @@ -85,7 +85,7 @@ - (void)command:(NSDictionary *)argument withPromise:(DoricPromise *)promise { } - (id)createParamWithMethodName:(NSString *)method promise:(DoricPromise *)promise argument:(id)argument { - if ([method isEqualToString:@"withPromise"]) { + if ([method isEqualToString:@"withPromise"] || [method isEqualToString:@"promise"]) { return promise; } return argument; @@ -99,7 +99,11 @@ - (void)findClass:(Class)clz target:(id)target method:(NSString *)name promise:( 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]) { + NSString *firstPart = array[0]; + if (![firstPart isEqualToString:name]) { + firstPart = [firstPart componentsSeparatedByString:@"With"][0]; + } + if ([firstPart isEqualToString:name]) { isFound = YES; SEL selector = NSSelectorFromString(methodName); NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector];