Are Extensions Bad for Performance in Swift

are extensions bad for performance in swift?

Apple encourages the use of extensions. You can read more about them on the Swift documentation here.

Swift: private / fileprivate runtime performance

Why would there be such a difference? These privacy terms are mostly just notes to the compiler to forbid certain kinds of access.

The important gains at runtime come from using Whole Module Optimization and/or declaring your classes final. This allows dynamic dispatch to be switched off.

Best practices for extensions of Types in swift

Sample ImageI usually don't implement extension anywhere across ViewControllers because if 5 VCs need 5 different extension functionalitis for an Array then we have to write extension Array { } in 5 VCs which will make it hard to navigate and find the implementation for extended functionalities. So what I actually do is make an Extension folder in project hierarcy Where I will make a file named Array+Extension.swift. All the functions releted to array extension will go inside Array+Extension file. The above image will give you a clear picture.

Class extension vs. subclassing in Swift?

It's

b)

because adding (stored) properties in a class extension is not supported.

There are two important rules for using extensions:

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

  • Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties

Where to put Firebase Performance trace

are you using Firebase Performance in the context of an App Extension (e.g. Watch, keyboard, today, etc.)? That message is triggered by this line in the FirebasePerformance.h file:

NS_EXTENSION_UNAVAILABLE("FirebasePerformance does not support app extensions at this time.")

Firebase Performance currently only supports normal applications on iOS.

Failed Trying to use Extensions - Swift

Short answer:

For a class derived from NSObject, a Swift property
which has the same name as an existing Objective-C method replaces that method.

Therefore in your case,

var size: CGSize {
return self.size()
}

calls itself recursively until the program aborts with a stack overflow
(well, that's what this site is for :).

If you choose a different name for the property, e.g.

var theSize: CGSize {
return self.size()
}

then everything works nicely.


Long answer:

SKTexture is a subclass of NSObject. Therefore all Swift properties are
"Objective-C compatible". As a consequence, the compiler generates a getter
method that can be called from Objective-C code. The getter method for the
size property is a -size method. So you have now two -size methods:
The original one from SKTexture and a second one defined in your Swift code.

If you do the same with your own Objective-C class defined in the same project
then you will get a linker warning:

instance method 'size' in category from /Users/.../main.o overrides
method from class in /Users/.../MyClass.o

If the Objective-C class is defined in a external framework (as in your case)
the linker does not notice the conflict.

Now return self.size() calls the generated Objective-C getter method, which in turn
calls the extension method. This leads to "infinite" recursion and ultimately
to a stack overflow.

This is confirmed by the stack backtrace which you can get with the lldb bt
command when the program has crashed:


* thread #1: tid = 0x3d2ef, 0x000000010fb15e01 libobjc.A.dylib`objc::DenseMapBase, unsigned long, true, objc::DenseMapInfo > >, DisguisedPtr, unsigned long, objc::DenseMapInfo >, true>::FindAndConstruct(DisguisedPtr const&) + 21, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff51b9cfe8)
frame #0: 0x000000010fb15e01 libobjc.A.dylib`objc::DenseMapBase, unsigned long, true, objc::DenseMapInfo > >, DisguisedPtr, unsigned long, objc::DenseMapInfo >, true>::FindAndConstruct(DisguisedPtr const&) + 21
frame #1: 0x000000010fb13e14 libobjc.A.dylib`objc_object::sidetable_retain() + 94
* frame #2: 0x000000010d8674d9 cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 25 at AppDelegate.swift:19
frame #3: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #4: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
frame #5: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #6: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
frame #7: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #8: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
...
frame #149556: 0x000000010d8674ed cdtest2`ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize(self=0x00007fcceea020f0) + 45 at AppDelegate.swift:19
frame #149557: 0x000000010d867542 cdtest2`@objc ext.cdtest2.ObjectiveC.SKTexture.size.getter : C.CGSize + 34 at AppDelegate.swift:0
frame #149558: 0x000000010d8694e0 cdtest2`cdtest2.AppDelegate.application (application=0x00007fccee8005a0, launchOptions=None, self=0x00007fccebc06410)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional>) -> Swift.Bool + 112 at AppDelegate.swift:83
frame #149559: 0x000000010d8697b0 cdtest2`@objc cdtest2.AppDelegate.application (cdtest2.AppDelegate)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional>) -> Swift.Bool + 560 at AppDelegate.swift:0
...
frame #149572: 0x000000010d86bcaa cdtest2`main + 42 at AppDelegate.swift:0
frame #149573: 0x00000001102f0145 libdyld.dylib`start + 1

This (hopefully) explains also why the problem occurs with both someTexture.size().width and someTexture.size.width:
In both cases, the custom extension method is called.

Swift 2, protocol extensions & respondsToSelector

Interesting. Looks like a bug to me. It does recognize functions on a class, but not on extension. No matter what type Instance has. Moreover without an extension code would not be compilable, since protocol methods are non optional. So really looks like a bug/feature? in responds to selector implementation.



Related Topics



Leave a reply



Submit