Two classes, callback and unit testing - ios

I have one class with static methods : this class wraps calls to the Twitter API
In a second class, I have some business logic.
Due to the asynchronousness behaviour of some methods in the wrapper class, I have difficulties to design the communication. Here is what I've done :
APIManager.swift
public class APIManager {
class func getPermission(callback : () -> Void) {
let accountStore = ACAccountStore()
let accountType =
ACAccountStore().accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
let callbackRequestAccess = { (granted: Bool, error: NSError!) -> Void in
...
if(granted) {
callback()
}
}
accountStore.requestAccessToAccountsWithType(setAccountType,
options: nil, completion: callbackRequestAccess)
}
}
Welcome.swift
public class Welcome {
public func checkPermission() {
APIManager.getPermission(getTweet)
}
public func getTweet() {
...
}
}
I am not sure that this design in right or not.
I don't want to have a strong link between those classes, that's why I am using a callback.
Is this a classic design ?
Moreover, I don't feel like this behaviour will be easy to test ?

You will greatly improve testability by not using class methods here. Create a TwitterConnection protocol. Create a SystemTwitterConnection that conforms to it and manages things through ACAccountStore. Create a TestTwitterConnection that returns pre-set responses that you can configure for testing. You could even create a KeychainTwitterConnection to manage Twitter logins by hand without using ACAccountStore, or some other implementation if Apple comes out with yet another way to store these accounts.
Pass the appropriate connection to Welcome when it is created.
If the TwitterConnection protocol gets large, you should strongly consider splitting it up into smaller protocols, such as TwitterAuthenticator and TweetFetcher that handle fewer things (even if a single type actually implements all of those protocols). This can make testing much easier by allowing your test types to implement just a few functions rather than dozens.
The use of closures is probably fine, but you should stick more closely to Cocoa naming conventions. What you're calling a callback is traditionally called completion. I'd also follow Cocoa's lead on how to name methods. Rather than getPermission(), it would be requestAccessWithCompletionHandler(). This would help the caller understand that it has very similar behavior to requestAccessToAccountsWithType(options:completion:). Don't built a new vocabulary for the caller.

https://en.wikipedia.org/wiki/Observer_pattern
It will help you to decouple event publisher (Observable) and consumer (Observer).
Also you can have a special Observable implementation
which doesn't connect to anywhere but notify the observers with static content.
So you directly call notifyObservers method, for testing the behavior of Observers.

Related

How to replicate an abstract Fragment in Kotlin to View Controllers in Swift

