Using 'Self' in Class Extension Functions in Swift

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. If
MyCustomView 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 Optionals 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



Leave a reply



Submit