swift unit test if a function was called - swift

I am still learning swift and so this might be a very very basic question.
I have this function in my view controller -
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
I am trying to test if the fetchData function is called, when the viewDidLoad is called. In Objective C, I used to be able to use OCMock and expect if that method was called.
Would anyone be able to help me with how I can do test this in swift?

Related

Swift OSX- View Loading Late (viewDidLoad) (applicationDidFinishLaunching)

Thanks for the help!
Whenever I enter any code after viewDidLoad or applicationDidFinishLaunching, my view is delayed until after that code has finished. Also tried viewDidAppear.
*Not Using SwiftUI
*Running Big Sur Xcode 13.2.1
Let's say I've entered
override func viewDidLoad() {
super.viewDidLoad()
sleep(5) }
The view will load after the sleep... I know sleep isn't a great example, but I've tried it with many functions.
Also if I run any code in AppDelegate - in applicationDidFinishLaunching
Same Result.
Any Tips/ Help/ Updates are greatly appreciated!
You can use DispatchQueue to resolve that issue.
Run your code in another thread using your own queue or predetermined:
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global(qos: .utility).async {
//your code here
sleep(5)
}
}

Is an event called immediately after object initialization?

Does an event procedure like override init exist but immediately after completion?
I'm hoping for something like override init_completed()
I need to perform functionality immediately after the object is fully initialized.
You could simply call a method at the end of the init() method:
struct myObject {
init() {
// Other code
otherMethod()
}
}
If your object is a subclass of UIView and exists inside a UIViewController you can of course override the viewDidLoad() method of the view controller.
For an isolated UIVIew, either awakeFromNib() or didLayoutSubviews() will be called after the view loads. There is more information here.
Other useful information available at the Swift documentation on initialisation.

Swift Threading: When to use DispatchQueue.main.async?

I believe I understand what the dispatch queue is doing when I call it, but I'm not sure when exactly I should use it and what it's advantages are when I do use it.
If my understanding is correct, DispatchQueue.main.async { // code } will schedule the code contained within the closure to run on the main dispatch queue in an asynchronous manner. The main queue has the highest priority, and is typically reserved for updating UI to maximize App responsiveness.
Where I'm confused is: What exactly is the difference in updating UI elements within a dispatch queue closure versus just writing the code outside the closure in the same spot? Is it faster to execute the code in the body of a view did load method rather than sending it to the dispatch queue? If not, why?
Code Example:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
}
Versus:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
updateUI()
}
}
}
Which one is will update the UI faster?
The primary use of DispatchQueue.main.async is when you have code running on a background queue and you need a specific block of code to be executed on the main queue.
In your code, viewDidLoad is already running on the main queue so there is little reason to use DispatchQueue.main.async.
But isn't necessarily wrong to use it. But it does change the order of execution.
Example without:
class MyViewController: UIViewController {
func updateUI() {
print("update")
}
override func viewDidLoad() {
super.viewDidLoad()
print("before")
updateUI()
print("after")
}
}
As one might expect, the output will be:
before
update
after
Now add DispatchQueue.main.async:
class MyViewController: UIViewController {
func updateUI() {
print("update")
}
override func viewDidLoad() {
super.viewDidLoad()
print("before")
DispatchQueue.main.async {
updateUI()
}
print("after")
}
}
And the output changes:
before
after
update
This is because the async closure is queued up to run after the current runloop completes.
I just ran into the exact situation discribed in your Question: viewDidLoad() calling DispatchQueue.main.async.
In my case I was wanting to modify Storyboard defaults prior to displaying a view.
But when I ran the app, the default Storyboard items were momentarily displayed. The animated segue would finish. And only THEN would the UI components be modified via the code in viewDidLoad(). So there was this annoying flash of all of the default storyboard values before the real values were edited in.
This was because I was modifying those controls via a helper function that always first dispatched to the main thread. That dispatch was too late to modify the controls prior to their first display.
So: modify Storyboard UI in viewDidLoad() without dispatching to the Main Thread. If you're already on the main thread, do the work there. Otherwise your eventual async dispatch may be too late.

learning swift: expressions are not allowed at the top level

I'm learning Swift. I met a problem cannot be solved.
import UIKit
func helloword(str:String) {
print(str)
}
helloword("say")
I use helloword("say") but Xcode tell me the error:
expressions are not allowed at the top level
You can't simply call this method anywhere in the file. It must be called in a control flow. I mean call it inside a function.
For example, call your function from your viewDidLoad method like so :
override func viewDidLoad() {
self.helloword("say") // here self is the View Controller itself
}

Extend a generic class in swift

I have some code which has to be available on all UIViewController of application. So I created a class UIViewControllerExtension: UIViewController, which will be extended by each class which I want to use as UIViewController. Which works as expected.
Now I have new screens where I have to use UITableViewController, so I can't extend same class UIViewControllerExtension, And to keep code centralized so I do not want to create another class UITableViewControllerExtension with same code, and want to have a common solution for both cases.
I tried various ways to extend generic class <T:UIViewController> so I can use it in both cases, but it didn't work (as it wouldn't compile). I did some research on internet but didn't find any solution to it. Does someone had same issue and have a solution?
I thought if there would be some solution like
class CommonViewController<T:UIViewController>: T{ //I know it doesn't compile
//...
}
Usage:
class MyHomeScreenViewController: CommonViewController<UIViewController>{
}
class MyItemListScreenViewController: CommonViewController<UITableController>{
}
I am open to any other solution if it solves my problem.
Edit: More details
1> I would like to extend viewDidLoad() method of UIViewController and UITableViewController in common way (no duplication of code as said before)
2> I would like to add some supporting methods to UIViewController (and UITableViewController), supporting methods like navigateBack, loginUser(name:String,password:String) etc..
A solution would be to extend UIViewController to add additional functionality to all UIViewControllers and override viewDidLoad in your own classes:
extension UIViewController {
func navigateBack() {
...
}
// an extension cannot override methods
// so this method gets called later in an overridden viewDidLoad
func viewDidLoadNavigate() {
...
}
}
// you own classes
class MyHomeScreenViewController: UIViewController {
// you have to make sure that all view controllers which can navigate override viewDidLoad
override viewDidLoad() {
// optional call to super
super.viewDidLoad()
// this is needed and called from the extension
viewDidLoadNavigate()
}
}
class MyItemListScreenViewController: UITableViewController {
override viewDidLoad() {
super.viewDidLoad()
viewDidLoadNavigate()
}
}
As you can see there is some code duplication but this is necessary since UITableViewController can also override viewDidLoad.
If generic inheritance is possible some day this code duplication can be reduced.