Object wrapper (surrogate) forwarding methods in Swift - swift

CBPeripheral is a painful object to test as it can not be instanced by itself. Therefore, I'm using a wrapper (HBRPeripheralWrapper) around it (also for other purposes).
I would like to forward most of call on the wrapper
(HBRPeripheralWrapper) to the actual wrapped object CBPeripheral.
It technically works using forwardInvocation but how can I adopt a similar pattern in Swift?
PS: NSInvocation is not available in Swift
class HBRPeripheralWrapper {
let peripheral:CBPeripheral
// I would like to avoid this "manual" forwarding
var identifier: NSUUID {
get {
return peripheral.identifier
}
}
init(peripheral:CBPeripheral) {
self.peripheral = peripheral
}
// target forwarding is great, but how can I make the compiler happy?
override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {
if(self.peripheral.respondsToSelector(aSelector)) {
return self.peripheral
}
return super.forwardingTargetForSelector(aSelector)
}
}

Instead of making HBRPeripheralWrapper, consider extending CBPeripheral
extension CBPeripheral {
// add whatever else you need here.
}
You don't say exactly what you do in HBRPeripheralWrapper other than forwarding, so I can't provide more help.

Related

How to implement custom implementation of method?

I'm drawing a blank for some reason.. If I want to make a bunch of objects from a class, but I want each instance to have its own unique implementation of a certain method, how would I do this?
For example:
class MyClass {
var name: String
func doSomething() {
// Each object would have custom implementation of this method, here.
}
}
Do I provide each object with its own closure during initialization, and then call that closure in the doSomething() method? I'm trying to figure out the correct or "Swiftly" way to do this. I'm also thinking along the lines of something with protocols, but I can't seem to figure out how to go about this.
I think there're many ways to do it.
In case of Base class + some sub-classes (e.g. Animal, subclassed by Dog, Cat, etc), you can do this:
First of all it's a good idea to define a protocol:
protocol MyProtocol {
func doSomething()
}
Also provide a default implementation, which throws a fatal error if a class doesn't override that method:
extension MyProtocol {
func doSomething() {
fatalError("You must override me")
}
}
Now your base class confirms the protocol thanks to default implementation. But it will throw a fatal error at runtime:
class MyClass: MyProtocol {
// conformant
}
Child class, however, will run correctly as long as it overrides this function:
class MyOtherClass: MyClass {
func doSomething() {
print("Doing it!")
}
}
You could also move fatal error into base class, and not do any extension implementation.
In case of many instances of the same Class, that solution makes no sense. You can use a very simple callback design:
typealias MyDelegate = () -> Void
class MyClass {
var delegate: MyDelegate?
func doSomething() {
delegate?()
}
}
let x = MyClass()
x.delegate = {
print("do it!")
}
x.doSomething()
// Or you can use a defined function
func doIt() {
print("also doing it")
}
x.delegate = doIt
x.doSomething()
It can also be that you re looking for Strategy pattern, or Template pattern. Depends on your usage details.
Do I provide each object with its own closure during initialization, and then call that closure in the doSomething() method
Yes. That is extremely common and eminently Swifty. Incredibly miminalistic example:
struct S {
let f:()->()
func doYourThing() { f() }
}
let s = S { print("hello") }
let s2 = S { print("goodbye" )}
s.doYourThing() // hello
s2.doYourThing() // goodbye
Giving an object a settable method instance property is very, very easy and common. It doesn't have to be provided during initialization — you might set this property later on, and a lot of built-in objects work that way too.
That, after all, is all you're doing when you create a data task with dataTask(with:completionHandler:). You are creating a data task and handing it a function which it stores, and which it will call when it has performed the actual networking.

Trying to call a class method from a protocol (Swift)

I am trying to write a fake for MFMailComposeViewController for testing so I made a protocol called MailComposeViewController and a class FakeComposeViewController that is conformed to this protocol. I also made MFMailComposeViewController conform to this protocol as well.
So in my code when I call it I am saying of type MailComposeViewController I want to have a replacement for MFMailComposeViewController.canSendMail(). If I try to replace with my protocol using: MailComposeViewController.canSendMail() I get the error Static member 'canSendMail' cannot be used on protocol metatype 'MailComposeViewController.Protocol' which makes sense. but how would I go about writing around this so I could decide to pass in a FakeComposeViewController.canSendMail() true response when testing and the real MFMailComposeViewController.canSendMail() when running?
You can work with Type of MailComposeViewController itself
func check(for viewControllerType: MailComposeViewController.Type) {
if viewControllerType.canSendMail() { ... }
}
Similar to what Robert suggested you could also get the type of the passed controller via:
func test(controller: MailComposeViewController) {
if type(of: controller).canSendMail() {
// Do stuff
} else {
// Do something different
}
}

