使函数只能从一个 class 调用

Make function only callable from one class

我有一个 class LoggingManager 和一个协议 LoggingHandler,只有一个方法 send(LoggingEvent)
LoggingManager 保留 LoggingHandler 的列表。
我希望 LoggingManager 成为允许从 LoggingHandler 和使用该协议的 classes 调用 send(LoggingEvent)only class应该实现 send(LoggingEvent) 方法。

我尝试将 LoggingHandlerLoggingManager 放入同一个文件并将 send(LoggingEvent) 标记为 fileprivate。 但是,它在协议中是不允许的。

有没有办法让它起作用?

LoggingManager.swift

import Foundation

public struct LoggingEvent {
    var eventName: String
    var eventParams: [String: Any]

    public init(_ name: String, _ eventParams: [String: Any]) {
        self.eventName = name
        self.eventParams = eventParams
    }

    public init(_ name: String) {
        self.eventName = name
        eventParams = [String: Any]()
    }

    mutating public func addParameter(_ eventName: String, _ eventValue: Any) {
        self.eventParams[eventName] = eventValue
    }
}

public protocol LoggingHandler {
    func logEvent(_ event: LoggingEvent) ///<--- Only LoggingManager should call this function, but classes implementing this should override it
}

public class LoggingManager {
    private var loggingHandlers: [LoggingHandler]
    static let shared = LoggingManager()

    private init() {
        loggingHandlers = []
    }

    public func registerLoggingHandler(_ loggingHandler: LoggingHandler) {
        loggingHandlers.append(loggingHandler)
    }

    public func logEvent(_ event: LoggingEvent) {
        for handler in loggingHandlers {
            handler.logEvent(event)
        }
    }
}

FirebaseLogger.swift

class FirebaseLogger: LoggingHandler {
    var firebaseApp: FirebaseApp?

    public init() {
        FirebaseApp.configure()
        firebaseApp = FirebaseApp.app()
    }

    func logEvent(_ event: LoggingEvent) {
        Analytics.logEvent(event.eventName, parameters: event.eventParams)
    }
}

LogLoggingHandler.swift(仅打印到控制台)

public class LogLoggingHandler: LoggingHandler {
    public func logEvent(_ event: LoggingEvent) {
        let name = event.eventName
        let description = event.eventParams.description
        print("LogEvent: \(name) \(description)")

    }
}

这不是最好的解决方案,但这是一个想法。在您的第一个文件中,您可以定义这些类型:

struct LoggingSecurity {
    fileprivate init() {}
}

class LoggingManager {
    private let handlers: [LoggingHandler]
    private let security: LoggingSecurity

    init(handlers: [LoggingHandler]) {
        self.handlers = handlers
        self.security = .init()
    }

    func broadcast(event: LoggingEvent) {
        handlers.forEach { handler in
            handler.send(
                event: event,
                securedBy: security
            )
        }
    }
}

由于 LoggingSecurity.init 方法被标记为 fileprivate 唯一可以实例化 LoggingSecurity 的 class 是 LoggingManager.

然后在您的其他文件中您可以定义这些类型:

struct LoggingEvent {
    let data: String
}

protocol LoggingHandler {
    func send(event: LoggingEvent, securedBy security: LoggingSecurity)
}

class PrintLoggingHandler: LoggingHandler {
    func send(event: LoggingEvent, securedBy security: LoggingSecurity) {
        print("LOG: \(event.data)")
    }
}