Swift Extension: Same Extension Function in Two Modules

Is the function name in the extension should be really unique or not in swift

and I have the same name function in the extension file, is it going to be a compiler error?

Yes

I was wondering if I need to change the name of the function to something really unique

Nah, just write it in the way that makes your code best. Don’t make your code ugly just to make it defensive.

I think the only issue you might run into is if two libraries both declare the same extension. If the extension is one that you wrote yourself, you should get an error if it’s redeclaring a method that already exists.

What is the scope of extensions in swift?

The scope of an extension follows the same rules as when creating structs, classes and other types and variables in swift.

By default the extension is internal to the module it is created in and so accessible to all files in that module.

You can change that to public or private if you wish to.

The collisions you reference would occur if two extensions of the same were visible to each other and added a function with the same signature.

So, if you wanted to create your trimmed() extension in several files and give it a different implementation in each file you would need to make them all private to avoid any conflict.

Although… that might not be a good idea as it could be quite confusing with several of these in your project.

A Swift module that contains all extension methods

Inspired by the approach RxSwift went on, here's a solution that provides access to both instance and static members of the my extension.

First things first, let's declare the basis for the extension:

struct MyExtension<Target> {
let target: Target

init(_ target: Target) {
self.target = target
}
}

Let's allow types to conform:

protocol MyExtensionCompatible { }

extension MyExtensionCompatible {
// instance extension
var my: MyExtension<Self> { return MyExtension(self) }

// static extension
static var my: MyExtension<Self>.Type { return MyExtension<Self>.self }
}

Now let's start playing and add the UIColor conformance:

extension UIColor: MyExtensionCompatible { }

extension MyExtension where Target == UIColor {

static var customColor: UIColor { return UIColor.blue }

func toImage() -> UIImage {
return UIImage()
}
}

Finally, let's use everything we created above:

// the static property
let color = UIColor.my.customColor

// the instance function
let colorImage = color.my.toImage()

// foldoesn't compile, compile, we haven't declared UILabel as compatible
let color2 = UILabel.my

What's nice about the above approach is that the methods declared as static will be available via the static protocol property, while the instance ones via the instance protocol property.

Creating a swift extension function for all controllers to access

If I have understood your desire correctly, you can achieve this with a manager class instead of extension, which will be responsible for downloading image for you. Create a class like below:

class ImageDownloaderManager {
class func loadImageFromDatabase(userImage: UIImageView, imageUrl: String, completionHandler: @escaping (Bool)-> Void) {

image.sd_setImage(with: URL(string: imageUrl!)) { (image, error, cache, urls) in
if (error != nil) {
userImage.image = UIImage(named: "1") // set your placeholder image maybe.
completionHandler(false)
} else {
userImageimage = image
completionHandler(true)
}
}
completionHandler(true)
}
}

It has a completion block where you can understand if your image was downloaded successfully or not from where-ever you call this function. Lets say you call this method from a viewController's viewDidLoad method as following:

override func viewDidLoad() {
super.viewDidLoad()
ImageDownloaderManager.loadImageFromDatabase(image: yourImage, imageUrl: yourImageURL) { (isSucceeded) in
if isSucceeded {
// It was successful, you could download the image successfully, do smth
} else {
// It was not successful image couldnt be downloaded, placeholder image has been set.
}
}
}

Overriding methods in Swift extensions

Extensions cannot/should not override.

It is not possible to override functionality (like properties or methods) in extensions as documented in Apple's Swift Guide.

Extensions can add new functionality to a type, but they cannot override existing functionality.

Swift Developer Guide

The compiler is allowing you to override in the extension for compatibility with Objective-C. But it's actually violating the language directive.

That just reminded me of Isaac Asimov's "Three Laws of Robotics" /p>

Extensions (syntactic sugar) define independent methods that receive their own arguments. The function that is called for i.e. layoutSubviews depends on the context the compiler knows about when the code is compiled. UIView inherits from UIResponder which inherits from NSObject so the override in the extension is permitted but should not be.

So there's nothing wrong with grouping but you should override in the class not in the extension.

Directive Notes

You can only override a superclass method i.e. load() initialize()in an extension of a subclass if the method is Objective-C compatible.

Therefore we can take a look at why it is allowing you to compile using layoutSubviews.

All Swift apps execute inside the Objective-C runtime except for when using pure Swift-only frameworks which allow for a Swift-only runtime.

As we found out the Objective-C runtime generally calls two class main methods load() and initialize() automatically when initializing classes in your app’s processes.

Regarding the dynamic modifier

From the Apple Developer Library (archive.org)

You can use the dynamic modifier to require that access to members be dynamically dispatched through the Objective-C runtime.

When Swift APIs are imported by the Objective-C runtime, there are no guarantees of dynamic dispatch for properties, methods, subscripts, or initializers. The Swift compiler may still devirtualize or inline member access to optimize the performance of your code, bypassing the Objective-C runtime. /p>

So dynamic can be applied to your layoutSubviews -> UIView Class since it’s represented by Objective-C and access to that member is always used using the Objective-C runtime.

That's why the compiler allowing you to use override and dynamic.



Related Topics



Leave a reply



Submit