ReactiveCocoa: creating a signal that applies a map over an observer - objective-c

From what I understand, the RACSubject equivalent of ReactiveCocoa 4 is the Observer class.
I want to have a signal and an observer linked together so that the signal sends events applying a map operation to the events sent to the observer.
In Obj-C it looks like this:
// ViewModel.h
#interface ViewModel
#property (readonly) RACSubject *someAction; //expects e.g. int values
#property (readonly) RACSignal *someSignal; //sends e.g. string values
#end
// ViewModel.m
//redeclaring the signal and action as readwrite
#implementation
- (id)init {
_someAction = [RACSubject subject];
_someSignal = [_someAction map:^id(NSNumber *index) {
return "Some string based on index passed in";
}];
}
#end
Now when someone pushes a value onto someAction, the someSignal will fire an event containing a derived value.
How do I achieve the same effect in Swift?
What I've been able to do so far is something like this:
public class ViewModel: NSObject {
public let (internalSignal, someAction) = Signal<Int, NoError>.pipe()
public var someSignal: Signal<String, NoError> {
get {
return self.internalSignal.map({ [unowned self](index: Int) -> String in
return "Some string value based on \(self.someArray[index])"
})
}
}
public let someArray = [1, 2, 3, 4, 5]
}
Which looks like a bad solution because
internalSignal should be private but needs to be declared public in order to match it to Signal's pipe
someSignal is computed every time it's needed therefore, even though the same signal could be reused over and over. Also can't be declared as a let constant.

You could initialize the members in init just like ObjC...
public class ViewModel: NSObject {
private let internalSignal: Signal<Int, NoError>
public let someAction: Observer<Int, NoError>
public let someSignal: Signal<String, NoError>
override init() {
(internalSignal, someAction) = Signal<Int, NoError>.pipe()
someSignal = internalSignal.map { index in
"Some string value based on \(index)"
}
super.init()
}
}
For someSignal you could also use lazy initialization, which allows the member to refer to self:
public class ViewModel: NSObject {
private let internalSignal: Signal<Int, NoError>
public let someAction: Observer<Int, NoError>
public private(set) lazy var someSignal: Signal<String, NoError> =
self.internalSignal.map { [unowned self] index in
"Some string value based on \(self.someArray[index])"
}
override init() {
(internalSignal, someAction) = Signal<Int, NoError>.pipe()
super.init()
}
}
Unlike the first piece of code, the lazy-var is initialized only before someSignal is used, not at the ViewModel's initialization.
Also, since it is a var, Swift allows you use mutate its value (there is no such thing as lazy let). We can restrict the permission using private(set), but this won't prevent you accidentally write self.someSignal = ... somewhere.
Alternatively, you could make someSignal an implicitly unwrapped optional and initialize manually:
public class ViewModel: NSObject {
private let internalSignal: Signal<Int, NoError>
public let someAction: Observer<Int, NoError>
public private(set) var someSignal: Signal<String, NoError>!
override init() {
(internalSignal, someAction) = Signal<Int, NoError>.pipe()
super.init()
someSignal = internalSignal.map { [unowned self] index in
"Some string value based on \(self.someArray[index])"
}
}
}

Related

Hiding base class constructor parameters in Kotlin

