L'initialiseur est inaccessible en raison du niveau de protection `` interne ''

89

J'ai quelques protocoles

ConnexionStratégie

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
}

et deux classes:

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
    }

}

FacebookLoginStratégie

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

Dans mon ViewController :

Quand j'utilise:

let facebookLoginProvider = LoginProvider(strategy: FacebookLoginStrategy())

Ça dit:

'FacebookLoginStrategy' est inaccessible en raison du niveau de protection 'interne'

appiconhero.co
la source

Réponses:

250

Ajoutez simplement à votre FacebookLoginStrategy:

public init() {}

Tant que vous n'implémentez pas explicitement init (), il est marqué comme interne par défaut. Vous devez remplacer ce niveau d'autorisation pour pouvoir instancier depuis l'extérieur de votre infrastructure.

jboi
la source
13
Très bonne réponse! Et faites attention à Swift4, c'est en fait une erreur si vous ne l'implémentez pas.
Paul Razvan Berg
2
Juste dans la classe.
jboi
12
c'est tellement stupide que Swift l'exige. Si je déclare le type de classe entier public, le libre init () devrait également devenir public
LightningStryk
3
Cela devrait être un bug de Swift. Cela ne devrait pas être une erreur de compilateur, puisque nous avions marqué publicpour class/struct.
lee
1
J'ai ajouté du public avant mon init et je reçois toujours le même message. Existe-t-il une autre protection?
AndreG
8

Si vous exécutez ceci dans le code dans un XCTestCase, assurez-vous que vous avez ajouté @testable import My-Awesome-Appen haut de votre fichier de test.

Alex Zavatone
la source