I want to pass the value as reference.
var a = "*"
var b = ""
func hello(c: inout String){
b = c
a = "**"
print(b)
print(c)
}
hello(c: &a)
The output for the above is
B: *
C: **
I want to change the value of B as well as in, I want to pass the reference to B not the value
I want the output to be
B: **
C: **
Any help would be appreciated. Thanks in advance
Something that you can do is this
var b = ""
var a = "*"{
didSet{
b = a
}
}
and when the value of a changes the b will have the value of a
Related
I'm considering converting a project using my own custom signal framework to use ReactiveSwift instead, but there is a fundamental issue I've never figured out how to resolve in ReactiveSwift:
As a simplified example, let's say you have two mutable properties:
let a = MutableProperty<Int>(1)
let b = MutableProperty<Int>(2)
Then, we derive a property that combines both to implement our logic:
let c = Property.combineLatest(a, b).map { a, b in
return a + b
}
Later, we receive some information that causes us to update the values of both a and b at the same time:
a.value = 3
b.value = 4
The problem now is that c will inform its listeners that it has the values 3 -> 5 -> 7. The 5 is entirely spurious and does not represent a valid state, as we never wanted a state where a was equal to 3 and b was equal to 2.
Is there a way around this? A way to suppress updates to a Property while updating all of its dependencies to new states, and only letting an update through once you are done?
combineLatest‘s fundamental purpose is to send a value when either of its upstream inputs send a new value, so I don’t think there’s a way to avoid this issue if you want to use that operator.
If it’s important that both values update truly simultaneously then consider using a MutableProperty<(Int, Int)> or putting the two values in a struct. If you give a little more context about what you’re actually trying to accomplish then maybe we could give a better answer.
Pausing Updates
So I really don't recommend doing something like this, but if you want a general purpose technique for "pausing" updates then you can do it with a global variable indicating whether updates are paused and the filter operator:
let a = MutableProperty<Int>(1)
let b = MutableProperty<Int>(2)
var pauseUpdates = false
let c = Property.combineLatest(a, b)
.filter(initial: (0, 0)) { _ in !pauseUpdates }
.map { a, b in
return a + b
}
func update(newA: Int, newB: Int) {
pauseUpdates = true
a.value = newA
pauseUpdates = false
b.value = newB
}
c.producer.startWithValues { c in print(c) }
update(newA: 3, newB: 4)
But there are probably better context-specific solutions for achieving whatever you are trying to achieve.
Using a sampler to manually trigger updates
An alternate solution is to use the sample operator to manually choose when to take a value:
class MyClass {
let a = MutableProperty<Int>(1)
let b = MutableProperty<Int>(2)
let c: Property<Int>
private let sampler: Signal<Void, Never>.Observer
init() {
let (signal, input) = Signal<Void, Never>.pipe()
sampler = input
let updates = Property.combineLatest(a, b)
.map { a, b in
return a + b
}
.producer
.sample(with: signal)
.map { $0.0 }
c = Property(initial: a.value + b.value, then: updates)
}
func update(a: Int, b: Int) {
self.a.value = a
self.b.value = b
sampler.send(value: ())
}
}
let x = MyClass()
x.c.producer.startWithValues { c in print(c) }
x.update(a: 3, b: 4)
Using zip
If a and b are always going to change together, you can use the zip operator which waits for both inputs to have new values:
let a = MutableProperty<Int>(1)
let b = MutableProperty<Int>(2)
let c = Property.zip(a, b).map(+)
c.producer.startWithValues { c in print(c) }
a.value = 3
b.value = 4
Use zip with methods for each type of update
class MyClass {
let a = MutableProperty<Int>(1)
let b = MutableProperty<Int>(2)
let c: Property<Int>
init() {
c = Property.zip(a, b).map(+)
}
func update(a: Int, b: Int) {
self.a.value = a
self.b.value = b
}
func update(a: Int) {
self.a.value = a
self.b.value = self.b.value
}
func update(b: Int) {
self.a.value = self.a.value
self.b.value = b
}
}
let x = MyClass()
x.c.producer.startWithValues { c in print(c) }
x.update(a: 5)
x.update(b: 7)
x.update(a: 8, b: 8)
Combining the values into one struct
I thought I would provide an example of this even though you said you didn't want to do it, because MutableProperty has a modify method that makes it less cumbersome than you might think to do atomic updates:
struct Values {
var a: Int
var b: Int
}
let ab = MutableProperty(Values(a: 1, b: 2))
let c = ab.map { $0.a + $0.b }
c.producer.startWithValues { c in print(c) }
ab.modify { values in
values.a = 3
values.b = 4
}
And you could even have convenience properties for directly accessing a and b even as the ab property is the source of truth:
let a = ab.map(\.a)
let b = ab.map(\.b)
Creating a new type of mutable property to wrap the composite property
You could create a new class conforming to MutablePropertyProtocol to make it more ergonomic to use a struct to hold your values:
class MutablePropertyWrapper<T, U>: MutablePropertyProtocol {
typealias Value = U
var value: U {
get { property.value[keyPath: keyPath] }
set {
property.modify { val in
var newVal = val
newVal[keyPath: self.keyPath] = newValue
val = newVal
}
}
}
var lifetime: Lifetime {
property.lifetime
}
var producer: SignalProducer<U, Never> {
property.map(keyPath).producer
}
var signal: Signal<U, Never> {
property.map(keyPath).signal
}
private let property: MutableProperty<T>
private let keyPath: WritableKeyPath<T, U>
init(_ property: MutableProperty<T>, keyPath: WritableKeyPath<T, U>) {
self.property = property
self.keyPath = keyPath
}
}
With this, you can create mutable versions of a and b that make it nice and easy to both get and set values:
struct Values {
var a: Int
var b: Int
}
let ab = MutableProperty(Values(a: 1, b: 2))
let a = MutablePropertyWrapper(ab, keyPath: \.a)
let b = MutablePropertyWrapper(ab, keyPath: \.b)
let c = ab.map { $0.a + $0.b }
c.producer.startWithValues { c in print(c) }
// Update the values individually, triggering two updates
a.value = 10
b.value = 20
// Update both values atomically, triggering a single update
ab.modify { values in
values.a = 30
values.b = 40
}
If you have the Xcode 11 Beta installed, you can even use the new key path based #dynamicMemberLookup feature to make this more ergonomic:
#dynamicMemberLookup
protocol MemberAccessingProperty: MutablePropertyProtocol {
subscript<U>(dynamicMember keyPath: WritableKeyPath<Value, U>) -> MutablePropertyWrapper<Value, U> { get }
}
extension MutableProperty: MemberAccessingProperty {
subscript<U>(dynamicMember keyPath: WritableKeyPath<Value, U>) -> MutablePropertyWrapper<Value, U> {
return MutablePropertyWrapper(self, keyPath: keyPath)
}
}
Now instead of:
let a = MutablePropertyWrapper(ab, keyPath: \.a)
let b = MutablePropertyWrapper(ab, keyPath: \.b)
You can write:
let a = ab.a
let b = ab.b
Or just set the values directly without creating separate variables:
ab.a.value = 10
ab.b.value = 20
Is there a good reason why this fails:
class Test<T: Hashable> {}
var d: Test<AnyHashable>? = nil
let t = Test<String>()
d = t // Cannot assign value of type 'Test<String>' to type 'Test<AnyHashable>?'
while this obviously works ?
var d: AnyHashable? = nil
let t = "123"
d = t // Works fine
I want to achieve something like
var a, b, c: MyType = MyType()
but this line doesn't compile because compiler treats the type annotation MyType is only for variable c thus a and b are missing either type annotation or a initial value for type inference.
Both of followings are legal :
// legal but verbose
var a = MyType()
var b = MyType()
var c = MyType()
// legal but verbose to initialize
var a, b, c: MyType
a = MyType()
b = MyType()
c = MyType()
These two styles I can think of are both legal but somehow verbose, especially if there are dozens of variables of same type.
Is there any elegant way to achieve this?
Two options in Swift: commas or tuples.
With commas separated statements:
var a = MyType(), b = MyType(), c = MyType()
With a tuple statement:
var (a, b, c) = (MyType(), MyType(), MyType())
Also, but discouraged, you can make multiple statements on one line using semi-colons:
var a = MyType(); var b = MyType(); var c = MyType()
You can declare multiple constants or multiple variables on a single
line, separated by commas:
var a = "", b = "", c = ""
NOTE
If a stored value in your code is not going to change, always declare
it as a constant with the let keyword. Use variables only for storing
values that need to be able to change.
Documentation HERE.
In your case:
var a = MyType(), b = MyType(), c = MyType()
MyType = MyType()
var MyType: [Any] = [Int, "String", "abc", Double, etc..]
Swift 5+
Some possible solution (maybe worth it if you're planning on doing this several times) is writting a struct to initialize your values and a method (or computed property) on that struct to return the individual components unpacked. You could also add a typealias for improved readability:
typealias MyTypeTrio = (a: MyType, b: MyType, c: MyType)
struct MyTypesPack {
var a, b, c: MyType
init(a: MyType = .init(), b: MyType = .init(), c: MyType = .init()) {
self.a = a
self.b = b
self.c = c
}
var components: MyTypeTrio { (a, b, c) }
}
Usage:
...
let (a, b, c) = MyPackTrio().components
Of course, if you don't need that much granularity of control you may as well just add a static (or not) helper method anywhere (but preferrably in a namespace, such as in an extension of MyType, for instance).
You coud simply write:
extension MyType {
static let trio: MyTypeTrio = (a: MyType(), b: MyType(), c: MyType())
}
and then just use it as:
var (a, b, c) = MyType.trio
I ran into a similar situation recently regarding color components.
Here's what I did then:
typealias RGBA = (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)
struct RGBAColor {
var red, green, blue, alpha: CGFloat
init(red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0) {
self.red = red
self.green = green
self.blue = blue
self.alpha = alpha
}
var components: RGBA { (red, green, blue, alpha) }
}
More smarter way to do this is
let type = (MyType(), MyType(), MyType())
var (a, b, c) = type
I am trying to concatenate multiple strings in swift 3:
var a:String? = "a"
var b:String? = "b"
var c:String? = "c"
var d:String? = a! + b! + c!
When compiling I get the following error:
error: cannot convert value of type 'String' to specified type 'String?'
var d:String? = a! + b! + c!
~~~~~~~~^~~~
This used to work in swift 2. I am not sure why it doesn't work anymore.
Bug report filed by OP:
SR-1122: Failure to typecheck chain of binary operators on force-unwrapped values
Which has been resolved (fix commited to master Jan 3 2017), and should hence no longer be an issue in upcoming Swift 3.1.
This seems to be a bug (not present in Swift 2.2, only 3.0) associated with the case of:
Using the forced unwrapping operator (!) for at least 3 terms in an expression (tested using at least 2 basic operators, e.g. + or -).
For some reason, given the above, Swift messes up type inference of the expression (specifically, for the x! terms themselves, in the expression).
For all the examples below, let:
let a: String? = "a"
let b: String? = "b"
let c: String? = "c"
Bug present:
// example 1
a! + b! + c!
/* error: ambiguous reference to member '+' */
// example 2
var d: String = a! + b! + c!
/* error: ambiguous reference to member '+' */
// example 3
var d: String? = a! + b! + c!
/* error: cannot convert value of type 'String'
to specified type 'String?' */
// example 4
var d: String?
d = a! + b! + c!
/* error: cannot assign value of type 'String'
to specified type 'String?' */
// example 5 (not just for type String and '+' operator)
let a: Int? = 1
let b: Int? = 2
let c: Int? = 3
var d: Int? = a! + b! + c!
/* error: cannot convert value of type 'Int'
to specified type 'Int?' */
var e: Int? = a! - b! - c! // same error
Bug not present:
/* example 1 */
var d: String? = a! + b!
/* example 2 */
let aa = a!
let bb = b!
let cc = c!
var d: String? = aa + bb + cc
var e: String = aa + bb + cc
/* example 3 */
var d: String? = String(a!) + String(b!) + String(c!)
However as this is Swift 3.0-dev, I'm uncertain if this is really a "bug", as well as what's the policy w.r.t. reporting "bugs" in a not-yet-production version of code, but possibly you should file radar for this, just in case.
As for answering your question as how to circumvent this issue:
use e.g. intermediate variables as in Bug not present: Example 2 above,
or explicitly tell Swift all terms in the 3-term expression are strings, as in Bug not present: Example 3 above,
or, better yet, use safe unwrapping of your optional, e.g. using optional binding:
var d: String? = nil
if let a = a, b = b, c = c {
d = a + b + c
} /* if any of a, b or c are 'nil', d will remain as 'nil';
otherwise, the concenation of their unwrapped values */
Swift 3
let q: String? = "Hello"
let w: String? = "World"
let r: String? = "!"
var array = [q, w, r]
print(array.flatMap { $0 }.reduce("", {$0 + $1}))
// HelloWorld!
let q: String? = "Hello"
let w: String? = nil
let r: String? = "!"
var array = [q, w, r]
print(array.flatMap { $0 }.reduce("", {$0 + $1}))
// Hello!
func getSingleValue(_ value: String?..., seperator: String = " ") -> String? {
return value.reduce("") {
($0) + seperator + ($1 ?? "")
}.trimmingCharacters(in: CharacterSet(charactersIn: seperator) )
}
let val: String? = "nil"
val.flatMap({(str: String) -> String? in
return str + "value"
})
var a:String? = "a"
var b:String? = "b"
var c:String? = "c"
var d:String? = ""
let arr = [a,b,c]
arr.compactMap { $0 }.joined(separator: " ")
compactMap be used to filter out nil values from flattened arrays
I'm trying to figure out how to create a pointer to a pointer in Swift. Now, I know we don't exactly have pointers in Swift, but here is what I am trying to accomplish:
var foo = objA() //foo is variable referencing an instance of objA
var bar = foo //bar is a second variable referencing the instance above
foo = objA() //foo is now a reference to a new instance of objA, but bar
//is still a reference to the old instance
I would like to have bar be a reference to the foo variable instead of it being a reference to the foo object. That way, if foo becomes a reference to a different object, bar goes along for the ride.
One way of having a secondary reference to a variable would be a computed variable:
class C {}
var a = C()
var b: C { return a } // b is a computed variable, returning the current value of a
b === a // true
a = C()
b === a // true, whereas "var b = a" would have made this false
I believe this is what you want:
class O {
let n: Int
init(n: Int) { self.n = n }
}
var foo = O(n: 1)
var bar = withUnsafePointer(&foo) {$0}
print(bar.pointee.n) // Prints 1
foo = O(n: 2)
print(bar.pointee.n) // Prints 2
(Replace pointee with memory for Swift < 3.0)
I really don't know why you'd want that though.
You can try to use UnsafeMutablePointer. See an example below:
let string = UnsafeMutablePointer<String>.alloc(1)
string.initialize("Hello Swift")
print(string.memory)
let next = string
next.memory = "Bye Bye Swift"
print(string.memory) // prints "Bye Bye Swift"
But it smells a little and It will be better to avoid using technique like this.