How to use inout variables with closures defined by other sources?

I'm relatively new to Swift and was wondering how I could achieve this exact thing.
I have a Swift process, and I want to toggle a flag on completion, and I have the following code:
task.terminationHandler = { process in
isTaskComplete.toggle()
}
I have this exact code duplicated in various views and was trying to convert it to a function, with my first attempt of referencing the isTaskComplete flag by using inout.
However, because terminationHandler itself defines the parameters of the closure it takes, there is no way for me to attach a secondary inout parameter. I was wondering if there was any way for me to reference the flag inside the closure and have the value be referenced?
For what it's worth in using Swift 5 and Xcode 11.5.
Any help will be greatly appreciated! Thanks :)
You can use protocols and protocol extensions for that.
protocol NameYourProtocol {
var task: TypeOfTask { get } // { get set } If you need
var isTaskComplete: Bool { get }
}
extension NameYourProtocol {
func handleTermination() {
task.terminationHandler = { process in
isTaskComplete.toggle()
}
}
}
And this is what you will do in every class you need to call it:
class Worker: NameYourProtocol {
// This will be required by protocol.
var task = TypeOfTask()
var isTaskComplete = false
init() {
// Call `handleTermination` where you need to.
handleTermination()
}
}

Conforming to Protocols in Swift Using Extensions