I am trying to understand how to hide a base constructor parameter in a subclass in kotlin. How do you put a facade over a base constructor? This doesn't work:
import com.android.volley.Request
import com.android.volley.Response
class MyCustomRequest(url: String)
: Request<String>(Request.Method.POST, url, hiddenListener) {
private fun hiddenListener() = Response.ErrorListener {
/* super secret listener */
}
...
}
I think I understand the problem:
During construction of a new instance of a derived class, the base
class initialization is done as the first step (preceded only by
evaluation of the arguments for the base class constructor) and thus
happens before the initialization logic of the derived class is run.
I'm trying to solve this problem for Volley, where I need my custom request to be be a Request so that it can be passed into a RequestQueue. It would be easier of RequestQueue took in some kind of interface but since it doesn't I have to subclass. There are other ways I can hide these complexities from the caller, but this limitation has come up for me other times in Kotlin and I'm not sure how to solve it.
I am not familiar with volley but I tried to come up with an example that should give you some insight how to solve your problem. What you can do is use a companion object:
interface MyListener {
fun handleEvent()
}
open class Base<T>(anything: Any, val listener: MyListener) { // this would be your Request class
fun onSomeEvent() {
listener.handleEvent()
}
}
class Derived(anything: Any) : Base<Any>(anything, hiddenListener) { // this would be your MyCustomRequest class
private companion object {
private val hiddenListener = object : MyListener {
override fun handleEvent() {
// do secret stuff here
}
}
}
}
So if you apply this to your problem, the result should look something like this:
class MyCustomRequest(url: String)
: Request<String>(Request.Method.POST, url, hiddenListener) {
private companion object {
private val hiddenListener = Response.ErrorListener {
/* super secret listener */
}
}
...
}
A different way would be to use a decorator, create your Request withing that decorator and just delegate the calls to it:
class Decorator(anything: Any) {
private var inner: Base<Any>
private val hiddenListener: MyListener = object : MyListener {
override fun handleEvent() { }
}
init {
inner = Base(anything, hiddenListener)
}
}
And once again for your example that would look like this:
class MyCustomRequest(url: String) {
private var inner: Request<String>
private val hiddenListener = Response.ErrorListener {
/* super secret listener */
}
init {
inner = Request<String>(Request.Method.POST, url, hiddenListener)
}
...
}

Swift 3 - Singleton

