Auf den Initializer kann aufgrund der internen Schutzstufe nicht zugegriffen werden

86

Ich habe einige Protokolle

LoginStrategy

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
}

und zwei Klassen:

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)
    }
}

In meinem ViewController :

Wenn ich benutze:

let facebookLoginProvider = LoginProvider(strategy: FacebookLoginStrategy())

Es sagt:

Auf 'FacebookLoginStrategy' kann aufgrund der 'internen' Schutzstufe nicht zugegriffen werden

appiconhero.co
quelle

Antworten:

241

Fügen Sie einfach zu Ihrer FacebookLoginStrategy hinzu:

public init() {}

Solange Sie init () nicht explizit implementieren, wird es standardmäßig als intern markiert. Sie müssen diese Berechtigungsstufe überschreiben, um von außerhalb Ihres Frameworks instanziieren zu können.

jboi
quelle
12
Gute Antwort! Und achten Sie auf Swift4, es ist tatsächlich ein Fehler, wenn Sie es nicht implementieren.
Paul Razvan Berg
2
Einfach in die Klasse.
Jboi
11
Das ist so dumm, dass Swift dies verlangt. Wenn ich den gesamten Klassentyp als öffentlich deklariere, sollte auch das freie init () als öffentlich erscheinen
LightningStryk
3
Dies sollte ein Fehler sein Swift. Es sollte einen Fehler von Compiler nicht, da wir markiert hatte publicfür class/struct.
Lee
1
Ich habe public vor meinem Init hinzugefügt und erhalte immer noch dieselbe Nachricht. Gibt es einen anderen Schutz?
AndreG
8

Wenn Sie diesen Code in einem XCTestCase ausführen, stellen Sie sicher, dass Sie ihn @testable import My-Awesome-Appoben in Ihrer Testdatei hinzugefügt haben .

Alex Zavatone
quelle