I have a Swift protocol defined as follows:
protocol SmartContract {
func apply(transaction :Transaction)
func addBrokenRule(_ brokenRule: BrokenRule)
var brokenRules :[BrokenRule] { get set }
}
I have an extension on SmartContract defined as follows:
extension SmartContract {
mutating func addBrokenRule(_ brokenRule :BrokenRule) {
if self.brokenRules == nil {
self.brokenRules = [BrokenRule]()
}
self.brokenRules.append(brokenRule)
}
}
I also have a class MoneyTransferContract which conforms to the protocol but does not define brokenRules. This is because I have defined the brokenRules inside the extension.
class MoneyTransferContract : SmartContract {
func apply(transaction :Transaction) { // do something here }
}
My question is how can I make sure that MoneyTransformContract conforms to the SmartContract protocol. Is there anyway to have BrokenRule available to MoneyTransformContract without defining it again and again in different SmartContracts.
john doe wrote:
Is there anyway to have BrokenRule available to MoneyTransformContract without defining it again and again in different SmartContracts.
What you want is a superclass/subclass relationship for that behavior.
class SmartContract {
func apply(transaction :Transaction) {
//implemention
}
var brokenRules: [BrokenRule] = []
func addBrokenRule(_ brokenRule :BrokenRule) {
brokenRules.append(brokenRule)
}
}
class MoneyTransferContract : SmartContract {
// Gets `brokenRules` for free from superclass.
}
class BitCoinTransferContract : SmartContract {
// Gets `brokenRules` for free from superclass.
}
If I'm understanding correctly, there is no way to do what you want. (EDIT: as Jeff notes, if you want to use inheritance as opposed to a protocol, this is possible. See his answer for how). Protocols in Swift are just lists of requirements that it is up to implementing types to properly define. Protocols generally don't have any say over the actual behavior or implementation of implementing types, and only guarantees that the properties and functions exist. Your SmartContract protocol says that every SmartContract must have a function apply(transaction:), a function addBrokenRule(_:), and a property brokenRules which can be accessed and modified.
When a type implements SmartContract it has to define each one of these. Just as you have to write out the signature to tell the compiler that you are implementing apply(transaction:), you also have to tell the compiler how the property brokenRules will be implemented. You could obtain this functionality in a somewhat useless way, by defining an extension which has brokenRules as a computed property which is essentially a no-op:
extension SmartContract {
var brokenRules: [BrokenRule] {
get { return [] }
set(newRules) { }
}
}
But this means that any implementing type which forgets to specify their own implementation for brokenRules will have a brokenRules property which always resolves to an empty array.
One reason for this is Swift's computed properties. For some implementing type, it might not make sense for brokenRules to be stored as an array--and a protocol can't force that. That's an implementation detail that a protocol author can't (and shouldn't) worry about. For instance, if BrokenRules were easily convertible to and from strings, you could imagine some class which implemented SmartContract like so:
class StringContract: SmartContract {
var ruleString: String
var brokenRules: [BrokenRule] {
get {
let stringArray = ruleString.split(separator: ",")
return stringArray.map { BrokenRule(string:String($0)) }
}
set(newRules) {
let stringArray = newRules.map { $0.stringValue }
ruleString = stringArray.joined(separator: ",")
}
}
func apply(transaction: Transaction) {
// do something here...
}
init() {
ruleString = ""
}
}
Note that we don't have to specify an implementation for addBrokenRule(_:). That's what your protocol extension gets you. By providing an implementation in the extension, you ensure that all implementing types have a default implementation of the function, and so they can choose to forego defining their own.

Determining protocol types at runtime

How can we determine if protocol conforms to a specific subtype based on user provided instances, if it's not possible this way, any alternate solutions.
API
protocol Super {}
protocol Sub: Super {} //inherited by Super protocol
class Type1: Super {} //conforms to super protocol
class Type2: Type1, Sub {} //conforms to sub protocol
inside another API class
func store(closures: [() -> Super]) {
self.closures = closures
}
when it's time to call
func go() {
for closure in closures {
var instance = closure()
if instance is Super {
//do something - system will behave differently
} else { //it's Sub
//do something else - system will behave differently
}
}
}
users of the api
class Imp1: Type1 {}
class Imp2: Type2 {}
var closures: [() -> Super] = [ { Imp1() }, { Imp2() } ]
store(closures)
my current workaround within API
func go() {
for closure in closures {
var instance = closure()
var behavior = 0
if instance as? Type2 != nil { //not so cool, should be through protocols
behavior = 1 //instead of implementations
}
if behavior == 0 { //do something within the api,
} else { //do something else within the api
}
//instance overriden method will be called
//but not important here to show, polymorphism works in here
//more concerned how the api can do something different based on the types
}
}
You are jumping through a lot of hoops to manually recreate dynamic dispatch, i.e. one of the purposes of protocols and classes. Try actually using real runtime polymorphism to solve your problem.
Take this code:
if instance is Super {
//do something
} else { //it's Sub
//do something else
}
What you are saying is, if it’s a superclass, run the superclass method, else, run the subclass. This is a bit inverted – normally when you are a subclass you want to run the subclass code not the other way around. But assuming you turn it around to the more conventional order, you are essentially describing calling a protocol’s method and expecting the appropriate implementation to get called:
(the closures aren’t really related to the question in hand so ignoring them for now)
protocol Super { func doThing() }
protocol Sub: Super { } // super is actually a bit redundant here
class Type1: Super {
func doThing() {
println("I did a super thing!")
}
}
class Type2: Sub {
func doThing() {
println("I did a sub thing!")
}
}
func doSomething(s: Super) {
s.doThing()
}
let c: [Super] = [Type1(), Type2()]
for t in c {
doSomething(t)
}
// prints “I did a super thing!”, then “I did a sub thing!"
Alternatives to consider: eliminate Sub, and have Type2 inherit from Type1. Or, since there’s no class inheritance here, you could use structs rather than classes.
Almost any time you find yourself wanting to use is?, you probably meant to use an enum. Enums allow you use to the equivalent of is? without feeling bad about it (because it isn't a problem). The reason that is? is bad OO design is that it creates a function that is closed to subtyping, while OOP itself is always open to subtyping (you should think of final as a compiler optimization, not as a fundamental part of types).
Being closed to subtyping is not a problem or a bad thing. It just requires thinking in a functional paradigm rather than an object paradigm. Enums (which are the Swift implementation of a Sum type) are exactly the tool for this, and are very often a better tool than subclassing.
enum Thing {
case Type1(... some data object(s) ...)
case Type2(... some data object(s) ...)
}
Now in go(), instead of an is? check, you switch. Not only is this not a bad thing, it's required and fully type-checked by the compiler.
(Example removes the lazy closures since they're not really part of the question.)
func go(instances: [Thing]) {
for instance in instances {
switch instance {
case Type1(let ...) { ...Type1 behaviors... }
case Type2(let ...) { ...Type2 behaviors... }
}
}
}
If you have some shared behaviors, just pull those out into a function. You're free to let your "data objects" implement certain protocols or be of specific classes if that makes things easier to pass along to shared functions. It's fine if Type2 takes associated data that happens to be a subclass of Type1.
If you come along later and add a Type3, then the compiler will warn you about every switch that fails to consider this. That's why enums are safe while is? is not.
You need objects derived from the Objective-C world to do this:
#objc protocol Super {}
#objc protocol Sub: Super {}
class Parent: NSObject, Super {}
class Child: NSObject, Sub {}
func go( closures: [() -> Super]) {
for closure in closures {
let instance = closure()
if instance is Sub { // check for Sub first, check for Super is always true
//do something
} else {
//do something else
}
}
}
Edit: Version with different method implementations:
protocol Super {
func doSomething()
}
protocol Sub: Super {}
class Parent: Super {
func doSomething() {
// do something
}
}
class Child: Sub {
func doSomething() {
// do something else
}
}
func go( closures: [() -> Super]) {
for closure in closures {
let instance = closure()
instance.doSomething()
}
}