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
theclass 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:
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.
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
How to Print Out a Property's Contents Using Xcode Debugger
Avplayer with Playback Controls of Avplayerviewcontroller
How to Access User Defined Runtime Attribute from the 'Sender' Object
Confirm Back Button on Uinavigationcontroller
Check If 3D Touch Is Supported and Enabled on the iOS9 Device
Bypass Code Signing with Xcode 6
iOS - Spritekit - How to Calculate the Distance Between Two Nodes
Installing Openssl Library for Xcode
Mkmapview Doesn't Zoom Correctly While User Tracking Mode Is Mkusertrackingmodefollowwithheading
Insert String at Cursor Position of Uitextfield
Code Signing Issue in Xcode Version 8
How to Take Uiimage of Avcapturevideopreviewlayer Instead of Avcapturephotooutput Capture
Uitableview: Nested Section Headers
iOS 8.3 and Later, Facebook Share Text Not Inserted
Is This a Bug with Mkmapkitdelegate Mapview:Didupdateuserlocation
I Just Want to Open Ms Outlook App and See Mailto Screen Using Url Scheme at iOS