NSClassFromString #interface for 'GIDSignIn' declares the selector 'fetchCloudValues' compiler error - swift

I'have a project where i have multiple targets, and in one of those targets i have added a custom class to download some Values from Firebase Remote Config.
Custom class is declared as follows:
#objc (Test)
final class CheckUpdate: NSObject {
#objc static let sharedInstance = CheckUpdate()
#objc func fetchCloudValues() {
// Grab remote config values and do things
}
}
I've added this class as target membership only on one target and in the code I've add
Class asdasd = NSClassFromString(#"Test");
if (asdasd) {
[[asdasd sharedInstance] fetchCloudValues];
}
My issue is that, at line where I call fetchCloudValues I get a compiling error saying that:
no visible #interface GIDSignIn declares the selector fetchCloudValues
but it's obviously an issue because asdasd should not be of type GIDSignIn

Related

Cannot find protocol declaration for protocol in Swift-Headers.h defined in Package

I got a compilation error.
XCode did not see the protocol that had been defined in a Package.
It was used as a requirement for a class.
class TestClass: NSViewController, ProtocolFromPackage {
}
In Swift-Headers.h I got an error:
< path to compilation directory >/DerivedSources/Swift-Headers.h:5911:118: Cannot find protocol declaration for 'ProtocolFromPackage'; did you mean 'SomeOtherProtocol'?
Just add a random dummy protocol with a property with the type of protocol that causes the error. Dont forget to use #objc with the dummy protocol.
#objc protocol PleaseJustFixCompilation: AnyObject {
/*
It's needed just to let Swift-header know that ProtocolFromPackage from Package exists.
*/
var dummyProperty: ProtocolFromPackage? { get }
}
It might also require adding into some header:
#protocol ObservableBooleanListener;

What is the difference between private and fileprivate in Swift 4

In Swift 4, since now private is visible in extensions also in the same source code file, how is it different from the fileprivate access modifier?
Background: In Swift 3, private variables in a class are not visible in its extensions in the same file. For that, fileprivate had to be used.
File Private
File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
Syntax: fileprivate <var type> <variable name>
Example: fileprivate class SomeFilePrivateClass {}
Private
Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
Syntax: private <var type> <variable name>
Example: private class SomePrivateClass {}
Here is more detail about all access levels: Swift - Access Levels
Answer to your question:
(In Swift 3, private variables in a class are not visible in its extensions in the same file. For that, fileprivate had to be used.)
Yes, in Swift 4.0, Private is now accessible in extension but within same file. If you declare/define extension in other file, then your private variable will not be accessible to your extension
Look at this images:
File: ViewController.swift
Here extension and view controller both are in same file, hence private variable testPrivateAccessLevel is accessible in extension
File: TestFile.swift
Here extension and view controller both are in different files, hence private variable testPrivateAccessLevel is not accessible in extension.
Here class ViewController2 is a subclass of ViewController and both are in same file. Here private variable testPrivateAccessLevel is not accessible in Subclass but fileprivate is accessible in subclass.
Applicable in swift 4.0 and its versions
Private
Private access only in class and its extension(When extension is in the same .swift file).
File Private
File-private access only in class and its extension & subClass(When extension or subClass is in the same .swift file).
///////////////ViewController1.swift file
class ViewController1 {
private func testPrivate() {
print("testPrivate")
}
fileprivate func testFilePrivate() {
print("testFilePrivate")
}
func doesNothing1() {
testPrivate() //success
testFilePrivate() //success
}
}
extension ViewController1 {
func doesNothingInExtensionSameFile() {
testPrivate() //success
testFilePrivate() //success
}
}
class SomeOtherClassInSameFile {
let vc1 = ViewController1()
func doesNothing() {
vc1.testPrivate() //throws error
vc1.testFilePrivate() //success
}
}
////////////// ViewController2.swift file
extension ViewController1 {
func doesNothingInExtensionDifferentFile() {
testPrivate() //throws error
testFilePrivate() //throws error
}
}
private and fileprivate access levels have come closer with Swift4.
The difference in access lies as follows:
fileprivate members - only & entirely within that .swift file
private members - only in that class & extension of the class if both are present in same .swift file
Hence only fileprivate members(not private) can be accessed in
Sub Classes in the same .swift file
Instances of the class (initialized in another class) in the same .swift file.
Open Vs Public:
Public does not allow a class to be inherited in another
module/target whereas Open does.
Public method does not allow to be overridden in subclass in another
module/target whereas Open does.
Apart from above both are same.
Private Vs Fileprivate:
(Within single file) Private does not allow to access (func and properties) in subclass whereas FilePrivate does.
(Outside File) Private and FilePrivate both can't be accessible.
Apart from above both are same.
"Private" is accessible only in class, "FilePrivate" accessible only in .swift file.
Private : Access in Class and Class Extension.
FilePrivate : Access in class, subClass, Extension,

