Declaration 'subscribe' cannot override more than one superclass declaration (ReSwift) - ios

I'm having a problem when overriding a function from the ReSwift Pod. I've got the following mock class:
import Foundation
import Quick
import Nimble
import RxSwift
#testable import MainProject
#testable import ReSwift
class MockReSwiftStore: ReSwift.Store<MainState> {
var dispatchDidRun: Bool = false
var subscribeWasTriggered: Bool = false
init() {
let reducer: Reducer<MainState> = {_, _ in MainState() }
super.init(reducer: reducer, state: nil)
}
required init(
reducer: #escaping (Action, State?) -> State,
state: State?,
middleware: [(#escaping DispatchFunction, #escaping () -> State?) -> (#escaping DispatchFunction) -> DispatchFunction]) {
super.init(reducer: reducer, state: state, middleware: middleware)
}
override func subscribe<SelectedState, S>(
_ subscriber: S,
transform: ((Subscription<MainState>) -> Subscription<SelectedState>)?)
where S: StoreSubscriber,
S.StoreSubscriberStateType == SelectedState {
subscribeWasTriggered = true
}
}
}
And when overriding the subscribe method I'm getting following errors
Then when using autocomplete it also shows 2 occurences:
However when looking for the original function there's only one which looks like this
open func subscribe<SelectedState, S: StoreSubscriber>(
_ subscriber: S, transform: ((Subscription<State>) -> Subscription<SelectedState>)?
) where S.StoreSubscriberStateType == SelectedState
{
// Create a subscription for the new subscriber.
let originalSubscription = Subscription<State>()
// Call the optional transformation closure. This allows callers to modify
// the subscription, e.g. in order to subselect parts of the store's state.
let transformedSubscription = transform?(originalSubscription)
_subscribe(subscriber, originalSubscription: originalSubscription,
transformedSubscription: transformedSubscription)
}
This is my compiler output
I'm out of ideas so any help is greatly appreciated
Thanks!

Here is your issue:
class Some<T> {
func echo() {
print("A")
}
}
extension Some where T: Equatable {
func echo() {
print("B")
}
}
class AnotherSome: Some<String> {
override func echo() {
print("Doesn't compile")
}
}
The problem is: ReSwift developers declare Store.subscribe behavior as a part of interface and as a part of extension (I am not sure why they chose to do it instead of introducing other objects). Swift can't figure out which part you are trying to override and thus it doesn't compile. Afaik there are no language instruments which allow you to resolve this issue.
A possible solution is to implement MockStore as a StoreType and use Store object to implement behavior for StoreType interface.

Related

How do you write a Swift completion block that can only be called once?

Let's say I have a Swift class that stores a completion block, and does a few asynchronous tasks.
I want that block to be called by whichever of the tasks finishes first, but only that one - I don't want it to be called again when the second task finishes.
How can I implement this in a clean way?
As long as you don't need this to be thread safe, you can solve this problem with a fairly straightforward #propertyWrapper.
#propertyWrapper
struct ReadableOnce<T> {
var wrappedValue: T? {
mutating get {
defer { self._value = nil }
return self._value
}
set {
self._value = newValue
}
}
private var _value: T? = nil
}
Mark the completion block var with #ReadableOnce, and it will be destroyed after the first time it's value is read.
Something like this:
class MyClass {
#ReadableOnce private var completion: ((Error?) -> Void)?
init(completion: #escaping ((Error?) -> Void)) {
self.completion = completion
}
public func doSomething() {
// These could all be invoked from different places, like your separate tasks' asynchronous callbacks
self.completion?(error) // This triggers the callback, then the property wrapper sets it to nil.
self.completion?(error) // This does nothing
self.completion?(error) // This does nothing
}
}
I wrote up more of a detailed discussion of this here but the key thing to be aware of is that reading the value sets it to nil, even if you don't invoke the closure! This might be surprising to someone who isn't familiar with the clever property wrapper you've written.
There is already a standard expression of onceness. Unfortunately the standard Objective-C is unavailable in Swift (GCD dispatch_once), but the standard Swift technique works fine, namely a property with a lazy define-and-call initializer.
Exactly how you do this depends on the level at which you want onceness to be enforced. In this example it's at the level of the class instance:
class MyClass {
// private part
private let completion : (() -> ())
private lazy var once : Void = {
self.completion()
}()
private func doCompletionOnce() {
_ = self.once
}
// public-facing part
init(completion:#escaping () -> ()) {
self.completion = completion
}
func doCompletion() {
self.doCompletionOnce()
}
}
And here we'll test it:
let c = MyClass() {
print("howdy")
}
c.doCompletion() // howdy
c.doCompletion()
let cc = MyClass() {
print("howdy2")
}
cc.doCompletion() // howdy2
cc.doCompletion()
If you promote the private stuff to the level of the class (using a static once property), the completion can be performed only once in the lifetime of the entire program.

query regarding mocking singleton in swift ,ios using xctest?

this is not a question regarding that should we use singleton or not. but rather mocking singleton related.
this is just a sample example, as i was reading about mocking singleton is tough. so i thought let me give a try.
i am able to mock it but not sure is this a correct approach ?
protocol APIManagerProtocol {
static var sharedManager: APIManagerProtocol {get set}
func doThis()
}
class APIManager: APIManagerProtocol {
static var sharedManager: APIManagerProtocol = APIManager()
private init() {
}
func doThis() {
}
}
class ViewController: UIViewController {
private var apiManager: APIManagerProtocol?
override func viewDidLoad() {
}
convenience init(_ apimanager: APIManagerProtocol){
self.init()
apiManager = apimanager
}
func DoSomeRandomStuff(){
apiManager?.doThis()
}
}
import Foundation
#testable import SingleTonUnitTesting
class MockAPIManager: APIManagerProtocol {
static var sharedManager: APIManagerProtocol = MockAPIManager()
var isdoThisCalled = false
func doThis(){
isdoThisCalled = true
}
private init(){
}
}
class ViewControllerTests: XCTestCase {
var sut: ViewController?
var mockAPIManager: MockAPIManager?
override func setUp() {
mockAPIManager = MockAPIManager.sharedManager as? MockAPIManager
sut = ViewController(mockAPIManager!)
}
func test_viewController_doSomeRandomStuffs(){
sut?.DoSomeRandomStuff()
XCTAssertTrue(mockAPIManager!.isdoThisCalled)
}
override func tearDown() {
sut = nil
mockAPIManager = nil
}
}
The basic idea is right: Avoid repeated references to the singleton directly throughout the code, but rather inject object that conforms to the protocol.
What’s not quite right is that you are testing something internal to the MockAPIManager class. The mock is only there to serve a broader goal, namely to test your business logic (without external dependencies). So, ideally, you should be testing something that is exposed by APIManagerProtocol (or some logical result of that).
So, let’s make this concrete: For example, let’s assume your API had some method to retrieve the age of a user from a web service:
public protocol APIManagerProtocol {
func fetchAge(for userid: String, completion: #escaping (Result<Int, Error>) -> Void)
}
(Note, by the way, that the static singleton method doesn’t belong in the protocol. It’s an implementation detail of the API manager, not part of the protocol. No controllers that get a manager injected will ever need to call shared/sharedManager themselves.)
And lets assume that your view controller (or perhaps better, its view model/presenter) had a method to retrieve the age and create an appropriate message to be shown in the UI:
func buildAgeMessage(for userid: String, completion: #escaping (String) -> Void) {
apiManager?.fetchAge(for: userid) { result in
switch result {
case .failure:
completion("Error retrieving age.")
case .success(let age):
completion("The user is \(age) years old.")
}
}
}
The API manager mock would then implement the method:
class MockAPIManager: APIManagerProtocol {
func fetchAge(for userid: String, completion: #escaping (Result<Int, Error>) -> Void) {
switch userid {
case "123":
completion(.success(42))
default:
completion(.failure(APIManagerError.notFound))
}
}
}
Then you could test the logic of building this string to be shown in your UI, using the mocked API rather than the actual network service:
class ViewControllerTests: XCTestCase {
var viewController: ViewController?
override func setUp() {
viewController = ViewController(MockAPIManager())
}
func testSuccessfulAgeMessage() {
let e = expectation(description: "testSuccessfulAgeMessage")
viewController?.buildAgeMessage(for: "123") { string in
XCTAssertEqual(string, "The user is 42 years old.")
e.fulfill()
}
waitForExpectations(timeout: 1)
}
func testFailureAgeMessage() {
let e = expectation(description: "testFailureAgeMessage")
viewController?.buildAgeMessage(for: "xyz") { string in
XCTAssertEqual(string, "Error retrieving age.")
e.fulfill()
}
waitForExpectations(timeout: 1)
}
}
i was reading about mocking singleton is tough
The notion is that if you have these APIManager.shared references sprinkled throughout your code, it’s harder to swap them out with the mock object. Injecting solves this problem.
Then, again, if you’ve now injected this APIManager instance everywhere to facilitate mocking and have eliminate all of these shared references, it begs the question that you wanted to avoid, namely why use a singleton anymore?

Simultaneous accesses when using PropertyWrapper

I want to create a property wrapper, that would store a callback block, and execute it every time, when it's value changes. Something like simple KVO. It works fine, but there is one problem with it. If I use the property itself in this callback block, then I get an error:
Simultaneous accesses to 0x6000007fc3d0, but modification requires exclusive access
From what I understand this is because the property itself is still being written to, while this block is executing, and this is why it can't be read.
Lets add some code, to show what I mean:
#propertyWrapper
struct ReactingProperty<T> {
init(wrappedValue: T) {
self.wrappedValue = wrappedValue
}
public var wrappedValue: T {
didSet {
reaction?(wrappedValue)
}
}
public var projectedValue: Self {
get { self }
set { self = newValue }
}
private var reaction: ((_ value: T) -> Void)?
public mutating func setupReaction(_ reaction: #escaping (_ value: T) -> Void) {
self.reaction = reaction
}
}
And AppDelegate:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
#ReactingProperty
var testInt = 0
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// 1. This will pass correctly.
$testInt.setupReaction { (value) in
print(value)
}
testInt = 1
// 2. This will cause crash, because I access testInt in this block, that is executed when value changes.
$testInt.setupReaction { [unowned self] (value) in
print(self.testInt)
}
testInt = 2
return true
}
}
I have a few workarounds for this, but none of theme is really what I need for various reasons.
If I access the value in the block from this block argument instead, and pass this argument in value didSet, then it works fine. But this forces me to always use it this way, and I would like to use this with the code, that contains various other callbacks, and sometimes it would be more convenient for me to be able to access this value directly as well.
I can execute the callback block asynchronously (DispachQueue.main.async { self.block?(value) }). But this also is not the best for my case.
Use combine instead. I will probably, but I would also like to remain this functionality for now. Also Im just curious on this issue.
Can this somehow be overcome? What variable is actually causing this read-write access error? Is this the value inside propertyWrapper or struct with propertyWrapper itself?
I think it's propertyWrapper struct accessing that causes this, and not its internal value, but Im not sure.
I think I have found the right solution. Just change from struct to class. Then read/write access is no issue.
#propertyWrapper
class ReactingProperty<T> {
init(wrappedValue: T) {
self.wrappedValue = wrappedValue
}
public var wrappedValue: T {
didSet {
reaction?(wrappedValue)
}
}
public lazy var projectedValue = self
private var reaction: ((_ value: T) -> Void)?
public mutating func setupReaction(_ reaction: #escaping (_ value: T) -> Void) {
self.reaction = reaction
}
}

