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

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.

Related

Difference when declaring swift protocol using inheritance from another protocol or using where Self

I still don't understand what is the difference when declaring a Swift protocol using inheritance:
protocol SubProtocol: SuperProtocol { ... }
or using where Self
protocol SubProtocol where Self: SuperProtocol { ... }
By doing this on these two ways the results are exactly the same, both options compile fine, and it works, SubProtocol will have the same stuff than SuperProtocol has. So what is the difference?
The only difference I can see is the semantic, one is more clear than the other (see example below). But this is my point of view and I would like to know if someone else thinks the same, or perhaps I am miss-understanding the whole thing.
Example:
protocol Progressable {
var isInProgress: Bool { get }
}
protocol Downloadable: Progressable {
func download()
}
protocol ProgressReporting where Self: Progressable {
func reportProgress() -> Bool
}
For me, Downloadable makes sense it inherits from Progressable, every download is progressable, so that is fine.
But ProgressReporting not necessary needs to inherit from Progressable, for me it would make more sense to constraint it by using where, this way the reader can know that whoever implements it, will need to conform to Progressable too (see the comments on the code below), here is when I think the semantic is different.
class MyClassA: Downloadable {
var isInProgress: Bool { return true }
func download() {}
func foo() {
/*
I have access to `self.isInProgress` because this class conforms `Downloadable`
which inherits from `Progressable`, so this makes sense
*/
_ = self.isInProgress
}
}
class MyClassB: ProgressReporting {
var isInProgress: Bool { return true }
func reportProgress() {}
func foo() {
/*
I have access to `self.isInProgress` but according to `ProgressReporting` definition,
this class should be `Progressable` which is not, at least not explicitely
*/
_ = self.isInProgress
}
}
I would apreciate if someone can explain me what are the differences 🙂
Thanks in advance.
Speaking about Swift5, there is no difference between the two forms, see Swift 5 Release notes:
Protocols can now constrain their conforming types to those that subclass a given class. Two equivalent forms are supported:
protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ }
Swift 4.2 accepted the second form, but it wasn’t fully implemented and could sometimes crash at compile time or runtime. (SR-5581) (38077232)

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

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)
}
}

Difference in protocol implementation behavior based on type declaration [duplicate]

This question already has answers here:
Swift Protocol Extensions overriding
(5 answers)
Closed 6 years ago.
Based on whether the type is explicitly declared or inferred the below code gives different outputs.
Why does it behave this way. Why can't I implement myFloat in my class if I declare the type?
What do I need to do if i want to declare the type explicitly but also override the implementation in the extension so that the call to testClass1.myFloat() returns 2.7?
This with Xcode 8.1, Swift 2.3
import UIKit
protocol TestSource {
func myFloat() -> Float
}
extension TestSource {
func myFloat() -> Float {
return 2.5
}
}
protocol TestProtocol: TestSource {
}
class DevClass: TestProtocol {
}
class TestClass: DevClass {
func myFloat() -> Float {
return 2.7
}
}
let testClass1: TestProtocol = TestClass()
testClass1.myFloat() // Returns 2.5
let testClass2 = TestClass()
testClass2.myFloat() // Returns 2.7
This is not a bug. The short answer is that protocol extensions to not introduce dynamic dispatch. For a more thorough explanation, see this answer. The explanation there is quite thorough and contains an example.
Here is a blog post that dives even more deeply: https://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future

Overriding methods in Swift extensions