I am working on implementing an iOS version of an existing Kotlin Android app. The specific feature that I am reproducing is a stepped wizard workflow.
How I Did it in Android
In Android, the library that I used had the following process:
Add a "stepper" view to a root activity, and provide a StepAdapter to this view
The StepAdapter controls the number of steps, and returns each step on request by index.
Each step is a Fragment implementing a Step interface that provides hooks for validation and transitioning between steps.
I ended up creating an abstract Fragment type that provides default implementations for the Step methods:
abstract class StepFragment(private val index: Int) : Fragment(), Step {
...overriding some methods from Fragment
...implementing methods from Step
}
Each step's Fragment inherits this class, passing a hard coded index into StepFragment's constructor. The steps may override some of the methods from StepFragment, and some of them call the superclass's implementation as well (I use the #CallSuper annotation to facilitate this). The StepAdapter instantiates and returns each one of these fragments.
How I'm Trying to Do it in iOS
Back in the iOS/Swift world, I found a similar library, but all it provides is the view for the progress bar. It does not handle instantiating and displaying the content of each step like the Android one does. I need to handle that myself.
You can, however, provide a delegate to the stepper that allows you to hook into the transitions (willSelectIndex, didSelectIndex, canSelectIndex, etc.). I made the root ViewController the delegate for the stepper. This ViewController has the progress bar view at the top, and a container for each step beneath the progress bar. Each step's ViewController is embedded into a corresponding container. To control transitions between steps, I simply show and hide these container views. I have that part figured out.
What I do not have figured out is how to replicate the StepFragment class from Android Fragments into Swift ViewControllers. I have the following problems:
Swift does not have abstract classes (for some reason).
I do not instantiate the step ViewControllers; that is handled internally by the storyboard. This means that I can't provide the step index in the constructor like I can in Android. An abstract property would be the typical way to get around this, but (see above) Swift doesn't have abstract classes.
I could get around these problems in a few ways:
Instead of an abstract class, I can use a protocol. I can specify the requirement that all classes that conform to the protocol must be ViewControllers, but I cannot override methods from ViewController in the protocol (as far as I've been able to see). I can add an extension to the protocol to provide functions with default implementations, which implementors can then override, and they can even call into the original functions (using (self as Protocol).func()). However, this feels very clunky.
Instead of an abstract class, I can use a regular class. I can achieve everything that I want to here, except that I can't enforce that the subclass implements abstract members at compile time. I would need to use something like fatalError() in the base class, which only throws at runtime. This also feels clunky.
I keep hearing about the "delegate" pattern, and I think it's a nice elegant way to solve a lot of problems in a "Swifty" way, but I have no idea how I would use that here. I think I would prefer being able to do it this way over the above two.
TL;DR
To sum up my problem, I am looking for a way for multiple "step" child ViewControllers to hook into a wizard workflow controlled by a parent ViewController. They should be able to perform some (potentially async) logic on step selection, before transitions, and even block transitions. I must be able to optionally ignore some of these hooks, which should then use a default implementation.
I discovered that you actually can provide default implementations for protocol functions, so this is the solution I came to:
protocol StepViewController: UIViewController {
var stepIndex: Int { get }
func onBackClicked(_ goToPreviousStep: () -> Void)
...
}
extension StepViewController {
// this is a default implementation, so implementors don't have to provide it
func onBackClicked(_ goToPreviousStep: () -> Void) {
goToPreviousStep()
}
...
}
class StepOneViewController: UIViewController, StepViewController {
let stepIndex: Int = 0
func onBackClicked(_ goToPreviousStep: () -> Void) {
// if I want to call the default implementation I can do this:
(self as StepViewController).onBackClicked(goToPreviousStep)
}
}

SwiftUI and MVVM design pattern

 
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.

In Unit Tests how can I programmatically dismiss system permission dialog?

I have an unit test which calls methods on CNContactStore() e.g. CNContactStore().execute(saveRequest). So the permission dialog for contacts pops up, like the Push notifications alert but the contacts permission dialog doesn't get dismissed automatically. I know how to do this in UI tests with addUIInterruptionMonitor() but have no idea how to do this in unit test.
I would create a wrapper around CNContactStore and then use a mock when testing.
You're not really interested in testing CNContactStore, you are interested in testing that your code interacts with CNContactStore properly right?
Setup
I would start out creating protocols and classes to extract the contact stuff out of your "normal" code base.
First a Contact struct to hold the properties you need later to create an actual CNContact
struct Contact {
//holds whichever properties you need to create a CNContact
}
Then a protocol to hold the methods you would like to execute. This could be done with a protocol with a lot of methods like so
protocol ContactsHolder {
func save(contact: Contact)
func add(contact: Contact)
func delete(contact: Contact)
func update(contact: Contact)
//Maybe more methods, the important thing is that you abstract yourself away from CNContactStore and other Contact kit classes
}
Or you could create an enum holding the possible options like so
enum ContactsUpdateMethod {
case save(Contact)
case add(Contact)
case delete(Contact)
case update(Contact)
}
protocol ContactsHolder {
func execute(_ method: ContactsUpdateMethod)
}
In Your "Real" Code
With that in place, you are ready to create your actual ContactsHolder, which then internally uses CNContactStore and everything related to that framework.
So for instance (if you chose the version with a "pure" save function)
class CNContactsHolder: ContactsHolder {
func save(contact: Contact) {
//1. create a `CNContact` from your `Contact`
//2. create a saveRequest
//3. execute: CNContactStore().execute(saveRequest)
}
....
}
And then you give the class(es) who needs to work with CNContactStore a reference to your new ContactsHolder protocol
So in your class you have
let contactsHolder: ContactsHolder
And then you can either pass it in, in your init method
init(contactsHolder: ContactsHolder = CNContactsHolder()) {
self.contactsHolder = contactsHolder
}
Or you can declare it as a var and then give it a default value
So instead of:
let contactsHolder: ContactsHolder
You say:
var contactsHolder: ContactsHolder = CNContactsHolder()
The important thing is that you can change the ContactsHolder from being a "real" CNContactsHolder into a mock when you need to test
In Your Test Code
To test this, you create a mock:
struct MockContactsHolder: ContactsHolder {
var saveWasCalled = false
func save(contact: Contact) {
saveWasCalled = true
}
}
And then you use that in your class instead of the CNContactsHolder
Now you should be able to test your own code, without getting interrupted with permissions and stuff that is not relevant to your code, but is a consequence of using CNContactStore.
Disclaimer :)
I haven't run the above by a compiler, so there may be typos.
Also, there might be bits and pieces missing to make it fit to CNContact (callbacks and so on), but I hope you get the idea about how to split things apart.
And finally...it may seem like a lot of work, but I think it makes sense to get the "framework specific" code out into a separate helper class, hid behind a protocol, so that you can swap it out whenever you need to do testing for instance, or...if you decide to get rid of CNContact at a later point and use a different frameworks.
Hope it helps.
I think you're confusing Unit Testing with UI Testing. In Unit Testing, you just want to test, your codes (e.g. functions and properties) and with that, you'll most probably need to have "mock-up".
For instance, you want to test your login button selector that has a network calls after validation of the input fields.
The following should be the steps:
Test your validation logic. Both failing and succeeding cases.
Test the code inside the completion block of your API call, BUT not using the REAL API data. Instead, use your mocked API here.
and so on...
Now, back to your question, you don't need to handle that uncontrollable and "un-dismissable" alert controller generated by the system. Instead, what you wanna do is to "mock" (ughh not again) that pop-up event by hitting the delegate function for that access-contacts alert by the system, "mock" a response namely "Don't Allow" and "OK". What do you expect to happen when user taps on the first button? The second button? Set expectations/assert.
That's it. Hit every function you need to hit to increase the coverage of your code. Let me know if this helps.

