Swift 3 access of private properties in a struct from a extension - swift

I've been looking through the swift docs and working through some examples around encapsulation, and am unsure about the behaviour that I'm seeing. I've looked for similar questions on stack, looked through the doc and looked through some tutorials (see the link below) and although this is a trivial question can't find an answer (possibly as Swift has changed?)
Creating a simple Struct representing a queue:
struct Queue<Element> {
private var elements = [Element]()
mutating func enqueue(newElement: Element) {
elements.append(newElement)
}
mutating func dequeue() -> Element? {
guard !elements.isEmpty else {
return nil
}
return elements.remove(at: 0)
}
}
Is later extended by:
extension Queue {
func peek() -> Element? {
return elements.first
}
}
But of course elements is inaccessible due to the private protection level.
It works by changing the access of elements to fileprivate - but why?
My understanding was that extensions were part of the enclosing type, and looking around the web it seems that is used to work this way https://www.andrewcbancroft.com/2015/04/22/3-nuances-of-swift-extensions/
So is my understanding of visibility wrong, or has Swift changed?

From the Swift's book:
Private access restricts the use of an entity to the enclosing declaration. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
So a private variable is only accessible within the set of curly brackets where it's defined. Swift's Access Control has never been like those of C++
, Java or C#.

With release of Swift 4 this has been changed if the extension is implemented within the same file. You can refer the doc here
Private Member in Extension
Example below is from Swift 4
protocol SomeProtocol {
func doSomething()
}
struct SomeStruct {
private var privateVariable = 12
}
extension SomeStruct: SomeProtocol {
func doSomething() {
print(privateVariable)
}
}

Related

In Swift, can you write an extension which returns a typed instance of the class the extension is on?

This is one of those things that seems simple enough, but doesn't work as you'd expect.
I'm working on a 'fluent/chaining'-style API for my classes to allow you to set properties via functions which can be chained together so you don't have to go crazy with initializers. Plus, it makes it more convenient when working with functions like map, filter and reduce which share the same kind of API.
Consider this RowManager extension...
extension RowManager
{
#discardableResult
public func isVisible(_ isVisible:Bool) -> RowManager
{
self.isVisible = isVisible
return self
}
}
This works exactly as one would expect. But there's a problem here... if you're working with a subclass of RowManager, this downcasts the object back to RowManager, losing all of the subclass-specific details.
"No worries!" I thought. "I'll just use Self and self to handle the type!" so I changed it to this...
extension RowManager
{
#discardableResult
public func isVisible(_ isVisible:Bool) -> Self // Note the capitalization representing the type, not instance
{
self.isVisible = isVisible
return self // Note the lowercase representing the instance, not type
}
}
...but that for some reason won't even compile giving the following error...
Command failed due to signal: Segmentation fault: 11
UPDATE
Doing more research, this seems to be because our code both is in, and also uses, dynamic libraries. Other questions here on SO also talk about that specific error in those cases. Perhaps this is a bug with the compiler because as others have correctly pointed out, this code works fine in a stand-alone test but as soon as the change is made in our code, the segmentation fault shows up.
Remembering something similar with class functions that return an instance of that type, I recalled how you had to use a private generic function to do the actual cast, so I tried to match that pattern with the following...
extension RowManager
{
#discardableResult
public func isVisible(_ isVisible:Bool) -> Self // Note the capitalization
{
self.isVisible = isVisible
return getTypedSelf()
}
}
private func getTypedSelf<T:RowManager>() -> T
{
guard let typedSelfInstance = self as? T
else
{
fatalError() // Technically this should never be reachable.
}
return typedSelfInstance
}
Unfortunately, that didn't work either.
For reference, here's the class-based code I attempted to base that off of (className is another extension that simply returns the string-representation of the name of the class you called it on)...
extension UITableViewCell
{
/// Attempts to dequeue a UITableViewCell from a table, implicitly using the class name as the reuse identifier
/// Returns a strongly-typed optional
class func dequeue(from tableView:UITableView) -> Self?
{
return self.dequeue(from:tableView, withReuseIdentifier:className)
}
/// Attempts to dequeue a UITableViewCell from a table based on the specified reuse identifier
/// Returns a strongly-typed optional
class func dequeue(from tableView:UITableView, withReuseIdentifier reuseIdentifier:String) -> Self?
{
return self.dequeue_Worker(tableView:tableView, reuseIdentifier:reuseIdentifier)
}
// Private implementation
private class func dequeue_Worker<T:UITableViewCell>(tableView:UITableView, reuseIdentifier:String) -> T?
{
return tableView.dequeueReusableCell(withIdentifier: reuseIdentifier) as? T
}
}
At WWDC Apple confirmed this was a Swift compiler issue that something else In our codebase was triggering, adding there should never be a case where you get a Seg11 fault in the compiler under any circumstances, so this question is actually invalid. Closing it now, but I will report back if they ever address it.

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

