Private VS. Fileprivate on Declaring Global Variables/Consts in Swift3

What is a good example to differentiate between fileprivate and private in Swift3

fileprivate is now what private used to be in earlier
Swift releases: accessible from
the same source file. A declaration marked as private can now only be accessed within the lexical scope it is declared in.
So private is more restrictive than fileprivate.

As of Swift 4, private declarations inside a type are accessible to extensions of the same type if the extension is defined in the same source file.

Example (all in one source file):

class A {
private func foo() {}
fileprivate func bar() {}

func baz() {
foo()
bar()
}
}

extension A {
func test() {
foo() // Swift 3: error: use of unresolved identifier 'foo'
// Swift 4: no error because extension is in same source file
bar()
}
}

let a = A()
a.foo() // error: 'foo' is inaccessible due to 'private' protection level
a.bar()
  • The private foo method is accessible only within the scope of
    the class A { ... } definition. It is not even accessible from
    an extension to the type (in Swift 3, see the second note below for
    changes in Swift 4).

  • The file-private bar method is accessible from the same source file.

Notes:

  1. The proposal SE-0159 – Fix Private Access Levels suggested to revert to the Swift 2 semantics in Swift 4. After a lengthy and controversial discussion on the swift-evolution mailing list, the proposal was rejected.

  2. The proposal SE-0169 – Improve Interaction Between private Declarations and Extensions suggests to make private
    declarations inside a type accessible to extensions of the same type
    if the extension is defined in the same source file.
    This proposal was accepted and implemented in Swift 4.

Swift: is there any functional difference between private static let (in a class definition) and fileprivate let (no owner)

The functional difference is minor: Your fileprivate (which could be private) global is accessible to all types defined within that file, whereas the former is limited to that one particular SomeClass.

The “private global” arguably requires non-local reasoning (i.e., you might have to scan through the whole file to see which types are there and might have access to it). On the other hand, the “private static property” makes the intent more clear at glance. As a result, many would favor this “private static property” approach.


For what it is worth, there is a hybrid approach:

class SomeClass {
var possibleValues: [String] {
return Self.someValues
}
}

private extension SomeClass {
private static let someValues: [String] = [
"mrah!",
"blah",
"shmah!"
]
}

It keeps the core type definition very clean, but keeps the namespace for the static constant. Sometimes it is nice to put various subtypes, methods, and statics in extensions within the same file. It can make it easy to grok the code, facilitates code folding, etc.

Why private variable declared outside the class can be access Class on the same file?

private is intended for use inside a type declaration. Otherwise it has no meaning. When private is used in a place where it has no meaning, it is reinterpreted as fileprivate. That is what happens here. This code is in the same file so the fileprivate variable is visible.

Global constants file in Swift

Structs as namespace

IMO the best way to deal with that type of constants is to create a Struct.

struct Constants {
static let someNotification = "TEST"
}

Then, for example, call it like this in your code:

print(Constants.someNotification)

Nesting

If you want a better organization I advise you to use segmented sub structs

struct K {
struct NotificationKey {
static let Welcome = "kWelcomeNotif"
}

struct Path {
static let Documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
static let Tmp = NSTemporaryDirectory()
}
}

Then you can just use for instance K.Path.Tmp

Real world example

This is just a technical solution, the actual implementation in my code looks more like:

struct GraphicColors {

static let grayDark = UIColor(0.2)
static let grayUltraDark = UIColor(0.1)

static let brown = UIColor(rgb: 126, 99, 89)
// etc.
}

and


enum Env: String {
case debug
case testFlight
case appStore
}

struct App {
struct Folders {
static let documents: NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
static let temporary: NSString = NSTemporaryDirectory() as NSString
}
static let version: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
static let build: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String

// This is private because the use of 'appConfiguration' is preferred.
private static let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"

// This can be used to add debug statements.
static var isDebug: Bool {
#if DEBUG
return true
#else
return false
#endif
}

static var env: Env {
if isDebug {
return .debug
} else if isTestFlight {
return .testFlight
} else {
return .appStore
}
}
}

Private var is accessible from outside the class

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.

How to define static constant in a generic class in swift?

You can define global constant with fileprivate or private access level in the same .swift file where your generic class is defined. So it will not be visible outside of this file and will not pollute global (module) namespace.

If you need to access this constant from outside of current file then declare it as internal (default access level) or public and name it like ClassConstant so it will be obvious that it relates to Class.

Read more about access levels in Swift 3.

Declaring private constants outside of a class in Swift

They're accessed differently.

In the first case, someFloat is in the scope of SomeClass. It's accessed with SomeClass.someFloat.

In the second case, someFloat is in the module scope. It's accessed with just someFloat.

The first method is preferable. It's generally harder to find identifiers in the module name space, because they can be easily drowned out by all the identifiers in the standard library or foundation/cocoa framework.

Swift - 'textFields' is inaccessible due to 'fileprivate' protection level

textfields is a private variable in the PCLBlurEffectAlertController. So we can't access the private variable.

fileprivate var textFields: [UITextField] = []

You can use like this :

var textfield1: UITextField?

let alert1 = PCLBlurEffectAlertController(title: NSLocalizedString("AGGENTRATA", comment: ""),
message: NSLocalizedString("insENTRATA", comment: ""),
effect: UIBlurEffect(style: .dark),
style: .alert)
alert1.addTextField( with: { (textField: UITextField!) in
textField.placeholder = NSLocalizedString("ENTRATA_LOCAL", comment: "") //impostiamo il segnaposto del field
textField.isSecureTextEntry = false //se fosse un campo Password mettremmo true
textField.keyboardType = UIKeyboardType.numberPad
self.textfield1 = textField
} )

alert1.addAction(PCLBlurEffectAlertAction(title: NSLocalizedString("AGG", comment: ""), style: .default, handler: { (action) in
let textField = (self.textfield1?.text as! NSString).floatValue
}))

Swift constants: Struct or Enum

Both structs and enumerations work. As an example, both

struct PhysicalConstants {
static let speedOfLight = 299_792_458
// ...
}

and

enum PhysicalConstants {
static let speedOfLight = 299_792_458
// ...
}

work and define a static property PhysicalConstants.speedOfLight.

Re: A struct will be copied every time i use it or not?

Both struct and enum are value types so that would apply to enumerations as well. But that is irrelevant here
because you don't have to create a value at all:
Static properties (also called type properties) are properties of the type itself, not of an instance of that type.

Re: What advantages has the choice of a struct or enum?

As mentioned in the linked-to article:

The advantage of using a case-less enumeration is that it can't accidentally be instantiated and works as a pure namespace.

So for a structure,

let foo = PhysicalConstants()

creates a (useless) value of type PhysicalConstants, but
for a case-less enumeration it fails to compile:

let foo = PhysicalConstants()
// error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers


Related Topics



Leave a reply



Submit