I'm new in Swift and even in object oriented programming languages itself. So my question is, how to use this very extensive language Swift the right way? I give an example to verify my problem:
Let's say I have got two classes:
Class ScanForBluetoth{} //Handles all parts to scan for BT devices
class ScanForDevices: UIViewController, CBCentralManagerDelegate , CBPeripheralDelegate, UITableViewDelegate,UITableViewDataSource{}
Class Bluetooth{} //Handles only the Bluetooth parts with it's delegates
class Bluetooth: ScanForDevices{}
Now, I would like to implement all my used delegates and other Bluetooth specific functions into the Bluetooth class. BUT I need some objects (for example of the CBCentralManagerDelegate) in my ScanForDevices class, too. So, I have to implement all my delegates in my "mother" class ScanForDevices although I only need some properties. SO if I implement the delegates, I have to be conform with the protocol and must implement ALL my needed delegate functions... At the end I have implemented all my delegate functions in ScanForDevices and then override them in Bluetooth. But I don't think that my way is the best way to realize this problem...
Thanks for reading!
Firstly, I would like to point out that your naming conventions are really off. In object oriented programming, you want your class names to be objects (nouns). You named your classes by what they were doing, rather than what they are. A better name choice for your classes would be something like BluetoothDeviceScanner, rather than scan for devices, and BluetoothManager rather than the non-explicit "bluetooth".
Secondly, what you have done is subclassed the bluetooth class to scan for devices class, which causes it to inherit all the functionality of its class. This really doesn't make any sense. Subclassing is used to create an object based on a parent object, while these two objects handle two totally different things, and then you're planning on overriding the functions anyway. Instead of that, you should just include the protocols that you need in the bluetooth class separately. Keep the functionality of the two classes separated as much as possible.
Thirdly, you should separate your view controller functionality from the scanning functionality. What I mean is the "ScanForDevices" object's job is to scan for devices, so it shouldn't also have the job of controlling a view... I would remove the UIViewController protocol and introduce a new view controller class, and within that class you can have a property that is assigned the "ScanForDevices" object, at which point the devices can be scanned for within the viewcontroller, but the scanning functionality is contained within a single object (which is best practice).
EDIT
All you need to do to "connect" the data is have your BluetoothManager and BluetoothScanner objects is have them available as a property within whatever view controller you need them. So, in the viewcontroller declare some properties, I usually do it with optionals so that I don't have to worry about initializing the properties (This means you need to unwrap the variables before using them).
In your ViewController...
var bluetoothScanner: BluetoothScanner?
var bluetoothManager: BluetoothManager?
override func viewDidLoad() {
super.viewDidLoad()
bluetoothScanner = BluetoothScanner(init parameters)
bluetoothManager = BluetoothManager(init parameters)
}
You're objects are now "connected" in the sense that you have access to them and all their properties/methods in the viewcontroller. Now that I think about it, you don't even need to have both objects on this level. You can store the BluetoothScanner as a property of the Bluetooth manager, at which point you would only need to use a BluetoothManager object to handle all your bluetooth needs on the view controller level.
Init Methods
//init method that takes 2 parameters, a string and a uiviewcontroller.
init(param1: String, param2: UIViewController) {
//Struct init code using parameters
self.name = param1
self.viewController = param2
}
//init method that takes no parameters, but still initializes the same properties.
init() {
self.name = "YungGun"
self.viewController = UIViewController()
}
Keep in mind these initialization methods are made up and have nothing to do with your problem at hand, I was attempting to illustrate that this is where you define the parameters needed to initialize the struct. The same parameters in the parenthesis must be passed when creating an instance of the struct.
Related
I am trying to get my head round how i can achive the following using the MVVM design pattern with SwiftUI.
I want to have only 1 instance of a networking operation queue (using OperationQueue) where any view model that needs to send any networking requests but i have heard that creating a Singleton is not preferred and i should be passing the networking queue object around where it is needed.
So if i create the instance of the network operation queue in the Scene Delegate and pass them into the ContentView initialiser and store it in an object there to then pass into the views then created.
This doesnt seem like good MVVM design practice as from what i understand the View should Own the ViewModel only?
What is the best way of achieving this?
Edit: thought a bit more about this and I can pass it into the view via its constructor and then within the constructor I can create the view model and pass it straight through so the view doesn’t own anything.
But I still will require a singleton so how can I pass the singleton as a dependency injection rather than using it globally?
Thanks
We shouldn’t create singletons for the single reason of being an easy way to get global variables, but it doesn’t mean we should never use them.
In your case, if I understood correctly, you are basically creating a service that can be used by the entire application. You could either A) create a reusable class with the networking functions you need (and instantiate anywhere you need it) or B) create a class with a singleton instance in it, that can be easily accessed anywhere.
A singleton would be a better choice if you need to keep some state common to all callers, or if you need to maintain a waiting queue, for example.
Option A
class NetworkService {
init() {
// init
}
// Your properties and methods
func someFunction() {}
}
Usage in a ViewModel:
let networkService = NetworkService()
networkService.someFunction()
Option B
class NetworkService {
static let shared = NetworkService()
private let queue : Any?
// Your properties and methods
func someFunction() {}
}
Usage:
NetworkService.shared.someFunction()
Either way, this is still MVVM. The data is not related to any specific view, nor to a specific model; it's simply a service you would call in any ViewModel that needs it.
For our iOS programming class we must make a framework for Swift iOS. We had the idea of a framework simplifying CoreData manipulation. I began by creating a class where you put the NSManagedObjectContext created in AppDelegate at the beginning, so you don't have to write this long (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext anymore.
open class SimpleCoreData {
var context: NSManagedObjectContext
init(context: NSManagedObjectContext) {
self.context = context
}
func delete(entity: NSManagedObject) /*-> Bool*/ {
// some code
}
func getAll(entityClass: NSManagedObject.Type) throws -> [NSManagedObject]? {
// some code
}
func create(entityDescr: NSManagedObject.Type) -> NSManagedObject? {
// some code
}
But I would like it to be accessible from everywhere in the application, and this simplification would be useless if you have to instantiate this each time.
I was first thinking about a singleton, but I recently learned it wasn't a good practice.
So do you know any solution to make this accessible from everywhere in the client app? Or maybe singleton is okay in this case?
Keeping Rob Napier's excellent comments in mind, if you decide to avoid a singleton in this case, a common approach would be
Create an instance of your SimpleCoreData class in the app delegate when the app launches.
Have the app delegate pass this to your initial view controller. That view controller would have a SimpleCoreData property but would not create the instance-- it would expect one to be assigned by whichever code creates it, which here is the app delegate.
Repeat this pattern everywhere you need a SimpleCoreData. That is, when you create an object that needs a SimpleCoreData, make sure it has a property with that type, and assign a value when you create it. For view controllers, a good place to do this is in prepare(for:sender:), if you're using segues.
It's not necessary to create the SimpleCoreData in the app delegate, though. You could create it at the first point in the app hierarchy where it's needed, and pass it along from there. So if it's only needed in the second view controller in the hierarchy and in other objects loaded from there, create it in that view controller.
This doesn't make your SimpleCoreData instance available everywhere automatically, it means that you're creating one and then passing it around. Often that works fine, but as Rob notes it's not always the best approach. It can lead to passing an object along to an object that doesn't need it, because some other object that gets created later on does. For example if you need SimpleCoreData in your initial view controller but then not again until five levels down the hierarchy, you still need to pass it along every step of the way. That's an example of when a shared instance can be useful. It's not a singleton since other instances are allowed, but it's a default instance that can be used as needed.
I finally learned thanks to you that singletons aren't so evil, they can be used in some case, including this one, and it seemed in my case that it was a good choice. Maybe I will change it for a shared instance pattern.
So the singleton works well. Thank you everybody for your advices, I learned a lot in design patterns.
Im trying to understand the high level implementation of protocols without delegates in Apple frameworks. When a subClass conforms to and implements a protocol method, how is that method called? Lets consider the NSCoder protocol methods (encodeWithCoder: and initWithCoder:) for instance.
Without delegates, could you provide any uses cases for protocols (other than achieving polymorphism? I see that some methods could be abstracted away from base classes and grouped into an interfaces but without any implementation (as mixins for instance), what is the significant use?
First, protocol methods are not special in any way. They, like every other Objective-C method, gets called by a message sent to an object. There's nothing special about that part of things. Protocols are basically just a hint to the compiler, though you can query whether an object conforms to one at runtime and make decisions based on that.
You can verify this by implementing a protocol method (or the entire protocol) without declaring that fact in a classes' interface, and call the function on an instance of that object after casting it to be id<YourProtocol>, and it will work.
You can (and sometimes should) call NSCoding methods yourself -- you may decide that you want to persist objects to the disk, and that this is the best way to do it.
NSCoding is actually a great example of why protocols are still useful even though they do not provide any implementation -- the implementation of initWithCoder: and encodeWithCoder: will be different for every class that implements them -- there is no sense in providing an implementation.
Building on that, consider the datasource property of a UICollectionView; as there is no multiple inheritance in Objective-C, it would be undesirable for the datasource to be a class itself, as that would prevent you from using a UIViewController as the data source, and force you to make a whole new class for that express purpose.
Protocols can also be used to implement multiple inheritance in a type safe way without redeclaring the interface of the giver in the inheritor. If the entire interface of the class being inherited from is a protocol, then the inheritor can simply conform to that protocol as well.
Objective-C does provide mixins in the form of Categories, which can implement protocols on existing classes.
For a full throated defense of protocols (in Swift), see the Protocol-Oriented Programming WWWDC 2015 talk.
Taking the example of the NSCoding Protocol, the two required methods in the protocol, basically implement the steps an object should perform to encode itself to be archived. It also implements the initWithCoder to recreate the object from the archive.
Lets say you create a custom object, only your object knows which properties it needs to archive.
When you call a method to archive your custom object, the method call ultimately flow to your encodeWithCoder or initWithCoder to take action specific to your class.
***** Updated ****
Looking at this with an example :
Lets say our data structure looks like this
someArray = [String,CustomObject,aDictionary]
When we want to archive someArray, we call the archiveRootObject method on it. Now inorder for someArray to archive itself, it needs all its contained items to inturn archive themselves. The Array simply instructs the sub items to archiver themselves calling the encodeWithCoder method on them.
By adopting and conforming to the NSCoding protocol, you are just confirming to the root array that Yes, I know how to archive and unarchive myself.
Hope this helps.
I've got a test project to use the private data object on several view controller.
(I've downloaded it from web & git-hub)
- (ExampleAppDataObject*) theAppDataObject;
{
id<AppDelegateProtocol> theDelegate = (id<AppDelegateProtocol>) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
return theDataObject;
}
First question is, theDelegate was casted with AppDelegateProtocol, even this applications UIApplication delegate name was ViewControllerDataSharingAppDelegate, and there's no warning. I can't under stand why, maybe it's because that was a id type?
(AppDelegateProtocol is a custom delegate protocol he declared in the AppDelegate.)
Second, it shows this kind of code on every view controller, and it seems like just a single-ton pattern.
I don't think this is not the best way to transfer data between view controller.
Which is the best way to transfer object data type?
Thanks.
Creating a protocol decouples the code somewhat from the specific implementation. You could conceivably have several applications, each of which uses its own custom class as an app delegate, but all implementations conform to the AppDelegateProtocol.
I used to use the app delegate to hold global data and methods a lot when I first started in iOS.
However, that fills your app delegate with app-specific code.
I've shifted away from that approach recently, and use a data container singleton (and perhaps a utility methods singleton as well.) As is typical for a singleton, I define a class method that lets me fetch the singleton. I add properties to my singleton as needed to store data, and then just use the class method to get a pointer to the singleton. I write my class method to lazy load the singleton.
Its also easy to make your data container singleton persistent by making it conform to NSCoding. Then every time you get moved to the background, just save your singleton somewhere. On app launch, read it in.
I understand what a delegate does in iOS, and I've looked at sample code, but I'm just wondering about the advantages of this type of encapsulation (as opposed to including delegate methods in the primary object).
The advantage of the delegate design pattern is loose coupling. It enables class A (the delegate) to depend on class B (the delegating class) without class B having to have any knowledge of class A. This ensures that the dependency relationship is one-way only, rather than being circular.
It also forms the foundation (lower case "f") of Apple's frameworks because it allows them to invoke your code as appropriate when functionality specific to your application is required. For example, responding to a button tap or telling a table view how many sections there should be.
Delegation is a design pattern not only used in iOS but many other languages. It enables you to hand values and messages over in your class hierarchy.
In iOS, delegation requires the "delegate" class to implement a protocol which contain methods that the "delegating" knows about. Still following?
The delegating class's implementation will call these protocol methods, but the delegate class will implement these methods in their class.
This keeps your Classes clean.
In reality, you don't really need delegation if you can add new methods to a single class. But for UIKIT's UIView class, Apple will not allow you to add new implementations to their class.
correct me if I'm wrong.
The most common use of a delegate in iOS is to establish communication within modules that are unrelated or partially related to each other. For example, passing data forward in a UINavigationController is very easy, we can just use segue. However, sending data backwards is little tricky. In this case, we can use delegate to send the data backward.
Let's call, the class, associated with the first Controller ClassA and the class, associated with the second Controller ClassB. The first Controller is connected to the second controller with a forward segue. We can pass data from ClassA to ClassB through this segue. Now, we need to pass some data to ClassA from ClassB for which we can use delegates.
The sender class(ClassB) needs to have a protocol in its header file(.h) and also a reference of it as delegate inside the block, #interface ClassB .... #end. This reference let's the ClassB know that it has a delegate. Any class that wants to use this ClassB will have to implement all of this protocol's required methods(if any). So, the receiver class,ClassA will implement the method but the call will be made by the sender class, ClassB.
This way, receiver class doesn't need to worry about the sender class' internal structure, and can receive the required information.
Delegation as I understand it is when an object will pass the responsibility of handeling an event to another object thus "delegating" the responsibility to that object.
For example if you have an NSButton in iOs you generally assign the Delegate to be the parent view controller. This means instead of handeling touchUp events in the definition of the button it is instead handled in the view controller.
The main advantage of delegation over simply implementing methods in the "primary object" (by which I assume you mean the object doing the delegating) is that delegation takes advantage of dynamic binding. At compile time, the class of the delegate object does not need to be known. For example, you might have a class that delegates the windowDidMove: method. In this class, you'd probably see some bit of code like
if([[self delegate] respondsToSelector:#selector(windowDidMove:)]) {
[[self delegate] windowDidMove:notification];
}
Here, the delegating class is checking at runtime whether its delegate responds to the given method selector. This illustrates a powerful concept: the delegating class doesn't need to know anything about the delegate other than whether it responds to certain methods. This is a powerful form of encapsulation, and it is arguably more flexible than the superclass-subclass relationship, since the delegator and the delegate are so loosely coupled. It is also preferable to simply implementing methods in the "primary object" (delegating object), since it allows runtime alteration of the method's implementation. It's also arguable that this dynamic runtime makes code inherently more dangerous.
Delegate is an important design pattern for iOS app.All apps directly or behind the hood use this delegate pattern.
Delegate design pattern allows an object to act on behalf of another.
If we are working with tableview then there are "tableViewDelegate" and "tableViewDataSource". But what this means
Suppose you have a tableview.
now some major concern for this.
1.what is the datasource(the data that will appear in table view) for this tableview?
2.How many row for table view etc.
delegate design pattern solve these question using another object as the provider or the solver of these question.
An object mark himself to the table view and ensure the table view that "Yes i am the man who can assist you" by marking himself as the delegate to the table view .Thanks
The class marked as delegate takes the responsibilities to handle the callbacks sent while some event occurs. For example, in case of UITextField, there are some methods called when some events occurs like editing started, editing ended, character typed etc. These methods will already be defined in the protocol. We will have to assign delegate for that i.e. which class is going to handle these events.
With the help of a delegate, two-way communication can be achieved. A delegate might be used to make an object reusable, to provide a flexible way to send messages, or to implement customization.
In iOS ecosystem especially UIKit Framework which consists of UIApplication, UITableView, UICollectionView, UITextfield & so on uses delegate & datasource design pattern intensively to communicate data to and fro.
Delegate design pattern is used to pass/communicate data from FirstVC(Delegator) to SecondVC(Delegate) to complete a task.
Here, SecondVC(Delegate) conforms to a protocol delegate & implements all its requirements like methods by providing body to complete that task given by FirstVC(Delegator).
Also, FirstVC(Delegator) object will be having a optional property of protocol delegate type i.e delegate which must be assigned by SecondVC(Delegate).
Now, FirstVC(Delegator) can call that method residing in SecondVC(Delegate) by passing data from its delegate property.
EX: CEO(FirstVC) which passes data i.e "confidential data" to Secretary(SecondVC) to do further processes using that data.
Datasource design pattern is part of Delegate pattern which is used to pass/communicate data from SecondVC(Delegate) to FirstVC(Delegator) when a task is assigned to SecondVC(Delegate).
Here, SecondVC(Delegate) conforms to a protocol datasource & implements all its requirements like methods with return type by providing body to talk back to FirstVC(Delegator) after the task is given by FirstVC(Delegator).
Also, FirstVC(Delegator) object will be having an optional property of protocol dataSource type i.e dataSource which must be assigned by SecondVC(Delegate).
Now, FirstVC(Delegator) can call that method with a return type residing in SecondVC(Delegate) by passing data from its dataSource property.
EX: Secretary(SecondVC) replies back with a data i.e "Sir, I am already having too much work to do. Please, can you assign that data to others" to CEO(FirstVC). Now, CEO(FirstVC) will analyse that data to do further processes.
Delegation means one object passes behaviour to another object..