I am having a public class in a different code like this -
public class Person {
public required init() {}
}
This class is in a framework and cannot be modified.
Now the problem is I have been told to inherit from this class and create a singleton object of the new class
public class Jon: Person {
public static var shared: Jon = Jon()
required init() {}
}
But the required init is letting users create multiple instances of the class Jon.
Can anybody suggest on how to do this in swift 4.
I found a solution to achieve this. Look into my solution hopefully it will serve your purpose.
public class ParentClass {
public required init() {}
}
class SubClass: ParentClass {
static let sharedInstance = SubClass(foo: "")
#available(*, unavailable)
required init() { }
//You can change the init parameter as per your requirement
private init(foo: String) {
super.init()
//Write your initialization code
}
}
If you dont want to pass any argument to the init you can do something like this.
private init(_ foo: String? = nil) {
super.init()
//Write your initialization code
}
Now you initialize your object without passing any argument like
static let sharedInstance = SubClass()
One solution is to use Composition rather than Inheritance as the design solution. Since the Person object is supposed to be singleton as well we make it immutable and initialise it in the private init method using the required init
public class Jon {
static let instance = Jon()
private init() {
person = Person()
}
public let person: Person
}
And it can be used like this (with a name property for instance)
var jon = Jon.instance
jon.person.name = "John"
or Person could be made private and computed properties added to the singleton class
public class Jon {
static let instance = Jon()
private init() {
person = Person()
}
private let person: Person
var name: String? {
get { return person.name }
set { person.name = newValue}
}
}
and then the name property is accessed directly
var jon = Jon.instance
jon.name = "John"
Related
I am working on project where I have requirements of using singleton.
while using them I stuck on following code
struct User{
var someUserProperty: String?{
willSet{
print(UserManager.shared.sharedUser ?? "")
}
}
}
class UserManager{
static var shared: UserManager = UserManager()
public var sharedUser: User?
/* Private to make this class singleton */
private init() {
self.sharedUser = User(someUserProperty: "someInitialValue")
}
}
class Managers{
static var userManager = UserManager.shared
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Managers.userManager.sharedUser?.someUserProperty = "someDifferentValue"
}
}
This code throws error in viewDidLoad as it is setting User's property and in that property's observer we are getting same User object.
To solve this, I searched and get solution, which led me to modification in UserManager as follows
class UserManager{
private let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent, target: nil)
static var shared: UserManager = UserManager()
public var sharedUser: User?{
get{
return concurrentQueue.sync {
return self.privateSharedUser
}
}set{
concurrentQueue.async(flags: .barrier){[unowned self] in
self.privateSharedUser = newValue
}
}
}
private var privateSharedUser: User?
/* Private to make this class singleton */
private init() {
self.sharedUser = User(someUserProperty: "someInitialValue")
}
}
I have used dispatch queue to allow read from different places but write in barrier mode so that it will not interrupt read operations. and it worked.
But also following solution works, and that is making me wonder because now I have removed all queuing task and just put get and set.
class UserManager{
private let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent, target: nil)
static var shared: UserManager = UserManager()
public var sharedUser: User?{
get{
return self.privateSharedUser
}set{
self.privateSharedUser = newValue
}
}
private var privateSharedUser: User?
/* Private to make this class singleton */
private init() {
self.sharedUser = User(someUserProperty: "someInitialValue")
}
}
My thinking is that what above code does is that just creating wrapper named sharedUser around actual variable privateUser. So when we set something on sharedUser behind the scenes, it will give you private privateSharedUser whose address is different than sharedUser. Is this the reason ? Or Swift is doing something great behind the scenes ? Please tell me, if any one knows
I am really new to Swift, and trying to understand how to work things out with protocol extensions. So here is my protocol:
public protocol User: class {
var name : String {get}
}
private class MyUser: User {
var name : String
init(name: String) {
self.name = name
}
}
extension User where Self:User {
func createUser(name: String) -> User {
return MyUser(name)
}
}
How do I call this function createUser from a totally different class/protocol, where I want to create an instance of User?
You could remake the function in whatever class you need it for
func createUser(name: String) -> User {
return MyUser(name)
}
then say
let newUser = createUser("WhateverName")
or you could do:
let newUser = User().createUser("WhateverName")
I am trying to write a simple property observer that can be used to see updates to a type - ie a public form of didSet. The basic implementation was easy enough, but I then wanted to use it for both strong (value and reference) types and weak (reference) types. The motivation for the latter was to serve as a lazy caching strategy wherein a shared resource would remain in use until the last observer freed it, whereupon it would query for the value again - generally from NSURLCache, but otherwise a remote server. In short, I wanted a transparent multi-tiered cache.
I have done things like this in C++, where I had stored either a type, or a type wrapped in smart pointer, through the use of a trait with typedef's for Type, StoredType, etc, so I could pass a trait for value types, or a trait for ref-counted pointer types etc.
From my understanding of Swift though, the unowned and weak modifiers are applied to the property and not to the type per se, so you can't for example do something like:
typealias StorageType = weak T
To work around this limitation, I abstracted my generic type T to always use a storage container, where the container could use either the direct type, or a weak reference to what would have to be a class-based AnyClass type. (This effort itself was cludged by the fact that you can't override assignment operators and that conversion functions were abandoned in the early betas)
Frustratingly, I ran into compiler bugs where it just segfaulted.
Given that I can't be the first person to have tried to solve this type of problem, has anybody found a clean way through it? Obviously the segfault is just another compiler bug, but perhaps there is a simpler solution?
For reference, my code (with the segfault inducing code in comments) is:
public class ObserverSubscription : Hashable {
// public (hashable)
public var hashValue: Int { return token }
// private
private init(token:Int, observable:ObservableProtocol) {
self.token = token
self.observable = observable
}
deinit {
self.observable.unsubscribe(self)
}
private var token:Int
private var observable:ObservableProtocol
}
public func ==(lhs: ObserverSubscription, rhs: ObserverSubscription) -> Bool {
return lhs.hashValue == rhs.hashValue
}
public protocol Storage {
typealias T
typealias StorageType
init(t:StorageType)
var element:StorageType { get set }
}
public class Weak<Type:AnyObject> : Storage {
typealias T = Type
typealias StorageType = T?
public required init(t:StorageType) { element = t }
public weak var element:StorageType
}
public class Strong<Type> : Storage{
typealias T = Type
typealias StorageType = T
public required init(t:StorageType) { element = t }
public var element:StorageType
}
public protocol ObservableProtocol {
func unsubscribe(subscription:ObserverSubscription)
}
public class Observable<T, Container:Storage where T == Container.T> : ObservableProtocol {
public typealias StorageType = Container.StorageType
public typealias Subscription = ObserverSubscription
public typealias ChangeNotifier = (Container.StorageType) -> ()
public init(_ t:Container.StorageType) {
self.value = Container(t:t)
}
public init(_ source:Observable<T, Container>) {
self.value = Container(t:source.value.element)
}
public func subscribe(notifier:ChangeNotifier) {
let subscription = Subscription(token: token++, observable: self)
subscriptions[subscription] = notifier
}
public func unsubscribe(subscription:Subscription) {
subscriptions.removeValueForKey(subscription)
}
public func subscription(notifier:(Container.StorageType) -> ()) -> Subscription {
let subscription = Subscription(token: token++, observable: self)
subscriptions[subscription] = notifier
return subscription
}
public func update(t:Container.StorageType) {
self.value.element = t
}
public private(set) var value:Container { didSet {
for n in subscriptions.keys {
self.subscriptions[n]!(self.value.element)
}}}
private var token:Int = 0
private var subscriptions: [Subscription: ChangeNotifier] = [:]
}
public class ValueObserver<T> : Observable<T, Strong<T>> {
override init(_ t:StorageType) {
super.init(t)
}
}
// dare ye segfault?
//public class WeakObserver<T:AnyObject> : Observable<T, Weak<T>> {
// override init(_ t:StorageType) {
// super.init(t)
// }
//}
My actual code was a little more involved, I derived a lazily loading class from the observer, but this too, induced a segfault:
//public class LazyLoader<T:AnyObject> : Observable<T, Weak<T>> {
//
// override init(_ t:StorageType) {
// super.init(t)
// }
//
// // do lazy loading here
//}
I have tested the observer in isolation, outside of the missing-trait work around, but has been many characters since I tested it. My goal at this point is to find a solution that compiles (and which could hopefully be simpler)
Thanks!
I'm trying to create a Abstract class that can fetch records from CloudKit and return the appropriate instances based on the subclass that called the fetch method.
The problem is the class method of the Base class doesn't return an instance of the Subclass.
Run the following code in playgrounds:
class Base {
class var value: String { return "Base" }
class func doSomething() -> Self { // In Obj-C this would return instanceType
println("doSomething() = \(self.value)")
let object = self.init()
return object
}
init() {
println("init() = \(self.dynamicType.value)")
}
}
class Sub: Base {
override class var value: String { return "Sub" }
override init() {
super.init()
println("Value = \(self.dynamicType.value)")
}
}
println("Base")
let base = Base.doSomething() // type = Base
println()
println("Sub")
let sub = Sub.doSomething() // type = Base !!
For some reason when calling doSomething() on the Subclass, the initializer prints the value of the Base class property ("Base" instead of "Sub):
Base doSomething() = Base
init() = Base
Sub doSomething() = Sub
init() = Base
You should get the correct string value when you do a:
NSStringFromClass(self.dynamicType)
I wrote class Vehicle in Vehicle.swift and inherited it in another class Bicycle in Bicycle.swift. But Xcode 6.1 reported an compile error: initializer does not override a designated initializer from its superclass.
Vehicle.swift:
import Foundation
public class Vehicle {
var numberOfWheels: Int?
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
Bicycle.swift:
import Foundation
public class Bicycle: Vehicle {
override init() {
super.init()
numberOfWheels = 2
}
}
Those codes are from Apple iOS Developer Library. Link: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_324
When in the same .swift file, they can pass the compile. Only do not work in different files. Is this a bug of swift?
It seems, Default Initializer is invisible from other files, as if it's declared as private init() {}.
I've not found any official documents about this behavior, though. I think it's a bug.
Anyway, explicit init() declaration solves the problem.
public class Vehicle {
init() {} // <- HERE
var numberOfWheels: Int?
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
OR as #rdelmar says in comment, explicit initial value of numberOfWheels also works:
public class Vehicle {
var numberOfWheels: Int? = nil
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
Bicycle is not a public class. Code from Apple's Library:
class Bicycle: Vehicle {
override init() {
super.init()
numberOfWheels = 2
}
}