New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用swift 扩展weex module #55

Open
acton393 opened this Issue Jul 28, 2016 · 15 comments

Comments

Projects
None yet
10 participants
@acton393

acton393 commented Jul 28, 2016

Swift In Weex

参考之前 Swift和Objective-C 混编的文档
Weex iOS SDK 是使用 Objective-C,结合部分C实现的,
引入 Swift,需要混编,直接进入正题

一个例子

SDK集成 参考

使用 Swift 进行 module 扩展

doc

因为 module 暴露 method 是通过Objective-C宏来做的,调用的时候是通过反射,所以Swift扩展 module 通过extension Objective-C的类,以下操作,可以直接在weex 的iOS playground 中进行

  • 新建 WXSwiftTestModule.h/mWXSwiftTestModule.swift文件, 在新建Swift文件的时候会提示
    img
    选择 Create Bridging Header, 因为我们要在 Swift 中访问 Objective-C 的一些类,正是通过这个 header暴露 OC 的类给 Swift,header 格式为 yourTarget-Bridging-Header.h,我这里创建完header文件名称为:WeexDemo-Bridging-Header.h

  • WXSwiftTestModule.h/m中实现

    • WXSwiftTestModule.h 中

          #import <Foundation/Foundation.h>
          #import <WeexSDK/WeexSDK.h>
      
          @interface WXSwiftTestModule : NSObject <WXModuleProtocol>
      
          @end
      
      
    • WXSwiftTestModule.m 中

      WeexDemo-Swift.h 这个文件需要编译一下才可以搜索到,具体的路径

      weex/ios/playground/DerivedData/WeexDemo/Build/Intermediates/WeexDemo.build/Debug-iphonesimulator/WeexDemo.build/DerivedSources/WeexDemo-Swift.h
      

      路径具体需要根据自己工程而定

          #import "WXSwiftTestModule.h"
          #import "WeexDemo-Swift.h" // Swift类和方法 被 `Objective-C` 识别需要导入
      
          @implementation WXSwiftTestModule
          #pragma clang diagnostic push //关闭unknow selector的warrning
          #pragma clang diagnostic ignored "-Wundeclared-selector"
      
          WX_EXPORT_METHOD(@selector(printSome:callback:)) //Swift 中定义的方法,XCode 转换成的最终的方法名称,在`WeexDemo-Swift.h`里面查看
      
          #pragma clang diagnostic pop
      
          @end
      
      
  • Swift 中实现
    扩展 OC 的类 WXSwiftTestModule,增加了一个方法,这个方法就是我们要暴露出来,在 js 中可以调到的

    • WXSwiftTestModule.swift

          import Foundation
          public extension WXSwiftTestModule {
             public func printSome(someThing:String, callback:WXModuleCallback) {
                 print(someThing)
                 callback(someThing)
             }
          }
      

      WXSwiftTestModuleWXModuleCallback 因为是 OC 的,需要在 WeexDemo-Bridging-Header 中暴露

    • WeexDemo-Bridging-Header.h中

      //
      //  Use this file to import your target's public headers that you would like to expose to Swift.
      //
      #import "WXSwiftTestModule.h"
      #import "WeexSDK.h"
      

      至此这个使用 Swift 开发的简单的 module 已经完成

    module 使用

    • 注册 module

      [WXSDKEngine registerModule:@"swifter" withClass:[WXSwiftTestModule class]];
      
      
    • we 文件中使用

      <template>
          <text>Swift Module</text>
      </template>
    
      <script>
        require('weex-components');
    
        module.exports = {
          data: {
    
          },
          ready: function() {
            var swifter = require('@weex-module/swifter');
            swifter.printSome("https://www.taobao.com",function(param){
              nativeLog(param);
            });
          }
    
        };
      </script>
    
@Bijiabo

This comment has been minimized.

Show comment
Hide comment
@Bijiabo

Bijiabo Dec 7, 2016