I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension, kind of like an extension per logical block that I would group with // MARK: as well.
For a UIView subclass for example, I would end up with an extension for layout-related stuff, one for subscribing and handling events and so forth. In these extensions, I inevitably have to override some UIKit methods, e.g. layoutSubviews. I never noticed any issues with this approach -- until today.
Take this class hierarchy for example:
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
The output is A B C. That makes little sense to me. I read about Protocol Extensions being statically dispatched, but this ain't a protocol. This is a regular class, and I expect method calls to be dynamically dispatched at runtime. Clearly the call on C should at least be dynamically dispatched and produce C?
If I remove the inheritance from NSObject and make C a root class, the compiler complains saying declarations in extensions cannot override yet, which I read about already. But how does having NSObject as a root class change things?
Moving both overrides into their class declaration produces A A A as expected, moving only B's produces A B B, moving only A's produces C B C, the last of which makes absolutely no sense to me: not even the one statically typed to A produces the A-output any more!
Adding the dynamic keyword to the definition or an override does seem to give me the desired behavior 'from that point in the class hierarchy downwards'...
Let's change our example to something a little less constructed, what actually made me post this question:
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
We now get A B A. Here I cannot make UIView's layoutSubviews dynamic by any means.
Moving both overrides into their class declaration gets us A A A again, only A's or only B's still gets us A B A. dynamic again solves my problems.
In theory I could add dynamic to all overrides I ever do but I feel like I'm doing something else wrong here.
Is it really wrong to use extensions for grouping code like I do?
Extensions cannot/should not override.
It is not possible to override functionality (like properties or methods) in extensions as documented in Apple's Swift Guide.
Extensions can add new functionality to a type, but they cannot override existing functionality.
Swift Developer Guide
The compiler is allowing you to override in the extension for compatibility with Objective-C. But it's actually violating the language directive.
😊That just reminded me of Isaac Asimov's "Three Laws of Robotics" 🤖
Extensions (syntactic sugar) define independent methods that receive their own arguments. The function that is called for i.e. layoutSubviews depends on the context the compiler knows about when the code is compiled. UIView inherits from UIResponder which inherits from NSObject so the override in the extension is permitted but should not be.
So there's nothing wrong with grouping but you should override in the class not in the extension.
Directive Notes
You can only override a superclass method i.e. load() initialize()in an extension of a subclass if the method is Objective-C compatible.
Therefore we can take a look at why it is allowing you to compile using layoutSubviews.
All Swift apps execute inside the Objective-C runtime except for when using pure Swift-only frameworks which allow for a Swift-only runtime.
As we found out the Objective-C runtime generally calls two class main methods load() and initialize() automatically when initializing classes in your app’s processes.
Regarding the dynamic modifier
From the Apple Developer Library (archive.org)
You can use the dynamic modifier to require that access to members be dynamically dispatched through the Objective-C runtime.
When Swift APIs are imported by the Objective-C runtime, there are no guarantees of dynamic dispatch for properties, methods, subscripts, or initializers. The Swift compiler may still devirtualize or inline member access to optimize the performance of your code, bypassing the Objective-C runtime. 😳
So dynamic can be applied to your layoutSubviews -> UIView Class since it’s represented by Objective-C and access to that member is always used using the Objective-C runtime.
That's why the compiler allowing you to use override and dynamic.
One of the goals of Swift is static dispatching, or rather the reduction of dynamic dispatching. Obj-C however is a very dynamic language. The situation you're seeing is borne out of the link between the 2 languages and the way they work together. It shouldn't really compile.
One of the main points about extensions is that they are for extending, not for replacing / overriding. It's clear from both the name and the documentation that this is the intention. Indeed if you take out the link to Obj-C from your code (remove NSObject as the superclass) it won't compile.
So, the compiler is trying to decide what it can statically dispatch and what it has to dynamically dispatch, and it's falling through a gap because of the Obj-C link in your code. The reason dynamic 'works' is because it's forcing Obj-C linking on everything so it's all always dynamic.
So, it isn't wrong to use extensions for grouping, that's great, but it is wrong to override in extensions. Any overrides should be in the main class itself, and call out to extension points.
There is a way to achieve a clean separation of class signature and implementation (in extensions) while maintaining the ability to have overrides in subclasses. The trick is to use variables in place of the functions
If you make sure to define each subclass in a separate swift source file, you can use computed variables for the overrides while keeping the corresponding implementation cleanly organized in extensions. This will circumvent Swift's "rules" and will make your class's API/signature neatly organized in one place:
// ---------- BaseClass.swift -------------
public class BaseClass
{
public var method1:(Int) -> String { return doMethod1 }
public init() {}
}
// the extension could also be in a separate file
extension BaseClass
{
private func doMethod1(param:Int) -> String { return "BaseClass \(param)" }
}
...
// ---------- ClassA.swift ----------
public class A:BaseClass
{
override public var method1:(Int) -> String { return doMethod1 }
}
// this extension can be in a separate file but not in the same
// file as the BaseClass extension that defines its doMethod1 implementation
extension A
{
private func doMethod1(param:Int) -> String
{
return "A \(param) added to \(super.method1(param))"
}
}
...
// ---------- ClassB.swift ----------
public class B:A
{
override public var method1:(Int) -> String { return doMethod1 }
}
extension B
{
private func doMethod1(param:Int) -> String
{
return "B \(param) added to \(super.method1(param))"
}
}
Each class's extension are able to use the same method names for the implementation because they are private and not visible to each other (as long as they are in separate files).
As you can see inheritance (using the variable name) works properly using super.variablename
BaseClass().method1(123) --> "BaseClass 123"
A().method1(123) --> "A 123 added to BaseClass 123"
B().method1(123) --> "B 123 added to A 123 added to BaseClass 123"
(B() as A).method1(123) --> "B 123 added to A 123 added to BaseClass 123"
(B() as BaseClass).method1(123) --> "B 123 added to A 123 added to BaseClass 123"
This answer it not aimed at the OP, other than the fact that I felt inspired to respond by his statement, "I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension ...". I'm primarily a C# programmer, and in C# one can use partial classes for this purpose. For example, Visual Studio places the UI-related stuff in a separate source file using a partial class, and leaves your main source file uncluttered so you don't have that distraction.
If you search for "swift partial class" you'll find various links where Swift adherents say that Swift doesn't need partial classes because you can use extensions. Interestingly, if you type "swift extension" into the Google search field, its first search suggestion is "swift extension override", and at the moment this Stack Overflow question is the first hit. I take that to mean that problems with (lack of) override capabilities are the most searched-for topic related to Swift extensions, and highlights the fact that Swift extensions can't possibly replace partial classes, at least if you use derived classes in your programming.
Anyway, to cut a long-winded introduction short, I ran into this problem in a situation where I wanted to move some boilerplate / baggage methods out of the main source files for Swift classes that my C#-to-Swift program was generating. After running into the problem of no override allowed for these methods after moving them to extensions, I ended up implementing the following simple-minded workaround. The main Swift source files still contain some tiny stub methods that call the real methods in the extension files, and these extension methods are given unique names to avoid the override problem.
public protocol PCopierSerializable {
static func getFieldTable(mCopier : MCopier) -> FieldTable
static func createObject(initTable : [Int : Any?]) -> Any
func doSerialization(mCopier : MCopier)
}
.
public class SimpleClass : PCopierSerializable {
public var aMember : Int32
public init(
aMember : Int32
) {
self.aMember = aMember
}
public class func getFieldTable(mCopier : MCopier) -> FieldTable {
return getFieldTable_SimpleClass(mCopier: mCopier)
}
public class func createObject(initTable : [Int : Any?]) -> Any {
return createObject_SimpleClass(initTable: initTable)
}
public func doSerialization(mCopier : MCopier) {
doSerialization_SimpleClass(mCopier: mCopier)
}
}
.
extension SimpleClass {
class func getFieldTable_SimpleClass(mCopier : MCopier) -> FieldTable {
var fieldTable : FieldTable = [ : ]
fieldTable[376442881] = { () in try mCopier.getInt32A() } // aMember
return fieldTable
}
class func createObject_SimpleClass(initTable : [Int : Any?]) -> Any {
return SimpleClass(
aMember: initTable[376442881] as! Int32
)
}
func doSerialization_SimpleClass(mCopier : MCopier) {
mCopier.writeBinaryObjectHeader(367620, 1)
mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
}
}
.
public class DerivedClass : SimpleClass {
public var aNewMember : Int32
public init(
aNewMember : Int32,
aMember : Int32
) {
self.aNewMember = aNewMember
super.init(
aMember: aMember
)
}
public class override func getFieldTable(mCopier : MCopier) -> FieldTable {
return getFieldTable_DerivedClass(mCopier: mCopier)
}
public class override func createObject(initTable : [Int : Any?]) -> Any {
return createObject_DerivedClass(initTable: initTable)
}
public override func doSerialization(mCopier : MCopier) {
doSerialization_DerivedClass(mCopier: mCopier)
}
}
.
extension DerivedClass {
class func getFieldTable_DerivedClass(mCopier : MCopier) -> FieldTable {
var fieldTable : FieldTable = [ : ]
fieldTable[376443905] = { () in try mCopier.getInt32A() } // aNewMember
fieldTable[376442881] = { () in try mCopier.getInt32A() } // aMember
return fieldTable
}
class func createObject_DerivedClass(initTable : [Int : Any?]) -> Any {
return DerivedClass(
aNewMember: initTable[376443905] as! Int32,
aMember: initTable[376442881] as! Int32
)
}
func doSerialization_DerivedClass(mCopier : MCopier) {
mCopier.writeBinaryObjectHeader(367621, 2)
mCopier.serializeProperty(376443905, .eInt32, { () in mCopier.putInt32(aNewMember) } )
mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
}
}
Like I said in my introduction, this doesn't really answer the OP's question, but I'm hoping this simple-minded workaround might be helpful to others who wish to move methods from the main source files to extension files and run into the no-override problem.
Use POP (Protocol-Oriented Programming) to override functions in extensions.
protocol AProtocol {
func aFunction()
}
extension AProtocol {
func aFunction() {
print("empty")
}
}
class AClass: AProtocol {
}
extension AClass {
func aFunction() {
print("not empty")
}
}
let cls = AClass()
cls.aFunction()
Just wanted to add that for Objective-C classes, two separate categories can end up overwriting the same method, and it this case... well... unexpected things can happen.
The Objective-C runtime doesn't make any guarantees about which extension will be used, as described by Apple here:
If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.
It's a good thing Swift prohibits this for pure Swift classes, since this kind of overly-dynamic behaviour is a potential source of hard to detect and investigate bugs.

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.