I have seen some code in swift some thing like below. It used in a Framework, I'm trying to replicate the same code, as we knows getting errors. But how it is used in Framework?.
If we see the below code Strings, Localized and String code its not implementing init or extension of String replace(::) not implemented. What this code means and how to use in project as TopLevel Objects?
I can able to access this code by importing Framework, and I can make changes to that code.
Here is the code.
struct Profile { }
extension Profile {
public struct Strings {
public var title: Localized
public init()
}
}
public struct Localized : ExpressibleByStringLiteral {
public init(value: String)
}
extension String {
public func replace(_ offset: Int = 4, with symbol: Character = "*") -> String
}
What this code means
It isn't code. It's a header. It shows the declarations of some structs and methods, but not their implementations. It's basically a table of contents for you, the programmer, describing what structs there are and what methods they have. But you are not shown the actual code for how those methods are written. As you yourself have said, the framework is private.
Related
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)
}
}
I have a class Address that's a pretty simple metadata container. (At bottom.)
I have an array of Address objects that is not an optional - it's definitely there. I also have a class that maintains an optional list of these refs, like so:
public class Person {
public var addresses : [Address]?
...
}
So when I have these items, I'm using:
if let theAddresses = backgroundTask.result {
person.addresses = theAddresses
}
Which seems fairly straightforward - but for whatever reason, I have a compiler error on the assignment of person.addresses:
Cannot assign a value of type '[Address]' to a value of type '[Address]?'
Which seems unreasonable. What can I check or experiment with to determine what's going on here?
This is with Xcode 6.4.
public class Address {
public let streetNum: Int
public let streetName: String
public let city: String
public let state: String
public let zip: String
}
The source code for BackgroundTask:
public class BackgroundTask<T> {
public var result: T?
}
Phew - figured it out. This was occurring after a large-ish refactoring, and the Address class existed in two different modules - the iOS application module, as well as the embedded framework.
It was intended for the embedded framework, so I removed it from the 'Compiled Sources' section of the iOS application, and everything's solid.
Seems two different "versions" of the class were being used depending on where they were being referenced/returned.
in this example getInstance is public so it makes sense to be accessible but the private variable was accessible as well, why?
public class SingleObject {
public struct Static {
private static var object: SingleObject?
public static func getObject() -> SingleObject {
if (object == nil) {
object = SingleObject()
}
return object!
}
}
}
SingleObject.Static.object //why private is accessible here?
SingleObject.Static.getObject()
As of Swift 3, the example code no longer compiles. A new modifier called fileprivate was added and works the way private used to work (i.e. it can be seen by anything else in the same file).
private in Swift 3 and 4 now works more like you would expect it to - in Swift 3, it can only be accessed within the context it was declared in, while in Swift 4 it can also be accessed from extensions to that type (but only if they're in the same file).
The private access modifier makes a declaration private to the file and not to the class or struct. That sounds a little weird, I know, but it's how it's implemented in swift.
The other 2 access modifiers are:
internal: accessible in the current module only
public: accessible from anywhere
Suggested reading: Access Control
The private keyword means that the variable is only accessible within the same file not within the same class.
You are accessing the property from within the same file, which is why it is working. Try doing it from a different file and you will see that it is not accessible.
I have a Swift framework that defines a struct:
public struct CollectionTO {
var index: Order
var title: String
var description: String
}
However, I can't seem to use the implicit memberwise initialiser from another project that imports the library. The error is:
'CollectionTO' cannot be initialised because it has no accessible initialisers
i.e. the default synthesized memberwise initialiser is not public.
var collection1 = CollectionTO(index: 1, title: "New Releases", description: "All the new releases")
I'm having to add my own init method like so:
public struct CollectionTO {
var index: Order
var title: String
var description: String
public init(index: Order, title: String, description: String) {
self.index = index;
self.title = title;
self.description = description;
}
}
... but is there a way to do this without explicitly defining a public init?
Quoting the manual:
"Default Memberwise Initializers for Structure Types
The default memberwise initializer for a structure type is considered private if any of the structure’s stored properties are private. Otherwise, the initializer has an access level of internal.
As with the default initializer above, if you want a public structure type to be initializable with a memberwise initializer when used in another module, you must provide a public memberwise initializer yourself as part of the type’s definition."
Excerpt from "The Swift Programming Language", section "Access Control".
While it is not possible to have the default memberwise initializer at least you can make one quickly with the following steps:
UPDATE: Xcode 11 and later
As mentioned by Brock Batsell on the comments, for Xcode 11 and later all you need to is this:
Right click the class or struct name and choose refactor ->
Generate Memberwise Initializer
Xcode 10 and earlier answer
Make the object a class temporarily instead of a struct
Save
Right click the class name and choose refactor ->
Generate Memberwise Initializer
Change it back to a struct
We now have a ruby gem 💎 to parse a complete swift data model file, line-by-line, and add public access modifiers, public member-wise default initializers, and other things into a separate auto-generated output swift file.
This gem is called swift_republic
Please check out the following documentation for running this gem:
https://github.com/mehul90/swift_republic
Sometimes it's really annoying having an initializer when you don't need one. If you're constantly updating the variables to the object, it becomes bothersome very quickly to update the variables in 3 places (variable declaration, initializer parameter, and initializer implementation).
A workaround I've used for this issue is to have a static variable on the struct to act as (or essentially wrap) the "initializer". For instance:
struct MyStruct {
static var empty = Self()
static func empty(name: String) -> Self {
.init(privateName: name)
}
private var identifier: String = ""
}
Then you can call it similar to how you would an initializer (with autocomplete and everything!):
func someFunction(_ value: MyStruct) { ... }
//someFunction(.init()) -> ERROR, invalid due to `private` variable
someFunction(.empty)
someFunction(.empty(name: "Dan IRL"))
let myObject = MyStruct.empty
let myObject2 = MyStruct.empty(name: "Monty Python")
You have to define public init by yourself, luckily starting from Xcode 14 🥳 there is an automatic initializer completion (source - 60399329)
What protocol do I have to implement to control the way an object is represented within a string interpolation in Swift?
I wan't to specify what get's printed in something like this:
struct A{
}
var a = A()
println("\(a)")
You need to implement the Printable protocol:
This protocol should be adopted by types that wish to customize their
textual representation. This textual representation is used when
objects are written to an OutputStreamType.
protocol Printable {
var description: String { get }
}
There's also the DebugPrintable protocol when it's only for debugging purposes:
This protocol should be adopted by types that wish to customize
their textual representation used for debugging purposes. This
textual representation is used when objects are written to an
OutputStreamType.
protocol DebugPrintable {
var debugDescription: String { get }
}
Documentation (Thanks #MartinR)
Note: As #Antonio and #MartinR mentioned in the comments, this doesn't work in the playground (as of Xcode6 GM anyway); that's a known bug. It does work in compiled apps.
From the Xcode6 GM Release Notes:
In Playgrounds, println() ignores the Printable conformance of
user-defined types. (16562388)
As of Swift 2.0 Printable has now become CustomStringConvertible. Everything stays the same as before, you still need to implement
var description: String { get }
But now its called CustomStringConvertible. And debug is CustomDebugStringConvertible
In Swift 5 Apple introduced Custom String Interpolation.
Suppose you have person struct with two properties name and age.
struct Person {
var name: String
var age: Int
}
If you wanted to add a special string interpolation for that so that we can print persons in descriptive way, we can add an extension to String.StringInterpolation with a new appendInterpolation() method.
extension String.StringInterpolation {
mutating func appendInterpolation(_ person: Person) {
appendInterpolation("My name is \(person.name) and I'm \(person.age) years old.")
}
}
Now If we print the person details like:
let person = Person(name: "Yogendra", age: 28)
print("Person Details: \(person)")
Output will be:
Person Details: My name is Yogendra and I'm 28 years old.
I would like to put an alternative solution here:
The protocol for string interpolation in Swift is StringInterpolationConvertible. That is, any class which implements the protocol, can be constructed from a string interpolation.
Back to the question, to control what is printed out for a String string interpolation of instances of class A, you would need to create a String extension and overload the init(stringInterpolationSegment expr: A) function.
extension String {
init(stringInterpolationSegment expr: A) {
//do custom work here
//for example: self.init(expr.description)
}
}
In case you are looking for a way to remove the annoying "Optional(...)" when interpolating Optional variables, which I think is the main reason why people would want to control how an object gets printed out, just have a look at the pod NoOptionalInterpolation here.
Additional information (edited):
Confirm that overriding description will only work for your own struct/class, but not for existing struct/class such as Int and Optional.