When NOT to use eraseToAnyPublisher() - swift

Combine seems to be built with type-erasure in mind. One reason is to avoid the complex types that are generated by many chained operators, such as the explanation defined in this question.
I'm curious about the cases where you would not want to call eraseToAnyPublisher(). I thought of a possible candidate:
func fetchResource() -> Future<Model, Error>
In this case, fetchResource isn't meant to emit more than once, and giving the return type of Future would add clarity to the functionality.
You could also return AnyPublisher:
func fetchResource() -> AnyPublisher<Model, Error>
This allows you to hide the implementation details from the consumer and protect against misuse. There is a tradeoff though... the consumer wouldn't know the semantics of the Future:
Future executes as soon as it's created, compared to some publishers that emit values only when there's a subscription
Future retains their eventual result and shares/replays the value to any future subscribers
Anyone know of any good examples of when you wouldn't eraseToAnyPublisher()?

AnyPublisher is only a temporary solution until we're able to add constraints to opaque types.
e.g. this…
var publisher: AnyPublisher<Int, Never> { .init(Just(1)) }
…should actually be something like this:
var publisher<Publisher: Combine.Publisher>: some Publisher
where Publisher.Output == Int, Publisher.Failure == Never {
Just(1)
}
You'll find a lot of discussion on the Swift forum about how this is not easy to implement (and what syntax to use!), hence why we're still using the intermediate solution of public type-erasing types.
There's no protocol in between Future and Publisher. That's what you're looking for, with this question. If you'd like to enforce a stronger contract, add some stuff to an inherited protocol…
protocol Futurey: Publisher {
extension Future: Futurey {
…and then, unfortunately, you'll have to create another erasing type. For now.
struct AnyFuturey<Output, Failure> {

Related

Why does the generic type not participate in method overloading via constraint further down the call chain?

Swift allows generic methods to be overloaded by the constraints placed upon the generic types passed in. If you use this with concrete types, then the type passed in will participate in this overloading and constraints will be inferred from that type.
As soon as a generic method delegates to another with overload resolution, the constraints can no longer be inferred and will instead utilize the constraints already placed on the type from above.
protocol Conformance {}
extension String : Conformance {}
// #1
func baseMethod<T>(_ value: T) {
let isConforming = T.self is Conformance.Type
}
// #2
func baseMethod<T>(_ value: T) where T : Conformance {
let isConforming = T.self is Conformance.Type
}
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
func run() {
// Calls #2, isConforming = true
baseMethod(String())
// Calls #1, isConforming = true
delegatingMethod(String())
}
I assume this is there so that you have sufficient type information from the call site about what constraints are applicable no matter where the generic type is used, but it seems to severely and artificially limit the utility of overloading by constraint.
Are there any known workarounds to this oddity? Something that emulates this would be extremely useful.
Swift allows generic methods to be overloaded by the constraints placed upon the generic types passed in.
Yes...but be very clear that this is a static overload, not a dynamic override. It is based on types that can be proven at compile-time.
func delegatingMethod<T>(_ value: T) {
baseMethod(value)
}
We're compiling this now, and we need to write it as a concrete, static function call, possibly inlined, into the binary. What do we know about T? We know nothing about T, so any where clause will fail.
We don't even know about how this function is called, because the call may come from another compile unit or module. While in principle, it could have different semantics based on access level, such that one version were used when it is private and all calls can be evaluated, and another used when it's public, that would be a really horrible source of bugs.
What you're asking for is that delegatingMethod defer its decision about what function call to make until runtime. That's not how generics work. Moreover, you're asking that all the where clauses be encoded somewhere in the binary so that they can be evaluated at runtime. Also not how generics work. That would require a much more dynamic dispatch system than Swift wants to implement. It's not impossible; it's just a completely different animal, and prevents lots of optimizations.
This feels like you're trying to reinvent class inheritance with protocols and generics. You can't. They're different solutions and have different features. Class inheritance is fundamentally dynamic. Protocols and generics are fundamentally static. If you want dynamic dispatch based on specific types, use classes.

Closure identity in swift: unregister observing closure

When rethinking my everyday programming patterns to be more swifty, there is one, that I really struggle with: observing changes. After a lot of thinking and research I have yet to find a satisfying solution. That is one,
that is easy to use,
leverages the full potential of swift's strong type system,
is compatible with value types and
allows for static dispatch.
Maybe the latter one is not possible and that's the reason why my search is unsuccessful so far. If so, I would like to know why?
Some of the work-arounds I found so far:
SO: Observer Pattern in Swift (Using Any or objective_c runtime functionality)
Solving the binding problem with Swift (IMHO rather awkward to use)
The ones based on closures e.g Answer by Airspeed Velocity
The third one is so far the one that ticks the most boxes it's type safe, straight forward to use, and compatible with value types. For reference:
// central part is an observable protocol that can be fulfilled by
// any observable type.
protocol Observable {
associatedtype Value
func register(f: Value->())
}
// this would be implemented like
struct ObeservableInt: Observable {
// observable value
var value: Int {
didSet {
// inform all observers
for f in observers {
f(value)
}
}
}
var observers = Array<Int->()>()
mutating func register(f: Int->()) {
observers.append(f)
}
}
So far so good. But what happens if our observer is not needed any more? To avoid a memory leak we should unregister it. But this is seemingly not possible with this architecture. Despite being reference types, closures don't have a reliable identity. That is unless we force dynamic dispatch by annotation with #objc_block. Another alternative is to return a token from register(f:) and use that in an the unregister(token:) call.
So my question is, are there any better alternatives regarding the listed criteria? If not, which one of the two solutions #objc_block or using token is the preferred one?

Design pattern for Swift using a protocol as a delegate

updated Clarifying question to make clear this is an issue with a protocol that has a typealias, causing the general error of can only be used as a generic constraint.
I have the following class/protocol pattern:
protocol Storage { /* ... */ }
protocol StorageView {
typealias StorageType: Storage
/* ... */
}
class StorageColumnView<StorageType:Storage>: StorageView { /* ... */ }
class SomeStorage: Storage { /* ... */ }
and I want to define a class that combines my Storage class with View class. Ideally, it would look something like:
class MyClass<S:StorageType> {
var view:ViewType<S>
}
This won't compile because you can't specify a variable's type based on a protocol. After searching around, the general answer I found was to use type-erasure and make a AnyView class. However, such an approach seems cumbersome for a single variable (in theory this is the only place I'll use it) and difficult because StorageView has enough functionality to make wrapping each variable time consuming. Additionally, the methods of the view may get called a decent amount (yes, premature optimization is the root of all evil, but its subscripts will be called in loops), so I'm worried about the overhead.
Three alternative methods I'm currently investigating are:
(1) Declaring view as AnyObject, and then casting it to the correct type:
var view:AnyObject
// ...
view = StorageColumnView(/*...*/)
// ...
if let v = view as? StorageView {
// operate on v
}
(2) Treating view as a function, and letting the type be defined using a closure:
var view: () -> StorageView
// ...
view = { return StorageColumnView(self) }
/// ...
view().doX()
(3) Parameterizing MyClass by the ViewType rather than Storage:
class MyClass<V:ViewType> {
typealias StorageType = ViewType.StorageType
}
I'm trying to evaluate which of the 3 options is best (in terms of Swift style as well as speed), or if there is another alternative I'm not aware of (or I really should just use type-erasure to solve this problem -- though it seems like AnyObject is essentially just that).
So:
Are there any major penalties for the first approach? Is this closer to c++'s static_cast or dynamic_cast?
Is there a way to make the closure approach a little more user-friendly (i.e. I rather not require the user to actually pass in a closure, but rather the type). Maybe create a helper function that is a generic that then returns the type?
While the last solution is potentially the cleanest in amount of extra code required, it also requires a design that is against what I'm trying to do. The ViewType is really supposed to act like a delegate, and be fungible. Instead, I'm not creating a specific type of MyClass based on the ViewType.
Any and all opinions welcome on the best design pattern! I'm a little surprised that making a delegate-type pattern is so difficult (assuming I'm doing things correctly), considering that is primarily how Objective-C is used in Cocoa.
Also, does anyone know the rationale for not letting a variable to be defined as a protocol type that has a typealias? What's the underlying difference between a protocol with and without a Self?

Stubbing methods for unit testing in swift 2

I am finding it difficult to stub methods in structs in swift. I can do it currently using a way that I'll explain below, but it feels wrong to me and would like an opinion on it.
I do not use any third party libraries for stubbing, instead I prefer to override the specific method whose result I need to change. Prior to swift, I would always use classes - so it was easy to subclass and override the method that I needed mocked in my unit test case.
Now most of my constructs are structs as they do not really need to be reference types. But then I cannot override any method in my test cases. I do it currently using protocol extensions as outlined below -
protocol AProtocol {
func a()
func b() // This calls a()
}
extension AProtocol {
func a(){
//Default implementation of a()
}
func b(){
//Default implementation of b() which also calls a()
}
}
struct A:AProtocol {
// Empty. struct A will be used by other classes/structs in the code
}
In my test case
struct TestA:AProtocol {
func a() {
Some mock implementation of a() so that b() can be tested
}
}
So my question is this - There is no real need for struct A to be implemented via a protocol. None of the other classes or structs will ever implement AProtocol. But this is the only way I can mock its methods for unit testing. I think the WWDC session on protocol extensions also showed this way of unit testing, but basically I do not need my struct as an implementation of a protocol.
Is there any other way to stub struct methods in swift (without using any third party libs)? Or a better way to test a struct's methods.
I'm going to be the person that doesn't answer the question and explores whether you really need to do what you ask I'm afraid.
My question is whether you really need mock the struct. For non mutating functions set up the struct and test the return value. For mutating functions check the state afterwards is as you expect.
With structs there shouldn't generally be side effects beyond the modification so there is no need to track exactly what other functions are called.
The bit that may be close enough to an answer to be slightly helpful:
If you really are doing something with side effects outside the struct I would suggest that you make the object that the effects are being done to or on injectable so that with an additional testing only init you can inject an alternate mock object to receive the side effect calls.

What is the usecase for ignored parameters in Swift

In Swift, you can write the following:
func foo(_:Int) -> { return 1 }
Where the underscore is an ignored parameter. I only know this because of the documentation, but cannot think of ANY usecase on why you would even do this. Am I missing something?
Ignoring parameters (or members of a tuple, which are pretty close to the same thing) makes sense when:
You're overriding a superclass function or implementing a function defined by a protocol, but your implementation of that function doesn't need one of the parameters. For example, if you hook app launching but don't need a reference to the shared UIApplication instance in that method:
override func application(_: UIApplication!, didFinishLaunchingWithOptions _: NSDictionary!) -> Bool { /* ... */ }
You're providing a closure (aka block in ObjC) as a parameter to some API, but your use of that API doesn't care about one of the parameters to the closure. For example, if you're submitting changes to the Photos library and want to throw caution to the wind, you can ignore the success and error parameters in the completion handler:
PHPhotoLibrary.sharedPhotoLibrary().performChanges({
// change requests
}, completionHandler: { _, _ in
NSLog("Changes complete. Did they succeed? Who knows!")
})
You're calling a function/method that provides multiple return values, but don't care about one of them. For example, assuming a hypothetical NSColor method that returned components as a tuple, you could ignore alpha:
let (r, g, b, _) = color.getComponents()
The reasoning behind this is that it makes your code more readable. If you declare a local name for a parameter (or tuple member) that you don't end up using, someone else reading your code (who could well be just the several-months-later version of yourself) might see that name and wonder where or how it gets used in the function body. If you declare upfront that you're ignoring that parameter (or tuple member), it makes it clear that there's no need to worry about it in that scope. (In theory, this could also provide an optimization hint to the complier, which might make your code run faster, too.)
Perhaps you're overriding a method and your override ignores one of the parameters? Making it clear that you're ignoring the parameter saves future coders from having to look through your code to work out that it's not using the parameter and makes it clear that this was intentional. Or maybe it's to create some sort of Adapter pattern where you make it clear that one of the parameters is being ignored.