So for the time I worked on the project and avoided Singletons and used Dependency Injection. By this I mean instead of creating a shared instance I created a class instance and passed to all controllers whichever needs.
Now my question, my model object which has references in all controllers, I need to point them either to a new object as for the requirements the data is fully updated like calling the init() again.
But if I do that in a certain controller that reference will only point to this new object.
So if you get what I mean I want the pointee of the references or where at memory address that object is there should be replaced to a new one and all references should still point to that old address / new object.
I think you need to inject not model in controllers, but service for obtaining and saving this model, something like this.
Protocol for service:
protocol ModelServiceProtocol {
func obtainModel(completion: (Model) -> Void)
func save(model: Model, compleiton: ()->Void)
}
Example ViewController with dependency:
class ViewController: UIViewController {
let modelService: ModelServiceProtocol
init(modelService: ModelServiceProtocol) {
self.modelService = modelService
}
func obtainModel() {
modelService.obtainModel { model in
// do something
}
}
func saveEditedModel() {
modelService.save(model: model) {
// model saved
}
}
}
Implementation of ModelService that will obtain and save your model:
class ModelService: ModelServiceProtocol {
func obtainModel(completion: (Model) -> Void) {
// implementation of obtainig model from some storage
}
func save(model: Model, compleiton: ()->Void) {
// implementation of saving model in some storage
}
}
Injection of dependency:
func buildController() -> ViewController {
let modelService = ModelService()
let viewController = ViewController(modelService: modelService)
return viewController
}
In this approach you will get actual model in ViewController, edit and save to some storage. Model will be actual on every step
Related
In View Controller
viewModel.frequentDate = Date() // This changes frequently
In ViewModel
struct ViewModel {
var frequentDate = Date()
mutating func validateSomeTime(startDatePicker: Observable<Date>) {
self.validdate = startDatePicker.map(someValid)
}
func someValid(_ date: Date) -> String {
if date = self.frequentDate {
return "Done"
}
}
}
frequentDate doesn't change frequently it always give first initial date. When I call observable validate the date value is initial one not updates the latest.
this self.frequentDate will never change of the VC lift cycle.
But if I changed ViewModel struct to class. It works fine
#Paulw11 mentioned a good point. You should probably make your viewModel a class and control its lifecycle in ViewController. The simplest way to do it is to instantiate your ViewModel directly inside ViewController
class ChurchesViewController {
let viewModel = ChurchesViewModel()
}
But what to do if your ViewModel uses some repositories, managers etc.? Well, you should inject ViewModel into ViewController somewhere else. In a simplest architecture such as MVVM-C you will probably use Coordinator to construct your flow:
class ChurchesCoordinator: Coordinator {
init(navigationController: UINavigationController, firstManager: FirstManager, secondManager: SecondManager) { ... }
func start() {
let vc = ChurchesViewController() // any instantiation method
let vm = ChurchesViewModel(firstManager: self.firstManager, secondManager: self.secondManager)
vc.viewModel = vm
navigationController.pushViewController(vc, animated: true, completion: nil)
}
}
This is a simple example, but I personally use a library for DI called Dip or Swinject, it simplifies things a lot. If you to choose other architectures, probably you will have another modules to make a DI.
I have a viewmode class like this :
class ViewMode {
let validateCountResult: Driver<Bool>
init(username: Driver<String>) {
validateCountResult = username
.flatMapLatest { username in
return // validate username
}
}
And I have a subclass of UIViewController as follow :
class ViewController : UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
let viewmode =
ViewMode(textfiled.rx.texttext.orEmpty.asDriver())
viewmode.validateCountResult.drive(onNext:{
// TODO Something
FuncA()
})
}
}
When viewDidload finishes, I believe the viewmode should deinits as well. But I see the binding still exists and FuncA still get called!
Why is it so?
The easiest way to understand binding is to think of the relationship as a connection between two entities:
A producer, which produces the value。
A receiver, which processes the values from the producer.
A receiver cannot return a value. This is a general rule when using bindings of RxSwift.
The fundamental function of binding is bind(to:), and to bind an observable to another entity it's required that the receiver conforms to ObserverType.
You should dispose your Disposable types by creating a DisposeBag.
If you don’t, there is no guarrantee that your viewController even deinits or your disposable types get disposed as well. They create a mutal like together via your ViewMode and all three objects stay in memory.
Take a look at this article to see how to find memory leaks.
I have a view controller that contains instances (objects) of a few related classes that need to intercommunicate.
I can easily set these up by creating instances of the objects within the VC:
var house = House ()
var road = Road ()
var town = Town ()
But how do I get a method in the House object to 'speak'/send data to the Road object? In some languages I could invoke the parent object and target the other class and its methods that way:
func sendHouseData (num: Int) {
_parent.road.getHouseData (num)
}
Obviously the _parent keyword is not swift code so won't work.
The only way I can think of doing this is to create an instance of road inside the House object as a child object, thus exposing it directly in scope to the method code. Having a lot of external code in the VC to do all the heavy lifting is another idea that seems like bad practice and inelegant.
Any ideas?
Many thanks.
Kw
One way would be to use the Delegation pattern. Each class should declare a protocol with all the messages it can send, and the class that needs to listen to those messages should implement the protocol, register as the (or one of the) delegate(s) and respond accordingly.
Here's a good example how to implement Delegation Pattern.
And a sample implementation for your objects:
protocol HouseDelegate {
func readData(data:Int)
}
class House {
var delegate:HouseDelegate
var data:Int = 0
init(delegate:HouseDelegate) {
self.delegate = delegate
}
func sendData() {
self.delegate.readData(data)
}
}
class Road: HouseDelegate {
var data:Int = 0
func readData(data: Int) {
print("Read data \(data)")
self.data = data
}
}
var road = Road ()
var house = House (delegate: road)
house.sendData() //prints "Read data 0"
Best way to handle this is by using mediator pattern, if you need to establish communication between House, Road, Town you can set it in a way that they communicate to 'mediator' (parent object). In this case parent object can mediate and coordinate between the objects
Or, you can use NSNotificationCenter, post a notification from one object and listen to the notification in another object, but this is hard to track as soon as your app gets more complex.
Let's say the Word class is parent class of the House, Road, Town.
Here you can establish communication between Word, House and Town, and inter-communication between House and Town.
Be advised this is more pseudo code I'm writting it in browser but you'll get idea
class Word {
let house = House()
let town = Town()
init() {
// Here World will be notified when the house hasReceivedVisitor and the town hasBuiltRoad.
self.house.hasReceivedVisitor = { visitorName in
print("\(visitorName) has visited the house!")
// Communication between house and town ...
self.town.doSometingWithVisitor(visitorName)
}
self.town.hasBuiltRoad = { roadNumber in
print("A road \(roadNumber) has been built!")
// Communication between town and house ...
self.house.doSometingWithRoad(roadNumber)
}
}
}
class House {
var hasReceivedVisitor: ((vistorName: String) -> ())?
func createVisitor() {
let vistor = Visitor("Mike")
self.hasReceivedVisitor?(vistor.vistorName)
}
func doSometingWithRoad(roadNumber: Int) {
// .....
}
}
class Town {
var hasBuiltRoad: ((roadNumber: Int) -> ())?
func createRoad() {
let road = Road(66)
self.hasBuiltRoad?(road.roadNumber)
}
func doSometingWithVisitor(visitorName: String) {
// .....
}
}
The same thing above can be accomplished via delegation but I like blocks more.
Basically you have 3 options: Notifications (the worst), delegation or callbacks.
TDLR; I have three classes, when Class A object is updated, it's calling on its delegate (Class B) which is calling on its delegate (Class C) without doing anything else. Class C will use Class B in different ways depending on the values in Class A. Class B need to know of its Class A at touch events. Is this acceptable?
classA { var information: String }
classB { var thing: ClassA thing.delegate = self }
classC { var things: [ClassB] for thing in things { thing.delegate = self } }
My real example
I have three classes: A mapViewController, a mapMarker and a place (model). The map holds multiple mapMarkers, and every mapMarker has a property place, which contains information of what the marker should look like (like place type, "bar", "restaurant" etc). The place might receive new information via a silent push notification, and hence being updated. When the place is updated, I need to notify the mapViewController that the marker needs to be redrawn (I'm using MapBox and their annotations doesn't support redrawing in any way but removing and adding the marker again, since the imageForAnnotation method is a delegate one.)
My first thought was to make two protocols placeDelegate and mapMarkerDelegate.
Place:
protocol PlaceDelegate: class
{
func placeUpdated()
}
class Place {
weak var delegate: PlaceDelegate?
var propertyThatCanBeUpdate: String {
didSet {
//Checking if the newValue == oldValue
delegate.placeUpdated()
}
}
MapMarker
protocol MapMarkerDelegate: class
{
markerShouldReDraw(mapMarker: MapMarker)
}
class MapMarker: PlaceDelegate {
var place: Place!
weak var delegate: MapMarkerDelegate?
init(place: Place) {
self.place = place
place.delegate = place
}
func placeUpdate()
{
delegate.markerShouldReDraw(self)
}
}
MapViewController
class MapViewController {
//I could easily set the marker.delegate = self when adding the markers
func markerShouldReDraw(mapMarker: MapMarker)
functionForRedrawingMarker()
}
This feels a bit ugly, and a bit weird that the MapMarker is just passing the "my place has been updated" information forward. Is this acceptable as far as performance goes? Should I use some kind of NSNotification instead? Should I make the MapViewController the delegate of place and search my array of mapMarker for the one holding the correct place?
A WWDC 2015 session video describes the idea of Protocol-Oriented Programming, and I want to adopt this technique in my future apps. I've been playing around with Swift 2.0 for the last couple of days in order to understand this new approach, and am stuck at trying to make it work with the Delegate Pattern.
I have two protocols that define the basic structure of the interesting part of my project (the example code is nonsense but describes the problem):
1) A delegation protocol that makes accessible some information, similar to UITableViewController's dataSource protocol:
protocol ValueProvider {
var value: Int { get }
}
2) An interface protocol of the entity that does something with the information from above (here's where the idea of a "Protocol-First" approach comes into play):
protocol DataProcessor {
var provider: ValueProvider { get }
func process() -> Int
}
Regarding the actual implementation of the data processor, I can now choose between enums, structs, and classes. There are several different abstraction levels of how I want to process the information, therefore classes appear to fit best (however I don't want to make this an ultimate decision, as it might change in future use cases). I can define a base processor class, on top of which I can build several case-specific processors (not possible with structs and enums):
class BaseDataProcessor: DataProcessor {
let provider: ValueProvider
init(provider: ValueProvider) {
self.provider = provider
}
func process() -> Int {
return provider.value + 100
}
}
class SpecificDataProcessor: BaseDataProcessor {
override func process() -> Int {
return super.process() + 200
}
}
Up to here everything works like a charm. However, in reality the specific data processors are tightly bound to the values that are processed (as opposed to the base processor, for which this is not true), such that I want to integrate the ValueProvider directly into the subclass (for comparison: often, UITableViewControllers are their own dataSource and delegate).
First I thought of adding a protocol extension with a default implementation:
extension DataProcessor where Self: ValueProvider {
var provider: ValueProvider { return self }
}
This would probably work if I did not have the BaseDataProcessor class that I don't want to make value-bound. However, subclasses that inherit from BaseDataProcessor and adopt ValueProvider seem to override that implementation internally, so this is not an option.
I continued experimenting and ended up with this:
class BaseDataProcessor: DataProcessor {
// Yes, that's ugly, but I need this 'var' construct so I can override it later
private var _provider: ValueProvider!
var provider: ValueProvider { return _provider }
func process() -> Int {
return provider.value + 10
}
}
class SpecificDataProcessor: BaseDataProcessor, ValueProvider {
let value = 1234
override var provider: ValueProvider { return self }
override func process() -> Int {
return super.process() + 100
}
}
Which compiles and at first glance appears to do what I want. However, this is not a solution as it produces a reference cycle, which can be seen in a Swift playground:
weak var p: SpecificDataProcessor!
autoreleasepool {
p = SpecificDataProcessor()
p.process()
}
p // <-- not nil, hence reference cycle!
Another option might be to add class constraints to the protocol definitions. However, this would break the POP approach as I understand it.
Concluding, I think my question boils down to the following: How do you make Protocol Oriented Programming and the Delegate Pattern work together without restricting yourself to class constraints during protocol design?
It turns out that using autoreleasepool in Playgrounds is not suited to proof reference cycles. In fact, there is no reference cycle in the code, as can be seen when the code is run as a CommandLine app. The question still stands whether this is the best approach. It works but looks slightly hacky.
Also, I'm not too happy with the initialization of BaseDataProcessors and SpecificDataProcessors. BaseDataProcessors should not know any implementation detail of the sub classes w.r.t. valueProvider, and subclasses should be discreet about themselves being the valueProvider.
For now, I have solved the initialization problem as follows:
class BaseDataProcessor: DataProcessor {
private var provider_: ValueProvider! // Not great but necessary for the 'var' construct
var provider: ValueProvider { return provider_ }
init(provider: ValueProvider!) {
provider_ = provider
}
func process() -> Int {
return provider.value + 10
}
}
class SpecificDataProcessor: BaseDataProcessor, ValueProvider {
override var provider: ValueProvider { return self } // provider_ is not needed any longer
// Hide the init method that takes a ValueProvider
private init(_: ValueProvider!) {
super.init(provider: nil)
}
// Provide a clean init method
init() {
super.init(provider: nil)
// I cannot set provider_ = self, because provider_ is strong. Can't make it weak either
// because in BaseDataProcessor it's not clear whether it is of reference or value type
}
let value = 1234
}
If you have a better idea, please let me know :)