Initializer is inaccessable due to 'internal' protection level
IosSwiftFrameworksAccess ModifiersInitializerIos Problem Overview
I have some protocols
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
}
and two 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
}
}
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 my ViewController:
When I use:
let facebookLoginProvider = LoginProvider(strategy: FacebookLoginStrategy())
It says:
> 'FacebookLoginStrategy' is inaccessable due to 'internal' protection > level
Ios Solutions
Solution 1 - Ios
Just add to your FacebookLoginStrategy:
public init() {}
As long as you do not implement init() explicitly, it is marked as internal by default. You need to overwrite that permission level to be able to instantiate from outside your framework.
Solution 2 - Ios
If you are running in to this in code within an XCTestCase, make sure that you have added @testable import My-Awesome-App
to the top of your test file.
Solution 3 - Ios
Add init method as Public access
public init() {}