Penginisialisasi tidak dapat diakses karena tingkat perlindungan 'internal'

92

Saya memiliki beberapa protokol

Strategi Login

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
}

dan dua kelas:

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

Di ViewController saya :

Saat saya menggunakan:

let facebookLoginProvider = LoginProvider(strategy: FacebookLoginStrategy())

Ia mengatakan:

'FacebookLoginStrategy' tidak dapat diakses karena tingkat perlindungan 'internal'

appiconhero.co
sumber

Jawaban:

258

Cukup tambahkan ke FacebookLoginStrategy Anda:

public init() {}

Selama Anda tidak mengimplementasikan init () secara eksplisit, ini ditandai sebagai internal secara default. Anda perlu menimpa tingkat izin tersebut agar dapat membuat instance dari luar kerangka kerja Anda.

jboi
sumber
13
Jawaban yang bagus! Dan hati-hati dengan Swift4, ini sebenarnya kesalahan jika Anda tidak menerapkannya.
Paul Razvan Berg
2
Baru masuk kelas.
jboi
15
ini sangat bodoh sehingga Swift meminta ini. Jika saya mendeklarasikan seluruh tipe kelas sebagai publik, init () gratis harus datang sebagai publik juga
LightningStryk
3
Ini seharusnya bug Swift. Ini seharusnya bukan kesalahan kompilator, karena kita telah menandai publicuntuk class/struct.
lee
1
Saya telah menambahkan publik sebelum init saya dan saya masih mendapatkan pesan yang sama. Apakah ada perlindungan lain?
AndreG
8

Jika Anda menjalankan ini dalam kode dalam XCTestCase, pastikan Anda telah menambahkan @testable import My-Awesome-Appke bagian atas file pengujian Anda.

Alex Zavatone
sumber