Using 'self' in class extension functions in Swift
Using the approach from How can I create instances of managed object subclasses in a NSManagedObject Swift extension?
you can define a generic helper method which infers the type of self
from the calling context:
extension UIView {
class func instantiateFromNib() -> Self? {
return instantiateFromNibHelper()
}
private class func instantiateFromNibHelper<T>() -> T? {
let topLevelObjects = NSBundle.mainBundle().loadNibNamed("CustomViews", owner: nil, options: nil)
for topLevelObject in topLevelObjects {
if let object = topLevelObject as? T {
return object
}
}
return nil
}
}
This compiles and works as expected in my quick test. IfMyCustomView
is your UIView
subclass then
if let customView = MyCustomView.instantiateFromNib() {
// `customView` is a `MyCustomView`
// ...
} else {
// Not found in Nib file
}
gives you an instance of MyCustomView
, and the type is
inferred automatically.
Update for Swift 3:
extension UIView {
class func instantiateFromNib() -> Self? {
return instantiateFromNibHelper()
}
private class func instantiateFromNibHelper<T>() -> T? {
if let topLevelObjects = Bundle.main.loadNibNamed("CustomViews", owner: nil, options: nil) {
for topLevelObject in topLevelObjects {
if let object = topLevelObject as? T {
return object
}
}
}
return nil
}
}
Use type of self as function parameter in extension
The "trick" is to define a protocol with a default implementation
in an extension, and make UIView
conform to that protocol:
protocol PerformOnMe { }
extension PerformOnMe {
@discardableResult func performOnMe(_ block: (Self) -> Void) -> Self {
block(self)
return self
}
}
extension UIView: PerformOnMe {}
The @discardableResult
attribute is added to avoid an
"expression result is unused" warning in the calling chain:
let button = UIButton(frame: CGRect.zero)
button.performOnMe { $0.alpha = 1 }
.performOnMe { $0.setTitle("Title", for: .normal) }
.performOnMe { $0.backgroundColor = UIColor.red }
let imageView = UIImageView()
image.performOnMe { $0.alpha = 1 }
.performOnMe { $0.image = nil }
How can I invoke a method on `Self` in a Swift extension?
Since allZeros is already a method of Int you can just do it like this:
extension Int {
static var allOnes: Int { return ~allZeros }
}
Swift extension with class: how to make a function to return an object's real type?
You need to introduce an extra type variable to say that the extension works on Optional
s where Wrapped.Element
is another Optional
of any type. You have to express the "any type" part with another type variable, but you cannot add this type variable in the extension's declaration (though this feature is being proposed), or the property's declaration. What you can do instead, is to make vals
a function:
func vals<T>() -> [T] where Wrapped.Element == T? {
var result = [T]()
if let arr = self{
for part in arr{
if let val = part{
result.append(val)
}
}
}
return result
}
Note that this can be simplified to:
extension Optional where Wrapped: Sequence {
func vals<T>() -> [T] where Wrapped.Element == T? {
self?.compactMap { $0 } ?? []
}
}
what is 'where self' in protocol extension
That syntax is: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID521
Consider:
protocol Meh {
func doSomething()
}
// Extend protocol Meh, where `Self` is of type `UIViewController`
// func blah() will only exist for classes that inherit `UIViewController`.
// In fact, this entire extension only exists for `UIViewController` subclasses.
extension Meh where Self: UIViewController {
func blah() {
print("Blah")
}
func foo() {
print("Foo")
}
}
class Foo : UIViewController, Meh { //This compiles and since Foo is a `UIViewController` subclass, it has access to all of `Meh` extension functions and `Meh` itself. IE: `doSomething, blah, foo`.
func doSomething() {
print("Do Something")
}
}
class Obj : NSObject, Meh { //While this compiles, it won't have access to any of `Meh` extension functions. It only has access to `Meh.doSomething()`.
func doSomething() {
print("Do Something")
}
}
The below will give a compiler error because Obj doesn't have access to Meh extension functions.
let i = Obj()
i.blah()
But the below will work.
let j = Foo()
j.blah()
In other words, Meh.blah()
is only available to classes that are of type UIViewController
.
passing an object (self) into extension
Array already has a placeholder type for its elements: Element
. Your generic parameter T
is exactly that placeholder type, so you can just use Element
:
extension Array {
func anotherFilter(predicate: (Element) -> Bool) -> [Element] {
var filteredArray = [Element]()
for item in self where predicate(item) {
filteredArray.append(item)
}
return filteredArray
}
}
Class Function In Extension Converting to Self
Try this:
extension UIView {
class func instantiateNIB(name: String, bundle: NSBundle? = nil) -> Self? {
return instantiateNIB(self, name: name, bundle: bundle)
}
private class func instantiateNIB<T>(type: T.Type, name: String, bundle: NSBundle? = nil) -> T? {
let nib = UINib(nibName: name, bundle: bundle)
let views = nib.instantiateWithOwner(nil, options: nil)
for view in views {
if let match = view as? T {
return match
}
}
return nil
}
}
Related Topics
How to Pop to the Root View Using Swiftui
How Does String Substring Work in Swift
Saving Custom Swift Class With Nscoding to Userdefaults
How to Provide a Localized Description With an Error Type in Swift
How to Cast Self to Unsafemutablepointer≪Void≫ Type in Swift
What Is the Purpose of Willset and Didset in Swift
How to Convert a Date String With Optional Fractional Seconds Using Codable in Swift
Examples of Delegates in Swift
How to Use String.Substringwithrange? (Or, How Do Ranges Work in Swift)
Error-Handling in Swift-Language
Overriding Methods in Swift Extensions
How to Make a Swiftui List Scroll Automatically
Inter-App Data Migration (Migrating Data to New App Version)
How to Find String B Missing Characters Based on String a and Add Them to String B
How to Create a Multi-Line Text Inside a Scrollview in Swiftui