class MyManager {
private static var __once: () = {
Static.instance = MyManager()
}()
class var sharedInstance: MyManager {
struct Static {
static var onceToken: Int = 0
static var instance: MyManager? = nil
}
_ = MyManager.__once
return Static.instance!
}
fileprivate init() {
print("MyManager init");
}
....... etc
calling it
aManager = MyManager.sharedInstance
results in
MyManager init fatal error: unexpectedly found nil while unwrapping an Optional value
_ = MyManager.__once isn't calling your __once function, it's assigning it to nothing. You forgot the ():
MyManager.__once()
That's the whole purpose of requiring _ =, to make you realize you're dealing with the function itself, not a function call.
Regardless, this is an unnecessarily convoluted and messy implmentation of a singleton. All you need is:
class MyManager {
static let instance = MyManager()
}
It's lazy, thread-safe, and sane.
For me this is the best way, make init private.
// MARK: - Singleton
final class Singleton {
// Can't init is singleton
private init() { }
// MARK: Shared Instance
static let shared = Singleton()
// MARK: Local Variable
var emptyStringArray : [String] = []
}

Having a singleton use the value from initWithCoder instead of creating a new instance in Swift

I have a simple boolean variable in a function on which a set an observer to check when it changes:
var userValid: Bool{
didSet{
let valid=userValid ? "valid" : "not valid"
print("uservalid changed to \(valid)")
}
}
I set it to false in the init and then to true in the program: the initialiser is called twice once for the class and once for the subclass but I am alway checking the value in the class. So I am seeing the variable is set to true in the observer, but then when I check it in another function I find it at false without the observer to be ever called again.
As it comes out the problem seems to stem from the fact I initialise two times the class: once as a singleton and the other one with:
init?(coder aDecoder: NSCoder)
Of course I initialise the singleton with:
public class func sharedMapDelegate() -> MapDelegate {
struct Static {
static let instance : MapDelegate = MapDelegate()
}
return Static.instance
}
How may I return the value generated from the initWithCoder instead of creating a new one?
I think I have fixed it by changing the singleton to:
public class func sharedMapDelegate() -> MapDelegate {
struct Static {
static var instance : MapDelegate {
if let me = Factory.sharedFactory().mapHandler {
return me
} else {
Factory.sharedFactory().mapHandler=MapDelegate()
return Factory.sharedFactory().mapHandler
}
}
}
return Static.instance
}

Singleton with properties in Swift 3

In Apple's Using Swift with Cocoa and Objective-C document (updated for Swift 3) they give the following example of the Singleton pattern:
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
Let's imagine that this singleton needs to manage a variable array of Strings. How/where would I declare that property and ensure it gets initialized properly to an empty [String] array?
For me this is the best way, make init private. Swift 3 \ 4 \ 5 syntax
// MARK: - Singleton
final class Singleton {
// Can't init is singleton
private init() { }
// MARK: Shared Instance
static let shared = Singleton()
// MARK: Local Variable
var emptyStringArray = [String]()
}
You can initialize an empty array like this.
class Singleton {
//MARK: Shared Instance
static let sharedInstance : Singleton = {
let instance = Singleton(array: [])
return instance
}()
//MARK: Local Variable
var emptyStringArray : [String]
//MARK: Init
init( array : [String]) {
emptyStringArray = array
}
}
Or if you prefer a different approach, this one will do fine.
class Singleton {
//MARK: Shared Instance
static let sharedInstance : Singleton = {
let instance = Singleton()
return instance
}()
//MARK: Local Variable
var emptyStringArray : [String]? = nil
//MARK: Init
convenience init() {
self.init(array : [])
}
//MARK: Init Array
init( array : [String]) {
emptyStringArray = array
}
}
As per the apple's documentation: In Swift, you can simply use a static type property, which is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneously.
class Singleton {
// MARK: - Shared
static let shared = Singleton()
}
With initialization method:
class Singleton {
// MARK: - Shared
static let shared = Singleton()
// MARK: - Initializer
private init() {
}
}
Any initialisation would be done in an init method. No difference here between a singleton and a non-singleton.

Implementing a generic weak storage box which knows when the value becomes nil

Not long after I posted this question, I got an idea of how a generic weak storage box could be implemented, that knows and sends an event when the weak value it holds is deallocked.
Here's what I mean by that (an example implementation that doesn't work):
class WeakValue<T: AnyObject> {
weak var value: T? {
didSet { /* Send event here when value is changed __or becomes nil__ */ }
}
}
This doesn't work. For some reason, property observers are not triggered when they observe a weak var and it becomes nil (missing feature, anyone?).
So, here's the idea I had:
private class Watcher {
weak var delegate: WeakValue<AnyObject>?
init(delegate d: WeakValue<AnyObject>) { delegate = d }
deinit { delegate?.watcherWillDisappear() }
}
public class WeakValue<T: AnyObject> {
private let storage = NSMapTable.strongToWeakObjectsMapTable()
public init() {}
public init(value v: T?) { value = v; reloadValue() }
public weak var value: T? { didSet { reloadValue() } }
private func reloadValue() {
storage.removeAllObjects()
if let v = value { storage.setObject(v, forKey: Watcher(delegate: unsafeBitCast(self, WeakValue<AnyObject>.self))) }
}
private func watcherWillDisappear() {
/* Event triggered here */
}
}
The idea was to use the functionality of NSMapTable to my advantage. Here's how it should work:
When a value is set, a strong-key/weak-value pair is added to NSMapTable. The key is a Watcher class that only NSMapTable holds a reference to (that's why it has to be strong). The value is the actual value that is to be stored.
Whenever the value is deallocked, NSMapTable removes the key/value pair from its storage, which in turn deallocks the Watcher class (set as the key and which only NSMapTable holds a reference to), which, when doing so, warns the WeakValue class.
My question is twofold:
This doesn't seem to work (I didn't test this on a Playground, I tested it on a real project): the test class I feed to WeakValue is deallocked, but watcherWillDisappear is not called. Why doesn't it work?
This is not very efficient, right? (creating a new NSMapTable for every weak value I want to store and for which I need an alert when deallocked)