I am getting return values from property. Is it possible? - swift

class TestClass {
var testString: String = {
print("about to initialize the property")
return "TestString"
}()
}
let testClass = TestClass()
print("before first call")
print(testClass.testString)
print(testClass.testString)
In the above program, I am getting the return value from a property. Is it possible because I have heard we been doing it for methods.
func method() -> String {
return "a string"
}
This is what I know. Can anyone elaborate my doubt?

Yes it's possible and recommended since Swift 3. If you need to get just one value without passing other values to compute it, this is the recommended approach.
For example, in Swift 2 you had UIColor.redColor() returning a red color, but since Swift 3 you need to use UIColor.redColor

Yet it is possible. These are called Computed Properties, and are thoroughly explained in the Swift Documentation

Related

Is there a way in Swift to partially match a generic?

That is, if I have a class C that takes two generics A and B, is there a way where I can cast an object to C where I don't care what B is?
My specific use case is that I need to bridge between NSView functionality and the new SwiftUI in a multi-window, but non-document based application. The problem I am having is, given an NSView, I need to obtain the SwiftUI View that it is managing (in my case a View called ContentView).
Note that I do have a solution, which I include below, but it involves the use of Mirror based reflection and I am wondering if there is a better way, most likely involving the use of as? to cast to a partial match of a generic.
The bridging is done using the NSHostingView hence it should seem that one would just do the following:
if let hostingView = NSApplication.shared.keyWindow?.contentView as? NSHostingView<ContentView> {
// do what I need with 'hostingView.rootView'
}
Unfortunately, NSHostingView.rootView does not return the actual ContentView that I created, it returns a modified version of that view dependant on the modifiers used. (In my case I'm using .environmentObject modifier.) As a result the if statement above never returns true because the type is not NSHostingView<ContentView> but rather NSHostingView<ModifiedContent<ContentView, _bunch_Of_Gobbletygook_Representing_The_Modifiers>>. One way to "solve" the problem is to print out the result of type(of: hostingView) when I create the window, and then change my cast to include the current version of the "gobbledygook", but that is brittle for the following two reasons:
If I change the modifiers, the compiler will not warn me that I need to update the cast, and
Since the "gobbledygook" contains single underscored values, I must assume those are internal details that could change. Hence without my changing any code, an OS update could cause the cast to start failing.
So I have created a solution in the form of the following NSView extension:
extension NSView {
func originalRootView<RootView: View>() -> RootView? {
if let hostingView = self as? NSHostingView<RootView> {
return hostingView.rootView
}
let mirror = Mirror(reflecting: self)
if let rootView = mirror.descendant("_rootView") {
let mirror2 = Mirror(reflecting: rootView)
if let content = mirror2.descendant("content") as? RootView {
return content
}
}
return nil
}
}
This allows me to handle my needs using the following:
private func currentContentView() -> ContentView? {
return NSApplication.shared.keyWindow?.contentView?.originalRootView()
}
... sometime later ...
if let contentView = currentContentView() {
// do what I need with contentView
}
What I would like to know is if there is a way to implement originalRootView without the use of reflection, presumably by allowing a partially specified cast to the ModifiedContent object. For example, something like the following (which does not compile):
extension NSView {
func originalRootView<RootView: View>() -> RootView? {
if let hostingView = self as? NSHostingView<RootView> {
return hostingView.rootView
}
if let hostingView = self as? NSHostingView<ModifiedContent<RootView, ANY>> {
return hostingView.rootView.content
}
return nil
}
}
The problem is what to put for "ANY". I would think some form of Any or AnyObject, but the complier complains about that. Essentially I would like to tell the compiler that I don't care what ANY is so long as the ModifiedContent has RootView as its content type.
Any ideas would be appreciated.
Just to make the results official, the answer is "no" there is no way to partially match a generic as of Swift 5.1.

Is it possible to get the KVC-String from Swift 4 KeyPath?

For a project I am currently working on, it would be very useful to get the KVC-String from a KeyPath instance my method is receiving. Short example:
struct Person {
var name: String
}
let propertyCache = ["name": "something"]
func method<T>(_ keypath: KeyPath<Person, T>) -> T? {
let kvcName = keypath.kvc
return propertyCache[kvcName]
}
This might seem not very useful, but in my project it is :) I found a property on KeyPath called _kvcKeyPathString which is also public, but it returns nil every time I tried.
Or is their maybe a possibility to use reflection there? Thanks in advance for ideas/solutions!
I don't know of a pure Swift way to get the name of the property as a string yet.
But, if you add the #objc attribute to the property then _kvcKeyPathString will actually have a value instead of always being nil. Also, since Swift structs can't be represented in Objective-C, this method only works for classes.
A minimal working example usage:
class SomeClass {
#objc var someProperty = 5
}
let keyPath = \SomeClass.someProperty
print(keyPath._kvcKeyPathString)