Selector to method inside singleton

This sounds like a stupid question, but I have been trying to find a solution for hours now, and I still don't know what to do. I am using Swift 3.0, and I am having an issue calling a method inside a singleton class from a selector inside another class. My singleton class is as follows:
class Singleton : NSObject {
static let sharedInstance = Singleton()
private override init() {} // defeats instantiation
func myAction() {
// do something useful...
}
}
Then, here is the class from which I am calling the method contained in the Singleton:
class StatusBarPresenter {
func addItemsToMenu(menu: NSMenu) {
...
menu.insertItem(withTitle: "Disconnect this network",
action: #selector(Singleton.sharedInstance.myAction),
keyEquivalent: "D", at: 4)
...
}
}
Xcode doesn't complain about the code... it compiles without any errors or warnings, but the selector doesn't work. The UIMenuItem that I add to the menu is disabled, which means that the selector is not working. If the selector instead calls a method inside the class, everything works fine just as usual. This is a screenshot of what I am getting:
Thanks to Martin R. for pointing out that in my code I was not setting an explicit target for the UIMenuItem, leading to it being nil and ultimately self.
The following line added to the addItemsToMenu function after the call to insertItem solves the problem:
menu.item(at: 4)?.target = Singleton.sharedInstance

'unresolved identifier' for return value of Type Method in Swift

I'm trying to access the return value from a Type Method in one file from another file. To wit:
file_1:
class LetterView: UIView {
class func testFunction() -> CGSize {
return CGSizeMake(100,200)
}
}
file_2:
class AnotherClass {
func callTestFunction() {
var result = LetterView.testFunction()
print("- breakpoint here - ")
}
}
I get an Unresolved Identifier error on var result if I put a breakpoint in the debugger and do a po result. However if I change the return type of testFunction() to be an Int (say 2) and return that instead, then the function call works as expected. Color me confused.
Is the second file importing UIKit as well? Also, you should update your example from function to func. This all works in the playground which leads to UIKit missing.
There could be a few possible issues.
One of the classes has a Testing target and other one doesn't. You have to even include all of your classes in the testing target or none of them.
If it's Objective C class, check that the class is in ObjectiveC bridging header file.
If it's NSManagedObject subclass. Add #objc(className) before the class declaration.
If it's part of a different framework, make sure that the class or function is public
This is the original answer link : Swift Compiler Error: Use of unresolved identifier 'name'

Private var is accessible from outside the class

This was done in Playground, just to simplify.
class MyPrivateVar
{
private var priv: String?
}
var myInstance = MyPrivateVar()
myInstance.priv = "Something"
No compiler warning. In fact auto-complete is showing priv without a problem.
My understanding is that outside the boundaries of {} of the class, I'm not supposed to be able to see a private anything, func nor var.
Am I missing something?
Access modifiers in Swift are implemented differently than other languages. There are three levels:
private: accessible only within that particular file
internal: accessible only within the module (project)
public: accessible from anywhere
Unless marked otherwise, everything you write is internal by default.
The Swift blog had a post about access control when the features were introduced in beta 4, and Apple's documentation has a chapter as well.
Note: this answer is for Swift 2
The Swift Programming Language states:
Swift provides three different access levels for entities within your
code. These access levels are relative to the source file in which an
entity is defined, and also relative to the module that source file
belongs to.
If you wan't to test private access level with Swift, the following step by step may help you.
1/ Create a new Xcode project.
2/ Create a file, MyPrivateVar.swift, and add the following code in it:
class MyPrivateVar {
private var priv: String? = nil
}
3/ Create a second file, MySecondClass.swift, and add the following code in it:
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
Xcode will immediatly give you a Swift compiler error message:
'MyPrivateVar' does not have a member named 'priv'
4/ Now, remove the two previous files from your project and create a single file TwoClassesInAFile.swift with the following code in it:
class MyPrivateVar {
private var priv : String? = nil
}
class MySecondClass {
init() {
var myPrivateVar = MyPrivateVar()
myPrivateVar.priv = "some string"
}
}
This time, you will get no Swift compiler error message and you will be able to access MyPrivateVar's priv private property from MySecondClass because priv and MySecondClass are in the same file (your TwoClassesInAFile.swift file).
Furthermore, access levels also work for global variables. For example, Xcode won't give any compiler error if the following code is part of the same ViewController.swift file:
import UIKit
private var globalPrivate : String? = nil
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
globalPrivate = "some string"
println(globalPrivate)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
However, if you define globalPrivate outside of ViewController.swift, Xcode will generate an error message:
Use of unresolved identifier 'globalPrivate'