How to hide an inherited method in Swift

I have a Child class that contains methods that I define and methods inherited from its Parent class. I want some of the methods from Parent to be unavailable to the user or at least generate a compile error/warning when used. Example:
class Parent {
public func secretMethod() { // Don't want anyone to use
}
}
class Child: Parent {
public func overtMethod() { // Fine with people using
}
}
Child.init().overtMethod() // Fine
Child.init().secretMethod() // Not Fine. Should not be viewable/useable/accessible
I cannot change the parent class. How I long to be able to set secretMethod to private. Swift doesn't allow restricting the access level when overriding functions, so I can't set secretMethod to private in the Child class either.
So far I have been using #available to mark the method with a compile warning and message, but I am hoping that there is a better way? I considered overriding and throwing an error, but that can't be done if the original method isn't marked throws.
Thank you.
Edit: I also cannot override the secretMethod to make it unavailable. The Child class needs to access it.
Rethink your design.
I think you may be only considering the "user" (another developer? .. you are writing a library, I guess?) and not existing source. The basic idea of subclassing is that the subclass will be able to be used anywhere the parent is used.
class A: UIView {
func availableMethod() {
}
// func layoutSubviews() ----- let's say you want to hide this method
}
The problem arises here from you not knowing what any other internal classes may be doing with the layoutSubviews and if you somehow block it on an instance of A, then anything expecting to be able to use that instance as though it is an instance of UIView will now fail.
Don't use inheritance if you don't want to expose public methods of the parent class. You can hide the 'parent' class as private instance in your 'child' class and only forward the methods you want to expose.
If you are relying on inheritance of your child class to your parent, because of some APIs which expect the parent class, then you also cannot make any parent methods private. This would break the contract between the API using the parent class, if you pass a child class, which hides formerly public parent methods. That won't work.
Look, what you're looking for is protected access modifier which would allow you to have methods and variables visible within its descendants.
But, in Swift there isn't any. The main access modifiers are private or internal.
Somewhere between them is fileprivate. It allows you to have visible methods and variables within one file. Even if this can be solution for you, it may not be right design pattern.
If you're writing library and you don't want to allow other programmers to call methods from parent but you want to allow them to see subclasses' methods, you can override internal function from parent to public or open function in subclass
I would like to enhance on the answer of #nikwest. You should try to use composition instead of inheritance. So Parent and Child don't need to share any code at all but some methods are available on both. You could also create a common ancestor so a certain var will always exist.
class Parent: Overt {
}
class Child: Overt, Secret {
}
protocol Overt {
func overtMethod()
}
protocol Secret {
func secretMethod()
}
extension Overt {
public func overtMethod() { // stuff }
}
extension Secret {
public func secretMethod() { // stuff }
}
A variation on this when you have a common var to share or something (like UIViewControllers using the composition pattern) could use a CommonParent that has the var and then Child1 and Child2 would add the protocols they need to come to the required functionality. If you don't use the default implementation in the extension you can still override.

Swift, how to declare methods requiring instance members while following MVC

I'm trying to use the MVC in an app loading a url into a webView. I'm struggling with how to/whether to define the back, forward, reload, etc... functions in the model or the viewController. I'm pretty sure they belong in the model, but then how do I call them in the IBAction for the corresponding button?
In trying to call the class function in the IBAction, first I have to create an instance of WebViewLoadRequest in each IBAction which seems extraneous. I can't (and probably shouldn't) create a global instance of WebViewLoadRequest because self isn't available in the property initializer to reference the UIWebView Outlet
class WebViewLoadRequest {
var outlet: UIWebView
var url : String
private var address: URL
init(outlet: UIWebView, url: String) {
self.outlet = outlet
self.url = url
self.address = URL(string: url)!
}
func load() {
self.outlet.loadRequest(URLRequest(url:address))
}
func back() {
if outlet.canGoBack {
outlet.goBack()
}
}
func forward() {
if outlet.canGoForward {
outlet.goForward()
}
}
func refresh() {
outlet.reload()
}
}
To simplify:
How can I write the following function in the model layer and implement it in the ViewController?
//outlet refers to a UIWebView
func back() {
if outlet.canGoBack {
outlet.goBack()
}
}
Or should this strictly be a function of the view controller? I realize essentially just the view is being changed, but there's a lot going on behind the scenes in the goBack operation that I'm not sure belongs in the ViewController
You are confusing two things here IMO, there is object oriented programming which you described in your question. There is also another concept which is commonly used and also very common in Swift, this concept is MVC. Model, View, Controller. This is basically a seperation of powers. In practice this comes down to:
Model - custom class with all the logic, in your case the WebViewLoadRequest
View - defined in a 'storyboard'
Controller - Will be a subclass of UIViewController, this subclass also has a reference to your model, all the IBActions and IBOutlets to connect to and update your UI.
You can learn more about MVC here:
https://www.raywenderlich.com/132662/mvc-in-ios-a-modern-approach
Also I would strongly recommend watching the C193p course from Standford by Paul Hegarty, this teaches you all there is to know. For example the 4th week is about MVC
https://itunes.apple.com/us/course/developing-ios-10-apps-with-swift/id1198467120
EDIT:
Basically your construction is a construction of delegation. The normal way to solve this issue is by creating a delegate property on your model-class, the delegate implements a certain protocol with for example a 'canIGoBack'-function. The model can request extra data from the delegate by calling that delegate function. Apple has something about delegation in their swift manual (check the 'Delegation' part:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
I believe Paul Hegarty also discussed it.
However, in this case it is also fine to do the canGoBack in the viewcontroller and conditionally call your model. MVC is only a guideline, there are many reasons to sometimes do logic in a viewcontroller, the biggest reason is probably if it makes shit easier. Implementing delegation only for a canGoBack is most of the times just silly.

Resources