declaring a global function across all views - ios

I have a function for eg. that I with to have across all views in my app.
How would I go about defining that. Where should the function be written.
read somewhere here that one possible solution is to define the function as a UIViewController extension like so:
extension UIViewController {
func displayAlert(title:String, error:String, buttonText: String) {
...
}
}
where should such a procedure be declared?
Thanks

Create a new Swift file and name it something like:
UIViewController+DisplayAlert.swift
In there is where you can add the code in your question.
extension UIViewController {
func displayAlert(title:String, error:String, buttonText: String) {
...
}
}
Since it is extending UIViewController, you'll be able to access this function on all subclasses of UIViewController.

Related

Is it possible to create a default implementation for 2 protocol implementations?

I want to know if it is possible to create a default implementation for 2 protocols implementations at the same time.
For example
protocol Coordinator {
var navigationController: UINavigationController
}
protocol Browsing {
func openBrowser(url: String)
}
And be able to create a default implementation like so
// This syntax is not correct of course, it is just an example
extension (Coordinator & Browsing) {
func openBrowser() {
//code
navigationController.present(...)
}
}
I want to be able to do this, because I'll have multiple classes extending both protocols
You can use the where clause on an extension to require a type conforming to multiple protocols.
Either of these will work and do the same thing. It's up to you which one makes sense. I'd probably go with the second one since the method came from Browsing and this adds the implementation when it also conforms to Coordinator.
extension Coordinator where Self: Browsing {
func openBrowser() {
//code
}
}
extension Browsing where Self: Coordinator {
func openBrowser() {
//code
}
}

How can assing generic (associated type require) protocol as delegate to any controller?

I have a protocol that have associatedtype named MessageType.
protocol MessageProtocol: class {
associatedtype MessageType
func sendMessage(_ with: MessageType)
}
Then implemented it in the controller
extension MainController: MessageProtocol{
typealias MessageType = String
func sendMessage(_ with: MessageType) {
// sending message
}
}
My purpose is using the protocol as delegate in other controller like below.
final class AnotherController {
weak var messagerDelegate: MessageProtocol?
...
}
But I get error of that
Protocol 'MessageProtocol' can only be used as a generic constraint
because it has Self or associated type requirements
Is there any way to handle this error?
I've reading Big Nerd Ranch blog post about this situation.
https://www.bignerdranch.com/blog/why-associated-type-requirements-become-generic-constraints/
I've learned about the situation but no idea about how it can be achived?
Thanks,
I handle the situation like that.
final class AnotherController<T: MessageProtocol> where T.MessageType == String {
weak var messagerDelegate: T?
...
}
And if I want to create anotherController instance programmatically, I created like that.
let instance = AnotherController<MainController>(frame: CGRect.zero)
instance.delegate = self
...
Because of MainController is comfortable with MessageProtocol from
extension MainController: MessageProtocol{}
Probably it's not common case but worked for me.

How to define functions for class in different file in Swift?

I have a swift class that has about 10 different functions in it. It's over 400 lines of code and needs to be broken up. I want to put some functions in different files. What is the best way to do this? Maybe inheritance?
You can create different files and then put some method in there within extension.
Example:
class MyMessyViewController: UIViewController {
var oneVariable: String = ""
override func viewDidLoad() {
super.viewDidLoad()
anotherFunctionFromThisExtension()
}
func one(){
}
func two(){
}
func three(){
}
}
Then Create a new file and put more functions into this file within an extension.
extension MyMessyViewController {
func anotherFunctionFromThisExtension() {
oneVariable = "I made this change from this File"
print(oneVariable)
}
}
Best practice if you have Delegates, Collection/TableViews in you view controller, you can separate them with extensions, just instead of simple extension MyMessyViewController { } write like extension MyMessyViewController: UICollectionViewDelegate, UICollectionViewDataSource { }

How to override instance method from protocol extension in Swift? [duplicate]

This question already has an answer here:
Implement protocol through extension [duplicate]
(1 answer)
Closed 6 years ago.
I'm trying to override an instance method from a protocol extension, and I'm having some trouble.
For context, I'm making an iOS app with a lot of different UICollectionViews. These views get data from different databases (requiring different callback funcs) and have very different layouts. Because any combination of (database, layout) is possible, it's difficult to make a nice OOP class hierarchy without massive code duplication.
I had the idea to put the layout functions (mostly those defined in the UICollectionViewDelegateFlowLayout protocol) into protocol extensions, so I can decorate a given UICollectionView subclass with a protocol that's extended to implement all relevant layout functions, but I'm having a hard time of it. The essence of the problem is contained in the code below.
class Base {
func speak(){
print("Base")
}
}
class SubA: Base, ProtocolA {}
class SubB: Base, MyProtocolB {}
protocol MyProtocolA{
func speak()
}
protocol MyProtocolB{
func speak()
}
extension MyProtocolA{
func speak(){
print("A")
}
}
extension MyProtocolA{
func speak(){
print("B")
}
}
let suba = SubA()
suba.speak() // prints "Base", I want it to print "A"
let subb = SubB()
subb.speak() // prints "Base", I want it to print "B"
Thoughts?
The default implementations in the protocols are only called if the class that conforms to these protocols do not implement that method itself. The classes' methods override the default implementations of the protocols, not the other way around.
Typically, you'd do something like:
protocol MyProtocolA {
func speak()
}
protocol MyProtocolB {
func speak()
}
extension MyProtocolA {
func speak() {
print("A")
}
}
extension MyProtocolB {
func speak() {
print("B")
}
}
class SubA: MyProtocolA {}
class SubB: MyProtocolB {}
let suba = SubA()
suba.speak() // prints "A"
let subb = SubB()
subb.speak() // prints "B"
But if you do
class SubC: MyProtocolA {
func speak (){
print("C")
}
}
let subc = SubC()
subc.speak() // prints "C"
Frankly, as you look at this, the use of Base is entirely redundant in this example, so I've removed it. Clearly, if you need to subclass from Base for other reasons, feel free. But the key point is that protocol default implementations don't override the classes' implementation, but rather the other way around.

Override function error in swift

I got a struct :
struct ErrorResultType: ErrorType {
var description: String
var code: Int
}
and a protocol:
protocol XProtocol {
func dealError(error: ErrorResultType)
}
Now I want to make an extention of UIViewController:
extension UIViewController: XProtocol {
func dealError(error: ErrorResultType) {
// do something
}
}
So I can subclass from this and override the function like:
class ABCViewController: UIViewController {
--->override func dealError(error: ErrorResultType) {
super.dealError(error)
// do something custom
}
}
But it goes wrong with: Declarations from extensions cannot be overridden yet
It doesn't make any sense to me. When I replace all ErrorResultType with AnyObject, the error won't appear any more.
Anything I missed?
For now the method in the extension must be marked with #objc to allow overriding it in subclasses.
extension UIViewController: XProtocol {
#objc
func dealError(error: ErrorResultType) {
// do something
}
}
But that requires all types in the method signature to be Objective-C compatible which your ErrorResultType is not.
Making your ErrorResultType a class instead of a struct should work though.
If i am not making mistake this is connected with Swift official extension mechanism for adding methods to classes.
Conclusion :
At the moment, it's not possible to override entities declared in
extension by subclassing, like so:
class Base { }
extension Base {
var foo: String { return "foo" }
}
class Sub: Base {
override var foo: String { return "FOO" } // This is an error
}
Please check this resource for more information : https://github.com/ksm/SwiftInFlux/blob/master/README.md#overriding-declarations-from-extensions

Resources