what is the difference between these two in swift 3 [duplicate]

In the Introduction to Swift WWDC session, a read-only property description is demonstrated:
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description)
Are there any implications to choosing the above approach over using a method instead:
class Vehicle {
var numberOfWheels = 0
func description() -> String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
println(vehicle.description())
It seems to me that the most obvious reasons for choosing a read-only computed property are:
Semantics - in this example it makes sense for description to be a property of the class, rather than an action it performs.
Brevity/Clarity - prevents the need to use empty parentheses when getting the value.
Clearly the above example is overly simple, but are there other good reasons to choose one over the other? For example, are there some features of functions or properties that would guide your decision of which to use?
N.B. At first glance this seems like quite a common OOP question, but I'm keen to know of any Swift-specific features that would guide best practice when using this language.
It seems to me that it's mostly a matter of style: I strongly prefer using properties for just that: properties; meaning simple values that you can get and/or set. I use functions (or methods) when actual work is being done. Maybe something has to be computed or read from disk or from a database: In this case I use a function, even when only a simple value is returned. That way I can easily see whether a call is cheap (properties) or possibly expensive (functions).
We will probably get more clarity when Apple publishes some Swift coding conventions.
Well, you can apply Kotlin 's advices https://kotlinlang.org/docs/reference/coding-conventions.html#functions-vs-properties.
In some cases functions with no arguments might be interchangeable
with read-only properties. Although the semantics are similar, there
are some stylistic conventions on when to prefer one to another.
Prefer a property over a function when the underlying algorithm:
does not throw
complexity is cheap to calculate (or caсhed
on the first run)
returns the same result over invocations
While a question of computed properties vs methods in general is hard and subjective, currently there is one important argument in the Swift's case for preferring methods over properties. You can use methods in Swift as pure functions which is not true for properties (as of Swift 2.0 beta). This makes methods much more powerful and useful since they can participate in functional composition.
func fflat<A, R>(f: (A) -> () -> (R)) -> (A) -> (R) {
return { f($0)() }
}
func fnot<A>(f: (A) -> Bool) -> (A) -> (Bool) {
return { !f($0) }
}
extension String {
func isEmptyAsFunc() -> Bool {
return isEmpty
}
}
let strings = ["Hello", "", "world"]
strings.filter(fnot(fflat(String.isEmptyAsFunc)))
There is a difference:
If you use a property you can then eventually override it and make it read/write in a subclass.
Since the runtime is the same, this question applies to Objective-C as well. I'd say, with properties you get
a possibility of adding a setter in a subclass, making the property readwrite
an ability to use KVO/didSet for change notifications
more generally, you can pass property to methods that expect key paths, e.g. fetch request sorting
As for something specific to Swift, the only example I have is that you can use #lazy for a property.
In the read-only case, a computed property should not be considered semantically equivalent to a method, even when they behave identically, because dropping the func declaration blurs the distinction between quantities that comprise the state of an instance and quantities that are merely functions of the state. You save typing () at the call site, but risk losing clarity in your code.
As a trivial example, consider the following vector type:
struct Vector {
let x, y: Double
func length() -> Double {
return sqrt(x*x + y*y)
}
}
By declaring the length as a method, it’s clear that it’s a function of the state, which depends only on x and y.
On the other hand, if you were to express length as a computed property
struct VectorWithLengthAsProperty {
let x, y: Double
var length: Double {
return sqrt(x*x + y*y)
}
}
then when you dot-tab-complete in your IDE on an instance of VectorWithLengthAsProperty, it would look as if x, y, length were properties on an equal footing, which is conceptually incorrect.
From the performance perspective, there seems no difference. As you can see in the benchmark result.
gist
main.swift code snippet:
import Foundation
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = Date()
for _ in 0...times {
_ = myClass.prop
}
let ending = Date()
return ending.timeIntervalSince(starting)
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)
Output:
prop: 0.0380070209503174
func: 0.0350250005722046
prop: 0.371925950050354
func: 0.363085985183716
prop: 3.4023300409317
func: 3.38373708724976
prop: 33.5842199325562
func: 34.8433820009232
Program ended with exit code: 0
In Chart:
There are situations where you would prefer computed property over normal functions. Such as: returning the full name of an person. You already know the first name and the last name. So really the fullName property is a property not a function. In this case, it is computed property (because you can't set the full name, you can just extract it using the firstname and the lastname)
class Person{
let firstName: String
let lastName: String
init(firstName: String, lastName: String){
self.firstName = firstName
self.lastName = lastName
}
var fullName :String{
return firstName+" "+lastName
}
}
let william = Person(firstName: "William", lastName: "Kinaan")
william.fullName //William Kinaan
Semantically speaking, computed properties should be tightly coupled with the intrinsic state of the object - if other properties don't change, then querying the computed property at different times should give the same output (comparable via == or ===) - similar to calling a pure function on that object.
Methods on the other hand come out of the box with the assumption that we might not always get the same results, because Swift doesn't have a way to mark functions as pure. Also, methods in OOP are considered actions, which means that executing them might result in side effects. If the method has no side effects, then it can safely be converted to a computed property.
Note that both of the above statements are purely from a semantic perspective, as it might well happen for computed properties to have side effects that we don't expect, and methods to be pure.
Historically description is a property on NSObject and many would expect that it continues the same in Swift. Adding parens after it will only add confusion.
EDIT:
After furious downvoting I have to clarify something - if it is accessed via dot syntax, it can be considered a property. It doesn't matter what's under the hood. You can't access usual methods with dot syntax.
Besides, calling this property did not require extra parens, like in the case of Swift, which may lead to confusion.
An updated/fixed version of Benjamin Wen's answer incorporating Cristik's suggestion.
class MyClass {
var prop: Int {
return 88
}
func foo() -> Int {
return 88
}
}
func test(times: u_long) {
func testProp(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.prop
}
let ending = CACurrentMediaTime()
return ending - starting
}
func testFunc(times: u_long) -> TimeInterval {
let myClass = MyClass()
let starting = CACurrentMediaTime()
for _ in 0...times {
_ = myClass.foo()
}
let ending = CACurrentMediaTime()
return ending - starting
}
print("prop: \(testProp(times: times))")
print("func: \(testFunc(times: times))")
}
test(times: 100000)
test(times: 1000000)
test(times: 10000000)
test(times: 100000000)