Initialising member to class function causes 'self' used in method call error

I have a class attribute that points to one of the class functions. However when I try to initialize this variable with one of the functions, I get the following error:
'self' used in method call before all stored properties are initialized.
I'm able to initialize any other variable to those functions, but the error makes it sound like I'm calling the function even though I'm not.
import UIKit
import AudioToolbox
class BeatMaker {
// iPhone 7 and up use beat function, iPhone 6s use beatFallback
let hapticFunction: () -> ()
let impactGenerator = UIImpactFeedbackGenerator.init(style: .heavy)
init(supportsImpactGenerator: Bool) {
// error 1: 'self' used in method call 'beat' before all stored properties are initialized
// error 2: 'self' used in method call 'beatFallback' before all stored properties are initialized
self.hapticFunction = (supportsImpactGenerator) ? beat : beatFallback
}
private func beat() {
impactGenerator.impactOccurred()
}
private func beatFallback() {
AudioServicesPlaySystemSound(1520)
}
func makeABeat() {
hapticFunction()
}
}
In this specific case I want to make use of the Taptic Engine and simulate a click through the UIImpactFeedbackGenerator. The iPhone 6s doesn't support this engine, so I want to call a fallback function that produces a similar effect.
I also tried initializing the variable on the spot:
// this works
var hapticFunction: (BeatMaker) -> () -> () = beat
init(supportsImpactGenerator: Bool) {
if !supportsImpactGenerator {
// error: Cannot assign value of type '() -> ()' to type '(BeatMaker) -> () -> ()'
self.hapticFunction = beatFallback
// produces same error
self.hapticFunction = beatFallback.self
}
}
I know that I could make everything static or put everything out of the class, but this feels like it should work yet it doesn't. Am I missing something?
EDIT
Setting the type of type of hapticFunction to an optional seems to work, but this doesn't make any sense to me. What's the difference?
// this works
var hapticFunction: (() -> ())?
init(supportsImpactGenerator: Bool) {
self.hapticFunction = (supportsImpactGenerator) ? beat : beatFallback
}
It might be better to not use a Bool, but rather a nested Enum, which is also more extendible if you wanna add some other modes of haptic feedback later on.
I have a generalized solution for a generalized problem of your question. So either you do:
public class FunctionOwner {
private let mode: Mode
public init(`do` mode: Mode = .default) {
self.mode = mode
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
switch mode {
case .foo: foo()
case .bar: bar()
}
}
}
private extension FunctionOwner {
func foo() {
print("doing foo")
}
func bar() {
print("doing bar")
}
}
public extension FunctionOwner.Mode {
static var `default`: FunctionOwner.Mode {
return .foo
}
}
// USAGE
FunctionOwner(do: .bar).fooOrBar() // prints "doing foo"
FunctionOwner(do: .foo).fooOrBar() // prints "doing bar"
Or if you for some reason do want to keep the stored Mode, you can do this (might be relevant for your actual question on how you do a workaround of referencing self in the init.):
public class FunctionOwner {
private let _function: (FunctionOwner) -> Void
public init(`do` mode: Mode = .default) {
_function = { functionOwner in
switch mode {
case .foo: functionOwner.foo()
case .bar: functionOwner.bar()
}
}
}
}
public extension FunctionOwner {
enum Mode {
case foo, bar
}
func fooOrBar() {
_function(self)
}
}
// The rest of the code is the same as the example above
There are two method to fix this
You can:
Give hapticFunction a initial value like {}
or fix like:
class BeatMaker {
let impactGenerator = UIImpactFeedbackGenerator.init(style: .heavy)
let supportsImpactGenerator: Bool
init(supportsImpactGenerator: Bool) {
self.supportsImpactGenerator = supportsImpactGenerator
}
private func beat() {
if supportsImpactGenerator {
impactGenerator.impactOccurred()
} else {
AudioServicesPlaySystemSound(1520)
}
}
func makeABeat() {
beat()
}
}

