You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Expo原生模块开发:NativeScannerModule未遵循AnyModule协议报错求助

Expo原生模块开发:NativeScannerModule未遵循AnyModule协议报错求助

嘿,看起来你在开发Expo原生扫描AirPrint打印机的模块时踩坑了,我来帮你梳理下问题和解决办法:

首先看你贴的代码片段,有几个明显的问题会触发协议遵循报错:

  1. 代码没写完,FunctFunction的拼写错误,而且没有完成方法的完整定义
  2. 没有满足Expo Modules Core中Module协议的全部要求,尤其是初始化方法和事件发送的核心逻辑,这大概率就是“未遵循AnyModule协议”报错的核心原因

我给你整理了修正后的完整代码示例,你可以参考调整:

import ExpoModulesCore
import Foundation
import Network

public class NativeScannerModule: NSObject, Module, NetServiceBrowserDelegate, NetServiceDelegate {
    private var serviceBrowser: NetServiceBrowser?
    private var discoveredServices: [NetService] = []
    // 用于给JS端发送事件的关键对象
    private let eventEmitter: EventEmitter

    // 必须实现接收AppContext的初始化方法,这是Expo模块的强制要求
    public required init(appContext: AppContext) {
        self.eventEmitter = appContext.eventEmitter
        super.init()
        setupServiceBrowser()
    }

    public func definition() -> ModuleDefinition {
        // 定义模块名称,JS端会通过这个名称调用模块方法
        Name("NativeScanner")
        
        // 注册要发送到JS端的事件
        Events("onPrinterFound")
        
        // 定义JS可调用的"开始扫描"方法
        Function("startScanning") { [weak self] in
            // AirPrint服务的标准类型是_ipp._tcp.,扫描本地局域网域
            self?.serviceBrowser?.searchForServices(ofType: "_ipp._tcp.", inDomain: "local.")
        }
        
        // 定义停止扫描的方法
        Function("stopScanning") { [weak self] in
            self?.serviceBrowser?.stop()
            self?.discoveredServices.removeAll()
        }
    }

    private func setupServiceBrowser() {
        serviceBrowser = NetServiceBrowser()
        serviceBrowser?.delegate = self
    }

    // 实现NetServiceBrowserDelegate方法,发现服务时触发
    public func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
        discoveredServices.append(service)
        // 触发服务地址解析
        service.delegate = self
        service.resolve(withTimeout: 5.0)
    }

    // 服务地址解析完成后,把打印机信息发送到JS端
    public func netServiceDidResolveAddress(_ sender: NetService) {
        guard let addressData = sender.addresses?.first else { return }
        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
        getnameinfo(addressData.bytes, socklen_t(addressData.count), &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST)
        let ipAddress = String(cString: hostname)
        // 组装JS端易处理的打印机信息字典
        let printerInfo = [
            "name": sender.name,
            "ipAddress": ipAddress,
            "port": sender.port
        ] as [String: Any]
        // 发送事件到JS端
        eventEmitter.sendEvent("onPrinterFound", body: printerInfo)
    }

    // 必须实现错误处理的代理方法,避免协议未完全遵循的报错
    public func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String: NSNumber]) {
        print("扫描打印机出错: \(errorDict)")
    }

    public func netService(_ sender: NetService, didNotResolve errorDict: [String: NSNumber]) {
        print("解析打印机服务出错: \(errorDict)")
    }
}

另外再给你几个额外的排查方向:

  • 如果你仍遇到“未遵循AnyModule协议”的报错,大概率是Expo Modules Core版本和项目的Expo SDK版本不匹配,建议检查依赖版本并保持一致
  • Swift对协议遵循的检查非常严格,必须完整实现所有你声明遵循的协议方法,缺一个都会触发报错
  • 可以尝试清理Xcode缓存(Product -> Clean Build Folder)后重新构建项目,有时候缓存会导致奇怪的协议校验问题

备注:内容来源于stack exchange,提问作者Dev07

火山引擎 最新活动