Xcode6.3.2 Swift bug with static constants

I am trying to figure out why I am having constant compile problems with this type of construct in Xcode 6.3.2.
class Foo {
static let CONSTANT_NAME = "CONSTANT_STRING"
...
func bar () -> String {
var s = String(format:"%s,%d\n", CONSTANT_NAME, 7)
return s
}
...
}
As I understand the language, this should be perfectly legal code however Xcode is constantly (hah-pun) having issues with it raising the error
"there is no member CONSTANT_NAME in class Foo"
If I get lucky and force it to clean, and then rebuild it will some times sort itself out and work. Other times, even doing that, then trying an open/close project will still not resolve the issue.
So, I guess my implicit follow up question (if the answer to the above is - it is legal code) is: is the Xcode Swift compiler that buggy that even basic things like this are likely to cause problems? If so, swift seems to be in a pretty bad state.
static is class property, that means you have to call it like this ClassName.property
class Foo {
static let CONSTANT_NAME = "CONSTANT_STRING"
func bar () -> String {
var s = String(format:"%s,%d\n", Foo.CONSTANT_NAME, 7)
return s
}
}
That is not a bug. That is what it should be. A class property "belongs" to the class.
If you want your code work without using ClassName, do not use static
class Foo {
let CONSTANT_NAME = "CONSTANT_STRING"
func bar () -> String {
var s = String(format:"%s,%d\n",CONSTANT_NAME, 7)
return s
}
}
More details in the Apple Documentation
The static let syntax is legal and valid. The issue is that you must fully qualify that variable when you access it:
var s = String(format:"%s,%d\n", Foo.CONSTANT_NAME, 7)
The compiler error is a bit obtuse, but it is telling the truth... CONSTANT_NAME is not a member, but a type property of class Foo: Swift Type Properties
I hear you about saving key strokes. I've personally been trying to make my Swift code as idiomatic as possible by milking every short cuts but when you find code like this, you should be glad that the compiler asks you to keep on the safe side:
class Foo {
static let CONSTANT = "hello"
func bar() -> String {
let CONSTANT = "bye"
return CONSTANT // I know which one! Thanks Swift!
}
}
println(Foo.CONSTANT)
println(Foo().bar())

Swift class without initializer working?

Could you please tell me why that code (class) is working in playground?
If I understand properly there should be init or something that can be used by "blank initializer"?
class Shape{
var numberOfSides = 0
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
var shapeA = Shape()
shapeA.simpleDescription()
shapeA.numberOfSides = 7
var shapeDescription = shapeA.simpleDescription()
shapeA.simpleDescription()
Thank you for your help
If all the stored properties are given default values, as here, the class does not need to have an explicit initializer.
In Swift an init override is only required in certain cases.
For instance, if you hadn't put a default value on that numberOfSides var then you would have to have an init to provide the default value.
Or you would have had to make it optional which gives it a nil default value.
This is all explained in the iBook by apple.