Use current class as type constraint

I would like to have a convenience method on my class like so:
class BaseEvent {
class func on(executionHandler: (BaseEvent -> Void)) -> Handler<BaseEvent> {
return Handler<BaseEvent>(executionHandler: executionHandler)
}
}
This has the downside that execution handler doesn't have the correct type for subclasses of BaseEvent. Imagine I had a class called JumpEvent that derived from BaseEvent, in an ideal world I would be able to do the following:
let handler = JumpEvent.on { event in
//Do something with jump event
}
Unfortunately the event is of type BaseEvent and would have to be downcast.
I've tried the following, with no luck:
class func on(executionHandler: (Self -> Void)) -> Handler<BaseEvent> {
return Handler<BaseEvent>(executionHandler: executionHandler)
}
class func on<T: Self>(executionHandler: (T -> Void)) -> Handler<BaseEvent> {
return Handler<BaseEvent>(executionHandler: executionHandler)
}
Note that the return type (Handler<BaseEvent>) isn't very important, just the type of the execution handler.
My current "solution" is the following, which requires manually redefining the method in subclasses which is obviously less than ideal:
class BaseEvent {
class func on<T: BaseEvent>(executionHandler: (T -> Void)) -> Handler<T> {
return Handler<T>(executionHandler: executionHandler)
}
}
class JumpEvent: BaseEvent {
override class func on<T: JumpEvent>(executionHandler: (T -> Void)) -> Handler<T> {
return super.on(executionHandler)
}
}
Please let me know if additional information is needed.
Thank you,
Noah
I ultimately rethought my implementation and achieved the desired results with generics. This might not work for all use cases, but it worked well for mine because the subclasses were the same as the base class except for their associated model object. So BaseEvent and JumpEvent changed to:
protocol ModelType {
}
class Jump: ModelType {
}
class Event<T: ModelType> {
class func on(executionHandler: (Event<T> -> Void)) -> Handler<T> {
return Handler<T>(executionHandler: executionHandler)
}
}
This allows me to reuse functionality like I did with BaseEvent, with the added benefit that I don't need to create a new subclass for each model object.

Resources