This article has been helpful in understanding the new access specifiers in Swift 3. It also gives some examples of different usages of fileprivate and private.
My question is - isn't using fileprivate on a function that is going to be used only in this file the same as using private?
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:
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.
I just draw a diagram about private, fileprivate, open and public
Hope it can quickly help you , for text description please refer to Martin R 's answer
[ Update Swift 4, 5 ]
Updated for Swift 5
Private vs FilePrivate
For better clarity paste the code snippet in Playground
class Sum1 {
let a: Int!
let b: Int!
private var result: Int?
fileprivate var resultt: Int?
init(a : Int, b: Int) {
self.a = a
self.b = b
}
func sum(){
result = a + b
print(result as! Int)
}
}
let aObj = Sum1.init(a: 10, b: 20)
aObj.sum()
aObj.resultt //File Private Accessible as inside same swift file
aObj.result //Private varaible will not be accessible outside its definition except extensions
extension Sum1{
func testing() {
// Both private and fileprivate accessible in extensions
print(result)
print(resultt)
}
}
//If SUM2 class is created in same file as Sum1 ---
class Sum2{
func test(){
let aSum1 = Sum1.init(a: 2, b: 2)
// Only file private accessible
aSum1.resultt
}
}
Note: Outside of Swift file both private and fileprivate are not accessible.
A practical rule of thumb is that you use private for variables, constants, inner structs and classes that are used only inside the declaration of your class / struct. You use fileprivate for things that are used inside of your extensions within the same file as your class/struct but outside of their defining curly braces (ie. their lexical scope).
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
//This is not used outside of class Viewcontroller
private var titleText = "Demo"
//This gets used in the extension
fileprivate var list = [String]()
override func viewDidLoad() {
navigationItem.title = titleText
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return list.count
}
}
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**
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
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.
Although #MartinR's and #StephenChen's answer are perfect, Swift 4 changes things a little bit.
Private is now considered as private to a class in which it is declared and also to its extensions.
FilePrivate is considered to be private in that file be it a class in which the variable is defined, it's extension, or any other classes defined in that same file.
filePrivate - access controll level is within the file.
case 1: If we create extension with in same class file and try to access fileprivate function or fileprivate property in its extension - access allowed
case 2: If we create a extension of class in new file - And now try to access fileprivate function or fileprivate property - access not allowed
private - access control level is with in lexical scope
case 1: If property or function is declared as private in class - then scope is by default the class.
case 2: if private instance is declared with in function body - then scope of instance is limited to function body.
This is the explanation for swift 4. For swift 3, the difference is the private. swift 3 private cannot be accessed by its extension, only Class A itself can access.
After swift 4, fileprivate becomes a bit redundant, because person normally will not define the subclass in the same file. Private should be enough for most cases.
In the following example, language constructs modified by private and fileprivate seem to behave identically:
fileprivate func fact(_ n: Int) -> Int {
if (n == 0) {
return 1
} else {
return n * fact(n - 1)
}
}
private func gauss(_ n: Int) -> Int {
if (n == 0) {
return 0
} else {
return n + gauss(n - 1)
}
}
print(fact(0))
print(fact(5))
print(fact(3))
print(gauss(10))
print(gauss(9))
This is according to intuition, I guess. But, is there any exception?
Kindest regards.
class Privacy {
fileprivate(set) var pu:Int {
get {
return self.pr
}
set {
self.pr = newValue
}
}
private var pr:Int = 0
fileprivate var fp:Int = 0
func ex() {
print("\(self.pu) == \(self.pr) and not \(self.fp)")
}
}
extension Privacy {
func ex2() {
self.pu = 5
self.ex()
}
}
I like this because it is super simple for ivars.
Try changing fileprivate to private (and vice versa) and see what happens on compile...

Want to avoid copy-pasting method names for a Swift 2 delegate dispatcher

