In Swift it's not necessary to prefix classes anymore as their module acts as the namespace.
What about prefixing extension functions? For example:
extension UIImage {
public func hnk_hasAlpha() -> Bool { ... }
}
On one hand Swift is not dynamic so collisions would generate compiler errors.
But what happens if compiled code runs in a future iOS/OS X version in which one of my extension methods is added? Would methods in different modules be considered different symbols even if they have the same signature?
Does it make a difference if the extended class is a NSObject subclass or a pure Swift class?
There's some subtlety here:
Extensions of Objective-C types are implemented as Objective-C categories, with all that implies.
Extensions of Swift types, however, are only in effect where visible due to imports. This means that you can't accidentally stomp on a private system method (whether now or one introduced in the future), and if the system introduces a public method with the same name as yours, you'll get a compile-time failure when you rebuild, but your existing app won't break.
You should check those threads also:
Name collisions for extension methods from different frameworks - quote from thread:
regardless the application code imports which Framework, it seems, the actual called implementation depends on the order in Linked Frameworks and Libraries in "First come, first served" manner. But, as far as I know, this behavior is not guaranteed.
and Swift Extension: same extension function in two Modules which also confirms the same problem.
So based on that for Objective-C objects such as UIImage from your example name collisions are possible and you might see unexpected behaviour if there will be two methods with the same name in two different extensions for Objective-C object.
Related
In Swift, I have historically used extensions to extend closed types and provide handy, logic-less functionality, like animations, math extensions etc. However, since extensions are hard dependencies sprinkled all over your code-base, I always think three times before implementing something as an extension.
Lately, though, I have seen that Apple suggests using extensions to an even greater extent, e.g. implementing protocols as separate extensions.
That is, if you have a class A that implement protocol B, you end up with this design:
class A {
// Initializers, stored properties etc.
}
extension A: B {
// Protocol implementation
}
As you enter that rabbit-hole, I started seeing more extension-based code, like:
fileprivate extension A {
// Private, calculated properties
}
fileprivate extension A {
// Private functions
}
One part of me likes the building-blocks you get when you implement protocols in separate extensions. It makes the separate parts of the class really distinct. However, as soon as you inherit this class, you will have to change this design, since extension functions cannot be overridden.
I think the second approach is...interesting. Once great thing with it is that you do not have to annotate each private property and function as private, since you can specify that for the extension.
However, this design also splits up stored and non-stored properties, public and private functions, making the "logic" of the class harder to follow (write smaller classes, I know). That, together with the subclassing issues, makes me halt a bit on the porch of extension wonderland.
Would love to hear how the Swift community of the world looks at extensions. What do you think? Is there a silverbullet?
This is only my opinion, of course, so take what I'll write easy.
I'm currently using the extension-approach in my projects for few reasons:
The code is much more clean: my classes are never over 150 lines and the separation through extensions makes my code more readable and separated by responsibilities
This is usually what a class looks like:
final class A {
// Here the public and private stored properties
}
extension A {
// Here the public methods and public non-stored properties
}
fileprivate extension A {
// here my private methods
}
The extensions can be more than one, of course, it depends on what your class does. This is simply useful to organize your code and read it from the Xcode top bar
It reminds me that Swift is a protocol-oriented-programming language, not an OOP language. There is nothing you can't do with protocol and protocol extensions. And I prefer to use protocols for adding a security layer to my classes / struct. For example I usually write my models in this way:
protocol User {
var uid: String { get }
var name: String { get }
}
final class UserModel: User {
var uid: String
var name: String
init(uid: String, name: String) {
self.uid = uid
self.name = name
}
}
In this way you can still edit your uid and name values inside the UserModel class, but you can't outside since you'll only handle the User protocol type.
I use a similar approach, which can be described in one sentence:
Sort a type's responsibilities into extensions
These are examples for aspects I'm putting into individual extensions:
A type's main interface, as seen from a client.
Protocol conformances (i.e. a delegate protocol, often private).
Serialization (for example everything NSCoding related).
Parts of a types that live on a background thread, like network callbacks.
Sometimes, when the complexity of a single aspect rises, I even split a type's implementation over more than one file.
Here are some details that describe how I sort implementation related code:
The focus is on functional membership.
Keep public and private implementations close, but separated.
Don't split between var and func.
Keep all aspects of a functionality's implementation together: nested types, initializers, protocol conformances, etc.
Advantage
The main reason to separate aspects of a type is to make it easier to read and understand.
When reading foreign (or my own old) code, understanding the big picture is often the most difficult part of diving in. Giving a developer an idea of a context of some method helps a lot.
There's another benefit: Access control makes it easier not to call something inadvertently. A method that is only supposed to be called from a background thread can be declared private in the "background" extension. Now it simply can't be called from elsewhere.
Current Restrictions
Swift 3 imposes certain restrictions on this style. There are a couple of things that can only live in the main type's implementation:
stored properties
overriding func/var
overidable func/var
required (designated) initializers
These restrictions (at least the first three) come from the necessity to know the object's data layout (and witness table for pure Swift) in advance. Extensions can potentially be loaded late during runtime (via frameworks, plugins, dlopen, ...) and changing the type's layout after instances have been created would brake their ABI.
A modest proposal for the Swift team :)
All code from one module is guaranteed to be available at the same time. The restrictions that prevent fully separating functional aspects could be circumvented if the Swift compiler would allow to "compose" types within a single module. With composing types I mean that the compiler would collect all declarations that define a type's layout from all files within a module. Like with other aspects of the language it would find intra file dependencies automatically.
This would allow to really write "aspect oriented" extensions. Not having to declare stored properties or overrides in the main declaration would enable better access control and separation of concerns.
I hate it. It adds extra complexity and muddies the use of extensions, making it unclear on what to expect that people are using the extensions for.
If you're using an extension for protocol conformance, OK, I can see that, but why not just comment your code? How is this better? I don't see that.
In ObjC, it is using Messaging, static binding, dynamic typing, dynamic binding, dynamic method resolution, dynamic loading, introspector and so on.
Importantly, the core method objc_msgSend is responsible for taking the selector you're sending and the object you're sending it to, and looking that up in the class method tables to figure out exactly which piece of code is supposed to handle it.
My concerns here are:
Is Swift doing something similar like ObjC on runtime?
How does Swift runtime find the implementation code for some object/class method?
In ObjC, classes and objects are compiled to some runtime types such as C struct on runtime. Then what are such classes and objects compiled to on runtime in Swift?
Does Swift runtime have something like class / meta class / isa pointer / super pointer?
In short there are Dynamic and Static types of method call dispatching.
Static - the function address to be called is determined in the compilation time, so that expense of such call is similar to C-function calling. This mechanism is used for private methods or final classes methods call dispatching.
Dynamic dispatching is mechinism which allows to implement polymorphism concept of OOP - the function address to be called is determined in running time. Swift has two subtypes of it:
2.1. Obj-C - you already described in the question. This mechanism is used when object inherits from NSObject or calling method has #objc prefix.
2.2. Virtual table based (like in C++) - there is similar witness tables. What it does during method call dispatching is just single arithmetic operation - calculation of actual function address based on function offset in the base class witness table and the object class witness table location. So that's a relatively cheap operation comparing to Obj-C. It explains why "pure" Swift approximates to C++ performance.
If you don't mark you method with private keyword or your class is not final and same time you class is "pure" Swift (it does not inherit NSObject) then this virtual table based mechanism is used. It means that all the methods by default are virtual.
P.S.
Helpful link for proving my vision regarding "Types":
https://developer.apple.com/swift/blog/?id=27
"Subtypes" explanation is based on my understanding.
I'm trying to add a new file to my Xcode project using Xcode 6.1.1 and Xcode now has a "File type" option where you select between "Empty File, Category, Protocol, Extension"
Can someone explain the differences between these and what the default to select would be? My file is a subclass of NSObject.
Thanks
Category
Categories are used to help modularize and organize class definitions. They allow you to take a (complex) class definition and spread it over several organized classes. It is not the same as subclassing. Although categories do allow you to override methods, Objective-C has no way of determining which method definition should be used, so you should never use a category to override methods. Instead, create a subclass that overrides the method as per usual.
Categories can contain protected methods, which "allow arbitrary files to 'opt-in' to a portion of an API by simply importing the category." (Check out the articles linked below.)
Extension
Extensions provide similar functionality to categories, except that you must implement the extension's API in the main implementation file.
Extensions can also be used to create a formal private API. Ordinarily, if you wanted to create private methods, you would write them in the implementation block, but would exclude them from the interface block. However, if you have an extensive group of methods that you would like to remain private, this becomes cumbersome and difficult to read/maintain. Using extensions, you can define the private methods in both the interface and implementation blocks of the .m file. As long as you do not include it in the respective .h file, these methods will be treated as private methods.
Extensions can also be used to make previously declared properties that are read-only outside the class read-write within the class (using the "self." syntax).
Protocol
Protocols allow for abstracted horizontal relationships across various (sometimes unrelated) classes and class hierarchies. A protocol consists of an API that can be used by a variety of classes, regardless of whether or not they are related. This allows you to modify/add some class functionality through a potentially wide range of classes without having to subclass them and alter their own class hierarchies.
In order to use a protocol, a class only needs to:
1. Include the protocol's name inside angled brackets <> after the class/superclass name declaration
2. Implement the protocol's methods
Protocols can also be useful for type checking.
Empty File
An empty file is just that - an empty file. You give it a name, but it contains no class information whatsoever (no generated methods, blocks, comments, etc.).
Sources: RyPress article on Categories and Extensions and RyPress article on Protocols. Both articles have helpful examples of each tool.
I'm a bit confused with Apple documentation relating to the explanation of whether to use prefix for methods or not?
Apple Doc Explanation 1:
Use prefixes when naming classes, protocols, functions, constants, and typedef structures. Do not use prefixes when naming methods; methods exist in a name space created by the class that defines them. Also, don’t use prefixes for naming the fields of a structure
Apple Doc Explanation 2:
If you are subclassing a large Cocoa framework class (such as NSView or UIView) and you want to be absolutely sure that your private methods have names different from those in the superclass, you can add your own prefix to your private methods. The prefix should be as unique as possible, perhaps one based on your company or project and of the form "XX_". So if your project is called Byte Flogger, the prefix might be BF_addObject:
For Classes which contains project related storylines/stuffs, there prefixes are not required.
But if we are using Apple Classes by extending few methods as given in example, like UIView to MBView then we should add prefix to methods to private methods in private category ( in .m file).
This is because ObjC does not support namespaces. Instead you should you capital letter prefixes(as you properly read in documentation). You could read this SO discussion why to use them.
Note that Apple uses two-letter prefixes(UI(View), NS(String), etc.) and advises programmers to use 3 letter prefixes.
I think you should use a prefix when you can, it can become a good practice and you can identify, by the name which part of your big software you're playing with.
Let's say your program name is Byte Flogger, then all your classes should start with :
BF prefix. BFBaseList for exemple, and if you want to prevent rejections when submitting your app to the AppStore, it's also a good practice to name your methods bfMyMethodName so that you still respect CamLCase naming conventions.
So for an image, you could name a property bfContentMode without being suspected by Apple to use one private API feature.
Now, let's say you handle some modules, a core module, a network module, etc...
If your class name is BFCObject, you could know that you're working with a Core object of your program.
So it is not necessary, but not doing it could force you to refactor your code in the last moment of submission. In a time driven project, I wouldn't even take that risk.
It's possible to add extensions to existing Swift object types using extensions, as described in the language specification.
As a result, it's possible to create extensions such as:
extension String {
var utf8data:NSData {
return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
}
}
However, what's the best naming practice for Swift source files containing such extensions?
In the past, the convention was to use extendedtype+categoryname.m for the Objective-C
type as discussed in the Objective-C guide. But the Swift example doesn't have a category name, and calling it String.swift doesn't seem appropriate.
So the question is: given the above String extension, what should the swift source file be called?
Most examples I have seen mimic the Objective-C approach. The example extension above would be:
String+UTF8Data.swift
The advantages are that the naming convention makes it easy to understand that it is an extension, and which Class is being extended.
The problem with using Extensions.swift or even StringExtensions.swift is that it's not possible to infer the purpose of the file by its name without looking at its contents.
Using xxxable.swift approach as used by Java works okay for protocols or extensions that only define methods. But again, the example above defines an attribute so that UTF8Dataable.swift doesn't make much grammatical sense.
I prefer having a + to underline the fact it contains extensions :
String+Extensions.swift
And if the file gets too big, you can then split it for each purpose :
String+UTF8Data.swift
String+Encrypt.swift
There is no Swift convention. Keep it simple:
StringExtensions.swift
I create one file for each class I'm extending. If you use a single file for all extensions, it will quickly become a jungle.
I prefer StringExtensions.swift until I added too much things to split the file into something like String+utf8Data.swift and String+Encrypt.swift.
One more thing, to combine similar files into one will make your building more faster. Refer to Optimizing-Swift-Build-Times
Rather than adding my comments all over the place, I'm surfacing them all here in one answer.
Personally, I take a hybrid approach that gives both good usability and clarity, while also not cluttering up the API surface area for the object that I'm extending.
For instance, anything that makes sense to be available to any string would go in StringExtensions.swift such as trimRight() and removeBlankLines().
However, if I had an extension function such as formatAsAccountNumber() it would not go in that file because 'Account Number' is not something that would naturally apply to any/all strings and only makes sense in the context of accounts. In that case, I would create a file called Strings+AccountFormatting.swift or maybe even Strings+CustomFormatting.swift with a formatAsAccountNumber() function if there are several types/ways to actually format it.
Actually, in that last example, I actively dissuade my team from using extensions like that in the first place, and would instead encourage something like AccountNumberFormatter.format(String) instead as that doesn't touch the String API surface area at all, as it shouldn't. The exception would be if you defined that extension in the same file where it's used, but then it wouldn't have it's own filename anyway.
If you have a team-agreed set of common and miscellaneous enhancements, lumping them together as an Extensions.swift works as Keep-It-Simple first level solution. However, as your complexity grows, or the extensions become more involved, a hierarchy is needed to encapsulate the complexity. In such circumstances I recommend the following practice with an example.
I had a class which talks to my back-end, called Server. It started to grow bigger to cover two different target apps. Some people like a large file but just logically split up with extensions. My preference is to keep each file relatively short so I chose the following solution. Server originally conformed to CloudAdapterProtocol and implemented all its methods. What I did was to turn the protocol into a hierarchy, by making it refer to subordinate protocols:
protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol {
var server: CloudServer {
get set
}
func getServerApiVersion(handler: #escaping (String?, Error?) -> Swift.Void)
}
In Server.swift I have
import Foundation
import UIKit
import Alamofire
import AlamofireImage
class Server: CloudAdapterProtocol {
.
.
func getServerApiVersion(handler: #escaping (String?, Error?) -> Swift.Void) {
.
.
}
Server.swift then just implements the core server API for setting the server and getting the API version. The real work is split into two files:
Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift
These implement the respective protocols.
It means you need to have import declarations in the other files (for Alamofire in this example) but its a clean solution in terms of segregating interfaces in my view.
I think this approach works equally well with externally specified classes as well as your own.
Why is this even a debate? Should I put all my sub classes into a file called _Subclasses.swift. I think not. Swift has module based name spacing. To extend a well known Swift class needs a file that is specific to its purpose. I could have a large team that creates a file that is UIViewExtensions.swift that express no purpose and will confuse developers and could be easily duplicated in the project which would not build. The Objective-C naming convention works fine and until Swift has real name spacing, it is the best way to go.