Swift protocol for shared functionality - swift

I have a number of objects, and each need to be locked until purchased.
Each of these objects (NSManaged) have a productName String and isPurchased Bool.
I wrote a function isLocked() which uses there properties as well an external check in a singleton.
How can this be combined into a protocol so that the protocol contains the isLocked function implementation and the objects can just adhere to the protocol and then call isLocked when needed?

If im not mistaken this can be achieved with Default implementations in swift.
protocol Locakable {
var productName: String { get }
var isPurchased: Bool { get }
func lock()
func unlock()
}
extension Locakable {
func isLocked() {
if isPurchased {
//do something
//lock it
unlock()
} else {
lock()
}
}
}
For more info on what mixin or default implementation is then chek out this wiki page https://en.wikipedia.org/wiki/Mixin
However, note that isLocked() is dispatched statically. Comment if something is unclear.
You can also abstract the idea of locking and unlocking and write a default implementation on the protocol extension if possible. Or provide a customisation point like so.
class Item: Locakable {
var productName = "ItemName"
var isPurchased = false
init () {
isLocked()
}
func lock() {
}
func unlock() {
}
}

Related

How to conform to a protocol with a generic superscript affordance in Swift?

TL;DR
How can I conform to the supscript function of a protocol in my implementation?
Protocol:
protocol DataStore {
//...
subscript<T>(id: T.ID) -> T where T: Identifiable { get set }
}
Neither
subscript<T>(id: T.ID) -> T where T : Identifiable {
get { Project() }//just to return anything for the time being…
set {}
}
nor
subscript(id: Task.ID) -> Task {
get { Project() }//just to return anything for the time being…
set {}
}
work...
The details:
I have developed a habit of creating specific data stores for my models. They all have the same functionality. A specific example could look like this:
final class ProjectDataStore: ObservableObject {
{
static let shared = ProjectDataStore()
let persistence = AtPersistLocally.shared // that's from a personal package I made that handles saving and loading locally as json files
#Published var projects: [Project] {
didSet { //save }
}
private init(projects: [Project]? = nil) {
//load from persistence
}
subscript(id: Project.ID) -> Project? {
get { //return project with id }
set { //set project at id }
}
func getBinding(by id: Project.ID) -> Binding<Project> {
//return Binding
}
func getProjectBy(taskId: Task.ID) -> Project {
//return instance
}
private func getIndex(by id: Project.ID) -> Int? {
//return index in array
}
private func load() -> [Project] {
//load from persistence
}
private func save() {
//save from persistence
}
}
While this works as expected, I'd like to be able to introduce a protocol that I could when adding new functionality / models to have a blueprint on what's necessary for my DataStore.
Here is my first attempt:
protocol DataStore {
static var shared: Self { get }
}
extension DataStore {
var persistence: AtPersistLocally {
get {
AtPersistLocally.shared
}
}
}
To also conform to ObservableObject, I introduce a typealias
typealias ObservableObjectDataStore = DataStore & ObservableObject
and change my model to conform to this new typealias:
final class ProjectDataStore: ObservableObjectDataStore {
//...
}
With this, I already have a static instance and access to persistence available.
Next step of course is to move more and more properties to the protocol–which is what I am struggling with right now.
Let's look at superscript first of all: I guess I understand what needs to be added to the protocol:
protocol DataStore {
//...
subscript<T>(id: T.ID) -> T where T: Identifiable { get set }
}
My problem now is that I don't know how to go about conforming to this subscript now while also getting access to a concrete model from the generic T from the implementation. This attempt…
final class ProjectDataStore: ObservableObjectDataStore {
//...
subscript<T>(id: T.ID) -> T where T : Identifiable {
get { Project() }//just to return anything for the time being…
set {}
}
}
…leads to the error message Cannot convert return expression of type 'Task' to return type 'T'.
If I go with…
final class ProjectDataStore: ObservableObjectDataStore {
//...
subscript(id: Task.ID) -> Task {
get { Project() }//just to return anything for the time being…
set {}
}
}
…the error message changes to Type 'TaskDataStore' does not conform to protocol 'DataStore'.
So I guess basically what I am asking is: how can I conform to my protocol's generic superscript in my implementation of ProjectDataStore?
I have a feeling that I am not too far of, but a critical info is obviously missing…
subscript<T>(id: T.ID) -> T where T: Identifiable { get set }
This says that the caller may pick any Identifiable T, and this method promise return a value of that type. This can't be implemented (other than calling fatalError() and crashing). Identifiable doesn't even promise that the type has an init. Your protocol is impossible.
What you probably meant to write is, which says that a given DataStore will return some specific Identifiable type (not "whatever type the caller requests"):
protocol DataStore {
associatedType Item: Identifiable
subscript(id: Item.ID) -> Item { get set }
}
But I expect this would be much better implemented without a protocol, and just use a generic struct:
struct DataStore<Item: Identifiable> { ... }

Type constraints on contained generic type parameter

I expected the following code to print "extension" in both cases. But the type constraint on the extension does not take effect on the contained generic type. I see the same behavior when constraining on protocols too.
class Generic1<T1> {
func doSomething() {
print("base")
}
}
extension Generic1 where T1 == String {
func doSomething() {
print("extension")
}
}
class Generic2<T2> {
private let generic1 = Generic1<T2>()
func doSomething() {
generic1.doSomething()
}
}
Generic1<String>().doSomething() // prints extension
Generic2<String>().doSomething() // prints base
The only workaround I currently have is to constrain the outer generic as well like so:
extension Generic2 where T2 == String {
func doSomething() {
generic1.doSomething()
}
}
Why does this happen? Are there better solutions?
Edit: Just for completeness, the workaround that suited my case was the following:
class Generic1<T1> {
func doSomething() {
print("base")
}
}
class StringGeneric1: Generic1<String> {
override func doSomething() {
print("extension")
}
}
class Generic2<T2> {
private let generic1: Generic1<T2>
init (_ generic1: Generic1<T2>) {
self.generic1 = generic1
}
func doSomething() {
generic1.doSomething()
}
}
Generic1<String>().doSomething() // prints "base"
Generic2<String>(StringGeneric1()).doSomething() // prints "extension"
The problem is that methods defined in extensions are statically dispatched. So when you have:
class Generic2<T2> {
private let generic1 = Generic1<T2>()
func doSomething() {
generic1.doSomething()
}
}
The compiler cannot know here whether T2 is going to be a String or not, so it generates a call to the method in the base class. When you explicitly specify that T2 is String, then with that information, the compiler can generate a call to the extension's method here. Otherwise, though, the type of T2 isn't known until runtime, so you can't reach the extension method via static dispatch.
This may be solved when conditional conformances are added with Swift 4.2

Swift: how to support "template method" design pattern (since Swift doesn't have protected)?

Traditionally in the "template method" pattern, a base class implements some algorithms and defers to derived classes for specific behavior. This works well in languages like C++/C#/Java because you can use "protected" on those methods to hide them from the callers but keep it visible for derived classes. For example, in the GoF book, you have something like:
class Application
{
void CreateDocument() { ..., this->DoCreateDocument() }
protected void DoCreateDocument() { } // override for custom behavior
}
This keeps the public interface for Application clean. In Swift, because you cannot use protected, the public interface is not clean. I do not want users of Application to see DoCreateDocument.
So I'm trying another method, which instead of using methods for DoCreateDocument, I'm trying to define a closure and use "functor" patterns.
class Application
{
typealias ActionFunc = () -> ()
private let doCreateDocument : ActionFunc
init(a : ActionFunc) { self.doCreateDocument = a }
func CreateDocument() {
self.doCreateDocument()
}
}
So this class looks good - the public interface is clean. However, it's impossible to actually use this.
The obvious approach is using a derived class:
class DoApplication : Application
{
init() {
super.init(
a : {
// This would work, but you cannot use self here!
self. // anything with self. is an error
})
}
}
The problem with this approach is that in the initializer, you cannot pass a closure to super.init that uses self. I get the error self used before super.init.
That basically makes it useless because you cannot access any state variables.
However, if you don't initialize doCreateDocument in the init, you need to expose a setter of some sorts - again, the lack of protected means that the setter is on the public API. Yuck.
So is there any way to cleanly implement the template pattern that keeps the interface clean?
I know this is an ugly hack, but it works.
class DoApplication: Application {
init() {
var doCreateDocument: (Application.ActionFunc)!
super.init(a: { doCreateDocument() })
doCreateDocument = { [unowned self] in
self.foo()
}
}
func foo() {
println("DoApplication.foo");
}
}
Alternatively, you can pass self to doCreateDocument:
class Application {
typealias ActionFunc = (Application) -> ()
private let doCreateDocument : ActionFunc
init(a : ActionFunc) { self.doCreateDocument = a }
func CreateDocument() {
self.doCreateDocument(self)
}
}
class DoApplication : Application {
init() {
super.init(a : { _self in
let _self = _self as! DoApplication
_self.foo()
})
}
func foo() {
println("DoApplication.foo");
}
}

Can I simulate traits/mixins in Swift?

Does Swift have a way of mixing in traits, a la Scala? The section of the Swift book on using extensions to add protocols to existing classes comes tantalizingly close. However, since protocols can't contain an implementation, this can't be used to mix code into a class. Is there another way?
As of Swift 2.0, yes!
Providing Default Implementations
You can use protocol extensions to provide a default implementation
to any method or property requirement of that protocol. If a
conforming type provides its own implementation of a required method
or property, that implementation will be used instead of the one
provided by the extension.
One way to simulate mixing is use generic function to provide implementation
For example with these protocols
protocol Named {
func GetName() -> String
}
protocol NamedExtension {
func GetLowercaseName() -> String
func GetUppercaseName() -> String
}
I want some class to implement GetName() and use mixing so they also get GetLowercaseName() and GetUppercaseName() without implement them
This is the implementation of NamedExtension as in free function
func GetLowercaseNameImpl<T:Named>(obj:T) -> String {
return obj.GetName().lowercaseString
}
func GetUppercaseNameImpl<T:Named>(obj:T) -> String {
return obj.GetName().uppercaseString
}
and extensions on Int
extension Int : Named {
func GetName() -> String {
return "Int"
}
}
extension Int : NamedExtension {
// use provided implementation
func GetLowercaseName() -> String {
return GetLowercaseNameImpl(self)
}
func GetUppercaseName() -> String {
return GetUppercaseNameImpl(self)
}
}
and I can use
1.GetName() // result Int
1.GetUppercaseName() // result "INT"
1.GetLowercaseName() // result "int"
I don't know Scala, but from what you're telling me it is possible to simultaneously create a protocol and an extension that extends a type to add "pseudo-trait" behavior.
For example:
protocol IsGreaterThan
{
func isGreaterThan(other:Int) -> Bool
func isNotGreaterThan(other:Int) -> Bool
}
extension Int : IsGreaterThan
{
func isGreaterThan(other:Int) -> Bool
{
return self > other
}
func isNotGreaterThan(other:Int) -> Bool
{
return !isGreaterThan(other)
}
}
The real hamstring is how generics are somewhat limited for now. I think they will improve a lot in the coming revisions of Swift.
Similar to Bryan Chen's answer:
import Foundation
protocol Named {
var name : String { get }
}
protocol NamedExtension : Named { // NB extends Named
var lowercaseName : String { get }
var uppercaseName : String { get }
}
struct NamedExtensionDefault { // Put defaults inside a struct to keep name spaces seperate
static func lowercaseName(named : NamedExtension) -> String {
return (named.name as NSString).lowercaseString
}
static func uppercaseName(named : NamedExtension) -> String {
return (named.name as NSString).uppercaseString
}
}
extension Int : NamedExtension {
var name : String {
return "Int"
}
// Use default implementation
var lowercaseName : String {
return NamedExtensionDefault.lowercaseName(self)
}
var uppercaseName : String {
return NamedExtensionDefault.uppercaseName(self)
}
}
1.name // result Int
1.uppercaseName // result "INT"
1.lowercaseName // result "int"
The main difference from Bryan's answer is that I didn't use generics because I made NamedExtension extends Named, so that the default implementations can access name.
Here's my (not yet widely tested) way of doing what I think are Scala traits in Swift 2.1.1, Playgrounds-ready, two versions:
Less flexible:
protocol BigBadProtocol {
func madFunc() -> String;
// func otherFunc();
// Maybe a couple more functions here.
}
protocol BlueMadFuncUser: BigBadProtocol {}
extension BlueMadFuncUser {
func madFunc() -> String {
return "Blue"
}
}
protocol RedMadFuncUser: BigBadProtocol {}
extension RedMadFuncUser {
func madFunc() -> String {
return "Red"
}
}
class ClearClass: BigBadProtocol {
func madFunc() -> String {
return "Clear"
}
}
class BlueClass: BlueMadFuncUser {}
class RedClass: RedMadFuncUser {}
More flexible:
protocol BigBadProtocol {
func madFunc() -> String;
// func otherFunc();
// Maybe a couple more functions here.
}
protocol BlueMadFuncUser {}
extension BigBadProtocol where Self: BlueMadFuncUser {
func madFunc() -> String {
return "Blue"
}
}
protocol RedMadFuncUser {}
extension BigBadProtocol where Self: RedMadFuncUser {
func madFunc() -> String {
return "Red"
}
}
class ClearClass: BigBadProtocol {
func madFunc() -> String {
return "Clear"
}
}
class BlueClass: BigBadProtocol, BlueMadFuncUser {}
class RedClass: BigBadProtocol, RedMadFuncUser {}
Sanity check:
var classes: [BigBadProtocol] = [ClearClass(), BlueClass(), RedClass()]
// Prints "Clear, Blue, Red\n"
print((classes.map { $0.madFunc() }).joinWithSeparator(", "))
// Print another way for Playgrounds, which appears to bug out on the lines above
var s = ""
for klass in classes {
s += klass.madFunc() + " "
}
print(s)
BlueMadFuncUser and RedMadFuncUser are two versions of a trait. My terminology might be off, but then you can independently create a second trait like that and mix and match in your classes as you please.
Would be much more challenging or boiler-plate-y to reuse logic like that with an inheritance-based approach.
I ended up wanting this pattern after finding it very useful in Hack for PHP, where from what I can tell traits are very similar to Scala's: https://docs.hhvm.com/hack/other-features/trait-and-interface-requirements)

how can I make this Swift event handler boilerplate more concise?

I've seen a pattern in Java that lets you implement a subset of a list of callbacks, in a type-safe way, inline with the class that uses the callbacks:
registerHandlers(new ClassWithNoOpMethods() {
#override
public void onFooEvent(FooEvent event) { ... }
#override
public void onBarEvent(BarEvent event) { ... }
}
All nice and type-safe. I'd like to do the same thing in Swift, but some googling didn't turn up any (IMHO) elegant solutions. So I came up with this:
let registrar = EventSource.getEventRegistrar()
registrar.onFooEvent = { event in doSomethingFoo(event) }
registrar.onBarEvent = { event in doSomethingBar(event) }
...
EventSource.removeEventCallbacks(registrar)
This works fine for consuming the events - its just the subset of events I'm interested in, it lets me define the code inline, etc etc.
However, when I actually implemented this, I got a lot of repeated, boilerplate, non-DRY code. It offends me, but I can't figure out a better way to implement the scheme shown above. I'd like to appeal to the Swift gods on StackOverflow to show me a more concise way to implement this.
Here is what it looks like now:
public class Phone {
...phone stuff...
public class PhoneEventRegistrar {
let phone : Phone
init(phone : Phone) {
self.phone = phone
}
public typealias OnErrorCallback = (PhoneErrorType, String) -> Void
private var onErrorValue : OnErrorCallback?
public var onError : OnErrorCallback {
get { return onErrorValue != nil ? onErrorValue! : {_,_ in} }
set {
assert(onErrorValue == nil, "onError cannot be set twice")
onErrorValue = newValue
}
}
func invokeErrorCallback(type : PhoneErrorType, message : String) {
if let onErrorValue = onErrorValue {
onErrorValue(type, message)
}
}
public typealias OnCallStateChangeCallback = (CallState) -> Void
private var onCallStateChangeValue : OnCallStateChangeCallback?
public var onCallStateChange : OnCallStateChangeCallback {
get { return onCallStateChangeValue != nil ? onCallStateChangeValue! : {_ in} }
set {
assert(onCallStateChangeValue == nil, "onCallStateChange cannot be set twice")
onCallStateChangeValue = newValue
}
}
func invokeCallStateChangeCallback(state : CallState) {
if let onCallStateChangeValue = onCallStateChangeValue {
onCallStateChangeValue(state)
}
}
// and the mostly-similar code shown twice above is repeated for
// each possible callback
}
func invokeErrorCallbacks(type : PhoneErrorType, message : String) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
registrars.forEach({$0.invokeErrorCallback(type, message: message)})
}
func invokeCallStateChangeCallbacks(state : CallState) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
registrars.forEach({$0.invokeCallStateChangeCallback(state)})
}
// again, the mostly similar block of code shown twice above is
// repeated for each possible callback
private var registrars : [PhoneEventRegistrar] = []
public func getPhoneEventRegistrar() -> PhoneEventRegistrar {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
let registrar = PhoneEventRegistrar(phone: self)
registrars.append(registrar)
return registrar
}
public func removeRegistrarCallbacks(registrar : PhoneEventRegistrar) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
assert(registrars.contains({$0 === registrar}), "cannot remove callbacks, no matching PhoneEventRegistrar found")
registrars = registrars.filter({$0 !== registrar})
}
}
If folks see an alternative implementation that has the same usability benefits for the event consumers, i'd love to see those too. Here are some of the other options I've thought of or tried:
implement a protocol defining the callbacks. Have event consumers implement the protocol and register that for callbacks. Negative: requires all methods to be implemented - forces too many no-op callbacks.
as above, but extend the protocol with default blank implementations. Negative: still requires the event consumer to implement an extra class for the callbacks. Also, lack of dynamic dispatch for protocol extensions means registering the protocol will force generated events to go to the no-op implementation instead of the real event handler.
set the consuming class as a delegate on the event producer. Negative: still have to implement no-op callbacks. I've only ever seen one delegate per event producer, and I need several. #Darko comments below are prompting me to consider this option further.
NSNotificationCenter
There are multiple solutions for your problem. One could be to simply use NSNotificationCenter instead of implementing your own event mechanism.
With NSNotificationCenter you can register for events:
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(MyClass.myMethod),
name: "com.mycompany.myEvent1",
object: userData)
And send events from anywhere:
let userData: [NSObject: AnyObject] = [anyObject: anyDataToSend]
NSNotificationCenter.defaultCenter.postNotificationName("com.mycompany.myEvent1", object: userData)
You will find plenty of tutorials on SO and Google regarding NSNotificationCenter.
Delegate with optional protocol
Another method would be to use the delegate pattern. Create a protocol and mark it as #objc, in this way protocol methods can be marked as "optional".
#objc protocol MyEventProtocol: class {
optional func foo() -> Bool
func bar()
}
Every object which conforms to this protocol now must implement bar() but can implement optionally foo().
class MyEventReceiver: MyEventProtocol {
func bar() { // do something }
}
Then your event sender class can do something like this:
class MyEventSender {
weak var delegate: MyEventProtocol? // the name "delegate" is just convention, you can use any other name
init(receiver: MyEventReceiver) {
self.delegate = receiver
}
func sendEventToReceiver() {
if let delegate = self.delegate {
delegate.func() // guaranteed by the protocol
delegate.foo?() // foo is marked as optional, so you have to check it with ?. If foo is implemented on the receiver it will be called, otherwise not.
}
}
}
That's the basic principle. In this way you can define one protocol for all possible events but the implementer of the protocol only have to implement the methods which are not marked as optional. They are "required".
Protocol extensions with default methods
A third method would be to create a protocol extension with default methods.
protocol MyEventProtocol: {
func bar()
}
extension MyEventProtocol {
func foo() -> Bool {
return true
}
}
Then the implementor of MyEventProtocol does not have to implement foo() because there is already an implementation. (it's a kind of a "faked" #objc protocol with optional methods) If you add some generic mechanism to this solution you could also prevent the hefty code duplication. (generics in Protocols are done with associatedtype in Swift 2.2, see other tutorials)