Almost no beginner would say he or she like the syntax, especially the name convention of method in Objective-C. But an experienced engineer always loves it indeed. Verbose method name would describe the purpose and parameters of a method perfectly in a regular English way. In most situation, writing code in Objective-C is likely to write in English. You can just rely on the auto-completion of the IDE instead of referring to the documentation all the time. Take an example, there is a method in NSString
:
- (BOOL)writeToFile:(NSString *)path
atomically:(BOOL)useAuxiliaryFile
encoding:(NSStringEncoding)enc
error:(NSError **)error
It is not only with a clear definition, but also easy to understand in using. We can understand what and how a method would do immediately without the documentation, which is impossible in other languages.
[string writeToFile:aPath atomically:YES
encoding:NSUTF8StringEncoding error:&err];
Yeah, you would read it as "Write the string to the file at aPath atomically. It should be using NSUTF8StringEncoding encoding and log the error to the pointer err if there is any". Great, everyone can write Objective-C now!
This is a so cool feature in Objective-C and the news is Swift inherits it. The same method in Swift is defined as:
func writeToFile(_ path: String,
atomically useAuxiliaryFile: Bool,
encoding enc: UInt,
error error: NSErrorPointer) -> Bool
Except for the type name and syntax, the spirit of Objective-C version and Swift version is the same. The external name of the first parameter in this method is a _
, which means we should ignore it when calling the method. As a result of this, when calling it, we write:
string.writeToFile(aPath, atomically:true,
encoding:NSUTF8StringEncoding, error: &err)
For seeing clearer, the Objective-C version is listed here again:
[string writeToFile:aPath atomically:YES
encoding:NSUTF8StringEncoding error:&err];
You can find how coincident they are, in both structure and usage. Apple introduced a way to keep everything the same with this ignored external parameter, as well as leave others. Most of the Cocoa/Cocoa Touch APIs are following this regulation, making experienced developers comfortable as at home.
In fact, even if we do not add any external name for the parameters, there is a set of rules to follow. They relate whether or not the name labels are required when we calling methods.
In init
method of a type, the parameter names are always required. Both color
and weight
cannot be omitted when creating a Car
instance:
class Car {
init(color: UIColor, weight: Int) {
//...
}
}
let car = Car(color: UIColor.redColor(), weight: 10)
For a normal instance method, the first parameter name is always ignored, but all following ones are required:
extension Car {
func moveToX(x: Int, y: Int) {
//...
}
}
car.moveToX(10, y: 20)
It is similar to class methods:
extension Car {
class func findACar(name: String, color: UIColor) -> Car? {
var result: Car?
//...
return result
}
}
let myPorsche = Car.findACar("Porsche", color: UIColor.yellowColor())
But there is an exception case. If this method is in global scope instead of being in a type define, all parameter names should be omitted when using:
// Now not in Car type, but in a global scope.
func findACar(name: String, color: UIColor) -> Car? {
var result: Car?
//...
return result
}
let myFerrari = findACar("Ferrari", UIColor.redColor())
You may ask why there are such rules? It should not be a rash decision of Chris Lattner and these talented Swift engineers. A lot of C function is declared in a global scope, and C is too huge and powerful to throw away totally. It is more likely a back compatibility in syntax and code style for these method, which are also existing in Core Frameworks of Cocoa in a large scale.
Although there are different convention when calling a method in different scope, we could always change the default behavior by adding _
or #
to the parameter's name. But in practice, we'd better to follow the name convention of Apple when naming the methods we create:
- For normal method, make the first parameter an anonymous one (by doing nothing or adding
_
). Then force other parameters to use name. - For init method, make sure all names should exist.
By following these rules when naming a method, you can get an API similar to system's. The reader of your could would be appreciated it as well.