I’m trying to implement a dispatcher to notify multiple targets for a delegate pattern protocol.
What’s a better way of doing the following pattern, without copy-pasting for every method name? Reflection, aspect-oriented programming, meta-programming all come to mind:
public class AirBatteryClientDelegateDispatcher: AirBatteryClientDelegate {
private var targets = [AirBatteryClientDelegate]()
public func clientDidStartScan(client: AirBatteryClient) {
for target in targets {
target.clientDidStartScan?(client)
}
}
. . .
}
For reference, I’m using the following protocol with a dozen more similar methods:
#objc public protocol AirBatteryClientDelegate: class {
optional func clientDidStartScan(client: AirBatteryClient)
optional func clientDidStopScan(client: AirBatteryClient)
optional func clientDidUpdateState(client: AirBatteryClient)
. . .
}
You will have to implement all the delegate methods explicitly, but you can at least reduce the amount of repetition by implementing them all the same way. Effectively, since you're using an Objective-C feature (optional protocol methods), you are writing this code in Objective-C:
#objc protocol AirBatteryClientDelegate: NSObjectProtocol { // *
optional func clientDidStartScan(client: AirBatteryClient)
optional func clientDidStopScan(client: AirBatteryClient)
optional func clientDidUpdateState(client: AirBatteryClient)
}
class AirBatteryClientDelegateDispatcher {
private var targets = [AirBatteryClientDelegate]()
private func call(f:String, client:AnyObject) {
for target in targets {
let f = f + ":" // work around Swift bug
if target.respondsToSelector(Selector(f)) {
target.performSelector(Selector(f), withObject:client)
}
}
}
func clientDidStartScan(client: AirBatteryClient) {
call(#function, client:client) // or __FUNCTION__ before Swift 2.2
}
// ... and the others are identical
}
However, it would be even better if you really were writing this code in Objective-C, which is made for this kind of dynamic forwarding. You'd be able to be even more elegant. But I won't describe how you'd do that, as it would take us too far afield from what you asked.

Swift generics and protocols issue

I'm trying to push MVVM patterns on my application, but I've found that quite difficult using Swift and Generics. Example:
I have a Comic struct on my model layer. But I want my viewControllers to consume objects conforming ComicViewModel protocol in order to increase separation of concerns.
I'm wrapping the model structs in a class called Box defined like this:
public class Box<T> {
public let value: T
public init(_ value: T) { self.value = value }
}
This is used only to wrap the actual return value in a Result enum like the one explained here
However, the Swift compiler doesn't seem to like the cast from Comic to ComicViewModel even if I'm clearly defining that
func sampleComics() -> Box<Comic> {...}
protocol ComicViewModel {...}
extension Comic : ComicViewModel {...}
func fetchComicsViewModel() -> Box<ComicViewModel> {
return sampleComics() //ERROR
}
Full playground available here.
Thanks a lot for your help!
Sad to say, Swift doesn't perform implicit casting like that. As of now, you have to re-Box() the value.
func fetchComicsViewModel() -> Box<ComicViewModel> {
return Box(sampleComics().value)
}

How do I make a private function in Swift? [duplicate]

This question already has answers here:
Does Swift have access modifiers?
(16 answers)
Closed 8 years ago.
How do I make a private function in Swift?
Here is an example:
import UIKit
class AnotherClass {
var someVar = 1
let someConst = 2
func somePrivateFunc() -> Bool {
return true
}
func someFunc() -> (Int -> Bool) {
var someInnerFuncVar = { (num: Int)->Bool in
return true
}
return someInnerFuncVar
}
init() {
var vc = ViewController()
}
}
But if this is the only way to do it....
At the moment there are no visibility modifiers in swift.
On the developers forum, the language authors said it's on the top of their priority list.
Quoting greg parker from here:
We don't usually promise anything for the future, but in this case we are making an exception. Swift will have access control mechanisms.
In the same forum they suggest you can use nested classes, in this fashion, but this is really only for preventing the code-completion to catch the inner methods. They're not really private in the sense that anyone can instantiate the nested class and access those methods.
import Foundation
class KSPoint {
class _KSPointInner {
class func distance(point p1 : KSPoint, toPoint p2 : KSPoint) -> Double {
return sqrt(pow(Double(p2.x - p1.x), 2) + pow(Double(p2.y - p1.y), 2))
}
}
var x : Int
func distance(point : KSPoint, toPoint : KSPoint) -> Double {
return _KSPointInner.distance(point: point, toPoint: toPoint)
}
}
Alternatively, you can use Nested Classes like so:
// Public interface
class Bakery
{
// Private implementation
class Baker
{
func prepareToMakeBread(numberOfLoafs:Int)
{
println("Preparing to make \(numberOfLoafs) loafs of bread...")
}
func bakeBread()
{
println("Baking the bread...")
}
func packageBread()
{
println("Packaging the freshly baked bread...")
}
}
// Public method
func buyBread(numberOfLoafs:Int)
{
println("Customer requests \(numberOfLoafs) loafs of bread!")
let baker = Bakery.Baker()
baker.prepareToMakeBread(numberOfLoafs)
baker.bakeBread()
baker.packageBread()
}
}
let bakery = Bakery()
bakery.buyBread(4)
Output:
Customer requests 4 loafs of bread!
Preparing to make 4 loafs of bread...
Baking the bread...
Packaging the freshly baked bread...
However, technically they are not private as someone can instantiate a Bakery.Baker and call the methods. Functions inside functions do work but are ugly...
See my answer over here.
In short, when you talk about making a "private method" or "private function" in Swift or ObjC (or ruby or java or…) those methods aren't really "private". There's no actual access control around them. Any language that offers even a little introspection lets developers get to those value from outside the class if they really want to.
So what we're talking about, then, is a way to define a public-facing interface that shows only the functionality we want it to, and "hides" the rest that we consider "private".
The swift mechanism for declaring interfaces is the protocol, and it can be used for this purpose.