Initializer is inaccessable due to 'internal' protection level
86,868
Solution 1
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
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
Add init method as Public access
public init() {}
Related videos on Youtube
Comments
-
Khuong over 2 years
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
-
Paul Razvan Berg almost 7 yearsGreat answer! And watch out for Swift4, it's actually an error if you don't implement it.
-
jboi over 6 yearsJust into the class.
-
LightningStryk about 5 yearsthis is so dumb that Swift requires this. If I declare the whole class type public, the free init() should come as public as well
-
lee over 4 yearsThis should a bug of
Swift
. It should not an error of compiler, since we had markedpublic
forclass/struct
. -
jboi over 4 yearsJust learned, that it also works for
structs
. Got the error-message, was confused, googled and found my own answer. It's getting late on a Friday... -
AndreG over 4 yearsI've added public before my init and I am still getting that same message. Is there another protection?
-
jboi over 4 yearsHi @AndreG , can you share some code with us? Maybe just ask your question.
-
fredy over 2 yearsThank you so much.
-
Peter Schorn over 2 years@lee It's not dumb, nor is it a bug. Sometimes you don't want the initializers for a type to be public. It's easy to forget about the existence of synthesized initializers because they don't actually appear in your code. Therefore, if these initializers were public, it'd be easy to accidentally expose them outside of the module.