初始化器不可访问,因为它的保护级别是“内部”的。

140

我有一个协议

登录策略

public protocol LoginStrategy {
    func login(_ viewController: UIViewController)
    func getUserInfo(withCompletionHandler completionHandler: @escaping (_ userInfo: [String: Any]?) -> ())
    func createLoginButton(_ frame: CGRect, withCompletionHandler completionHandler: @escaping (_ loginButton: UIView) -> ())
    func getUserId() -> String
}

还有两个类:

LoginProvider

public class LoginProvider {
    
    public let strategy: LoginStrategy
    
    public func login(_ viewController: UIViewController) {
        return self.strategy.login(viewController)
    }
    
    public func getUserInfo(withCompletionHandler completionHandler: @escaping (_ userInfo: [String: Any]?) -> ()) {
        return self.strategy.getUserInfo(withCompletionHandler: completionHandler)
    }
    
    public func createLoginButton(_ frame: CGRect, withCompletionHandler completionHandler: @escaping (_ loginButton: UIView) -> ()) {
        return self.strategy.createLoginButton(frame, withCompletionHandler: completionHandler)
    }
    
    public func getUserId() -> String {
        return self.strategy.getUserId()
    }
    
    public init(strategy: LoginStrategy) {
        self.strategy = strategy
    }
    
}

FacebookLoginStrategy

import Foundation
import FacebookCore
import FacebookLogin

public class FacebookLoginStrategy: LoginStrategy {
    
    public var grantedPermissions: Set<Permission>? = nil

    public var declinedPermissions: Set<Permission>? = nil
    
    public var userId: String = ""
    
    public func login(_ viewController: UIViewController) {
        let loginManager = LoginManager()
        let permissions: [ReadPermission] = [.publicProfile, .userFriends, .email]
        loginManager.logIn(permissions, viewController: viewController) { loginResult in
            switch loginResult {
            case .failed(let error):
                print(error)
            case .cancelled:
                print("User cancelled login.")
            case .success(let grantedPermissions, let declinedPermissions, let accessToken):
                self.userId = accessToken.userId ?? ""
                self.grantedPermissions = grantedPermissions
                self.declinedPermissions = declinedPermissions
                print("Logged in!")
            }
        }
    }
    
    public func getUserId() -> String {
        return userId
    }
    
    public func getUserInfo(withCompletionHandler completionHandler: @escaping (_ userInfo: [String: Any]?) -> ()) {
        let request = GraphRequest(graphPath: "me", parameters: ["fields":"email, name"], accessToken: AccessToken.current, httpMethod: .GET, apiVersion: FacebookCore.GraphAPIVersion.defaultVersion)
        request.start { (response, result) in
            switch result {
            case .success(let value):
                print(value.dictionaryValue)
                completionHandler(value.dictionaryValue)
            case .failed(let error):
                print(error)
            }
        }
    }

    public func createLoginButton(_ frame: CGRect, withCompletionHandler completionHandler: @escaping (_ loginButton: UIView) -> ()) {
        let permissions: [ReadPermission] = [.publicProfile, .userFriends, .email]
        let loginButton = LoginButton(readPermissions: permissions)
        loginButton.frame = frame
        completionHandler(loginButton)
    }
}

在我的视图控制器中:

当我使用:

let facebookLoginProvider = LoginProvider(strategy: FacebookLoginStrategy())

其意思是:

'FacebookLoginStrategy'由于其被设置为 'internal',因此无法访问。

4个回答

369

只需在您的Facebook登录策略中添加:

public init() {}
只要您没有明确实现init(),它就默认为内部方法。您需要覆盖该权限级别才能从框架外实例化。

15
好的回答!请注意Swift4,如果您不实现它,实际上会出错。 - Paul Razvan Berg
2
刚进入类。 - jboi
58
这太愚蠢了,Swift居然要求这样做。如果我把整个类的类型声明为public,那么free init()也应该是public的。 - LightningStryk
4
这应该是Swift的一个错误。这不应该是编译器的错误,因为我们已经使用public标记了class/struct - lee
1
我在我的init之前添加了public,但仍然收到相同的消息。还有其他保护措施吗? - AndreG
显示剩余4条评论

21
如果你在XCTestCase代码中遇到这个问题,请确保在测试文件的顶部添加了@testable import My-Awesome-App

1
非常感谢您。 - fredy

7

将init方法设置为公共访问

public init() {}

3

如果有人在实现Swift包以构建可重用的SwiftUI视图时遇到此问题,请记住以下几点:

  1. 如果有从父组件设置的组件属性,请不要忘记将它们添加到构造函数中
  2. 如果该属性被包装在@State中,则将状态分配给下面的对象,如下所示。
public struct Layout: View {
    @State var layout: NavType = .TOP
    var navItems: [NavItemObject]
    public init(layout: NavType, navItems: [NavItemObject]) {
        _layout = State(initialValue: layout);
        self.navItems = navItems;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接