完整根据这个代码来的,运行后发现找不到这个方法,提示:
[fg0,128,0; <Weex>[debug]WXJSCoreBridge.m:135, Calling native... instance:1, tasks:( { args = ( "https://www.taobao.com", 2 ); method = printSome; module = swifter; } ), callback:-1 �[;

Bijiabo commented Dec 7, 2016

完整根据这个代码来的,运行后发现找不到这个方法,提示:
[fg0,128,0; <Weex>[debug]WXJSCoreBridge.m:135, Calling native... instance:1, tasks:( { args = ( "https://www.taobao.com", 2 ); method = printSome; module = swifter; } ), callback:-1 �[;

@acton393

This comment has been minimized.

Show comment
Hide comment
@acton393

acton393 Dec 8, 2016

@Bijiabo 这个提示是 JS调用native的一个日志,可以参考一下这个例子 swiftExample

acton393 commented Dec 8, 2016

@Bijiabo 这个提示是 JS调用native的一个日志,可以参考一下这个例子 swiftExample

@Bijiabo

This comment has been minimized.

Show comment
Hide comment
@Bijiabo

Bijiabo Dec 8, 2016

@acton393 sorry,复制错了内容,提示是这样的:
2016-12-08 23:29:07.413 learnProject [60197:2137501] �[fg255,0,0; <Weex>[error]WXMonitor.m:190, Module:swifter, method:printSome doesn't exist �[;

Bijiabo commented Dec 8, 2016

@acton393 sorry,复制错了内容,提示是这样的:
2016-12-08 23:29:07.413 learnProject [60197:2137501] �[fg255,0,0; <Weex>[error]WXMonitor.m:190, Module:swifter, method:printSome doesn't exist �[;

@lenvonsam

This comment has been minimized.

Show comment
Hide comment
@lenvonsam

lenvonsam Mar 15, 2017

如果非http请求的图片资源而是项目中内部的图片资源,ios是如何读取的

lenvonsam commented Mar 15, 2017

如果非http请求的图片资源而是项目中内部的图片资源,ios是如何读取的

@acton393

This comment has been minimized.

Show comment
Hide comment
@acton393

acton393 Apr 24, 2017

@lenvonsam 可以参考WXURLRewriteProtocol 这个协议,有默认实现

acton393 commented Apr 24, 2017

@lenvonsam 可以参考WXURLRewriteProtocol 这个协议,有默认实现

@15130886370

This comment has been minimized.

Show comment
Hide comment
@15130886370

15130886370 Apr 26, 2017

请问那个 WeexDemo-Swift 是源自哪里的?

15130886370 commented Apr 26, 2017

请问那个 WeexDemo-Swift 是源自哪里的?

@acton393

This comment has been minimized.

Show comment
Hide comment
@acton393

acton393 Apr 26, 2017

@15130886370 文档中有链接

acton393 commented Apr 26, 2017

@15130886370 文档中有链接

@XImoon

This comment has been minimized.

Show comment
Hide comment
@XImoon

XImoon Jul 1, 2017

按照文档所说的,

  1. 添加WXSwiftTestModule.h/.m文件,并在Bridging-Header.h中import WXSwiftTestModule.h
  2. 在WXSwiftTestModule.m中添加WX_EXPORT_METHOD(@selector(method:))方法,并import project-swift.h
  3. 创建swift file,通过extension的方式扩充method方法
    但是仍然提示找不到注册的module的方法
    method:method for module: module doesn't exist, maybe it has not been registered [;

XImoon commented Jul 1, 2017

按照文档所说的,

  1. 添加WXSwiftTestModule.h/.m文件,并在Bridging-Header.h中import WXSwiftTestModule.h
  2. 在WXSwiftTestModule.m中添加WX_EXPORT_METHOD(@selector(method:))方法,并import project-swift.h
  3. 创建swift file,通过extension的方式扩充method方法
    但是仍然提示找不到注册的module的方法
    method:method for module: module doesn't exist, maybe it has not been registered [;
@xeha-gmbh

This comment has been minimized.

Show comment
Hide comment
@xeha-gmbh

xeha-gmbh Jul 24, 2017

@XImoon you have to import the XCode generated header files.
Something like "#import "ProjectName-Swift.h"
Also in this file you can find the generated method names for the WX_EXPORT_METHOD.
it's located somewhere under "~/Library/Developer/XCode/DerivedData/......./DerivedData/ProjectName-Swift.h"
It will be generated after you hit build.

xeha-gmbh commented Jul 24, 2017

@XImoon you have to import the XCode generated header files.
Something like "#import "ProjectName-Swift.h"
Also in this file you can find the generated method names for the WX_EXPORT_METHOD.
it's located somewhere under "~/Library/Developer/XCode/DerivedData/......./DerivedData/ProjectName-Swift.h"
It will be generated after you hit build.

@XImoon

This comment has been minimized.

Show comment
Hide comment
@XImoon

XImoon Jul 25, 2017

@xeha-gmbh
I think you misunderstand me. It's not me but the compiler can not find the method. I'm confused somewhere I lost or did mistake, so that the complier can't excute even relate the method I write.
Finally, I completed it using OC, which call a swift method to finish the action.
But I still really wonder know what's wrong with me as the article says.

XImoon commented Jul 25, 2017

@xeha-gmbh
I think you misunderstand me. It's not me but the compiler can not find the method. I'm confused somewhere I lost or did mistake, so that the complier can't excute even relate the method I write.
Finally, I completed it using OC, which call a swift method to finish the action.
But I still really wonder know what's wrong with me as the article says.

@zhongdom

This comment has been minimized.

Show comment
Hide comment
@zhongdom

zhongdom Sep 20, 2017

@XImoon 和你遇到同样的问题,通过swift的extension方式提示找不到方式,完全使用OC代码实现是ok的,不知道哪个步骤不对

找到坑了,现在用的是swift 4.0,默认去掉了自动增加的 @objc,swift代码改成这样就没问题了

public extension WXEventModule {
    @objc public func openURL(_ url:String) {
        var newUrl:String = url;
        if url.hasPrefix("//") {
            newUrl = String.init(format: "http://%@", url);
        }else if !url.hasPrefix("http") {
            //relative path
            newUrl = (URL.init(string: url, relativeTo: weexInstance.scriptURL)!.absoluteString)
        }
        let controller:URLViewController = URLViewController()
        controller.url = URL.init(string: newUrl)
        weexInstance.viewController.navigationController?.pushViewController(controller, animated:true)
    }
} 

zhongdom commented Sep 20, 2017

@XImoon 和你遇到同样的问题,通过swift的extension方式提示找不到方式,完全使用OC代码实现是ok的,不知道哪个步骤不对

找到坑了,现在用的是swift 4.0,默认去掉了自动增加的 @objc,swift代码改成这样就没问题了

public extension WXEventModule {
    @objc public func openURL(_ url:String) {
        var newUrl:String = url;
        if url.hasPrefix("//") {
            newUrl = String.init(format: "http://%@", url);
        }else if !url.hasPrefix("http") {
            //relative path
            newUrl = (URL.init(string: url, relativeTo: weexInstance.scriptURL)!.absoluteString)
        }
        let controller:URLViewController = URLViewController()
        controller.url = URL.init(string: newUrl)
        weexInstance.viewController.navigationController?.pushViewController(controller, animated:true)
    }
} 
@XImoon

This comment has been minimized.

Show comment
Hide comment
@XImoon

XImoon Sep 22, 2017

@zhongdom
这个问题我后来直接用oc代码实现,然后调用swift的方法……非常感谢解惑,我以为这个坑就这么掉下去爬不出来了

XImoon commented Sep 22, 2017

@zhongdom
这个问题我后来直接用oc代码实现,然后调用swift的方法……非常感谢解惑,我以为这个坑就这么掉下去爬不出来了

@thecorsair

This comment has been minimized.

Show comment
Hide comment
@thecorsair

thecorsair Oct 19, 2017

请问有没有swift weex component相关的代码
成员方法报 is not function
已经通过WX_EXPORT_METHOD暴露出去
oc写法是成功的

thecorsair commented Oct 19, 2017

请问有没有swift weex component相关的代码
成员方法报 is not function
已经通过WX_EXPORT_METHOD暴露出去
oc写法是成功的

@leoprc

This comment has been minimized.

Show comment
Hide comment
@leoprc

leoprc Oct 26, 2017

@XImoon @thecorsair 我也是遇到这个问题,我是 OC/Swift 新手,经验不太足,花了一整天测试,最后找到一个办法。

一开始试了上面提到的 @objc 办法,但在我这里并不生效,我尝试了不带任何参数的函数签名,通过 WX_EXPORT_METHOD 暴露,是完全正常的,所以就定位问题到 “函数签名” 上了。

Weex Vue Code:
webView.open(url, callback)

*-Swift.h 头文件里的签名形式
- (void)open:(NSString * _Nonnull)url :(SWIFT_NOESCAPE void (^ _Nonnull)(id _Nullable))callback;

.swift 文件里的 extension 扩展实现(特别注意参数前面的 _ )
public func open(_ url: String, _ callback: WXModuleCallback)

.m 文件里的暴露(你的函数是几个参数,就几个冒号)
WX_EXPORT_METHOD(@selector(open::))

应该写对了函数签名,这个问题就可以解决,但我就没有花更多时间去深挖了,目前能让项目进行下去就 OK。

希望对大家有帮助。

leoprc commented Oct 26, 2017

@XImoon @thecorsair 我也是遇到这个问题,我是 OC/Swift 新手,经验不太足,花了一整天测试,最后找到一个办法。

一开始试了上面提到的 @objc 办法,但在我这里并不生效,我尝试了不带任何参数的函数签名,通过 WX_EXPORT_METHOD 暴露,是完全正常的,所以就定位问题到 “函数签名” 上了。

Weex Vue Code:
webView.open(url, callback)

*-Swift.h 头文件里的签名形式
- (void)open:(NSString * _Nonnull)url :(SWIFT_NOESCAPE void (^ _Nonnull)(id _Nullable))callback;

.swift 文件里的 extension 扩展实现(特别注意参数前面的 _ )
public func open(_ url: String, _ callback: WXModuleCallback)

.m 文件里的暴露(你的函数是几个参数,就几个冒号)
WX_EXPORT_METHOD(@selector(open::))

应该写对了函数签名,这个问题就可以解决,但我就没有花更多时间去深挖了,目前能让项目进行下去就 OK。

希望对大家有帮助。

@terryjianluo

This comment has been minimized.

Show comment
Hide comment
@terryjianluo

terryjianluo Mar 25, 2018

更新一个在swift4下面的解决方法
在方法前加入'@objc(printSome::)',与.m的selector方法名一样
@objc(printSome::)
func printSome(_ someThing:String, _ callback:WXModuleCallback) {
print(someThing)
callback(someThing)
}

terryjianluo commented Mar 25, 2018

更新一个在swift4下面的解决方法
在方法前加入'@objc(printSome::)',与.m的selector方法名一样
@objc(printSome::)
func printSome(_ someThing:String, _ callback:WXModuleCallback) {
print(someThing)
callback(someThing)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment