Many Cocoa and Cocoa Touch calls are boilerplate. They use common argument values with nearly every call. Why not take advantage of Swift's default system instead? We'd like to simplify calls like this:
dismissViewControllerAnimated(flag: true, completion: nil)
to calls like this:
dismiss()
Joe Groff:
Note that framework owners really don’t have the tools to do this right now: one cannot effectively replace an Objective-C method with a method in an overlay without breaking overriding, so framework owners who wanted to add defaults for specific APIs would likely need a way to spell the default argument in Objective-C that would work through the Clang importer.
Dave A:
I don't think we can add anything to SE-0005 now that it's accepted, but the "parameter patterns" part of this gist looks like it could be a proposal on swift-evolution for the Objective-C importer. We'd need to make sure the framework owners or their representatives participate in that review, though. The rest are still radar fodder, I think.
SE-0005 introduced a number of ways in which ObjC APIs will gain default values through automatic translation. Under this accepted proposal, any method that matches one of the following patterns will now provide default values:
- Trailing closures: nullable closure parameters will default to
nil. - NSZones: nullable zones also default to
nil. (The proposal notes that they should always benilto begin with as they are unused in Swift.) - Option sets: Any type name containing the word
Optionsdefaults to[], the empty option set. - Dictionaries:
NSDictionaryparameters with names includingoptions,attributes, andinfodefault to[:], the empty dictionary.
Daniel Steinberg and I love this defaulting behavior and approached the Swift Evolution list to see whether we could expand defaults for Cocoa and Cocoa Touch APIs even further. David Abrahams replied that we should best proceed by putting together specific requests and file them as radars for the UIKit/AppKit teams, who would then presumably provide extensions that pass the default values.
For example, dismissViewControllerAnimated(flag: true, completion: nil)
could become dismissAnimated() or better yet dismiss() when default values
are available for flag and completion. There's a large-ish class of these boilerplate
defaults.
Here's our preliminary list of updates that we'd like to see, and we're requesting community input to help us expand that list, so when we approach our bug reports that we've already thought through and prioritized the kinds of changes we're invested in.
Here's our current list:
-
Set a default value for any case where an imported API uses an enum parameter that offers a case named
.Normal,.Default, or.Plain. For example, the action style forUIAlertAction, the view style forUIAlertViewStyleDefault, the table row action style forUITableViewRowActionStyleDefaultall provide.Defaultoptions.UIBarButtonItemoffers a.Plainstyle. Other.Plainstyle enums includeUITableViewStyle,PKPaymentButtonType, andWKTextInputMode. -
In any case where an imported API uses more than one parameter and one of those parameters is
bundle:, default that parameter to nil. For example, forUIStoryboard'sstoryboardWithName:bundle:andUINib'snibWithName:bundle:, thebundle:should default to nil.
UIControlstates should always default to.Normal, e.g.button.setTitle("Hello"). (This recommendation overlaps with the parameter name section from earlier in this write-up.)UIButtonactions should always default to.TouchUpInside, e.g.button.addTarget(target, action: action)(although, honestly,button.add(target: target, action: action)would be preferable)UISliderandUISwitch(and probablyUIStepperandUISegmentedControl) actions should always default to.ValueChanged, e.g.slider.addTarget(target, action: action)
- CG construction should always default to
0.0values (e.g.x: 0.0, y:0.0, dX: 0.0, dY: 0.0, width: 0.0, height: 0.0). This courtesy should probably extend as well toUIEdgeInsets,UIOffsetMake, and possiblyCGAffineTransform(this using identity transform defaults).
UIGraphicsBeginImageContextWithOptionsalmost universally usesscaleof0.0. (This follows the screen scale of the current device.)animated:should always default totruefor UIKit controller calls. We note that callingsuper.viewWillAppear()is foolish. You should always pass on the argument that was passed to you. A full list of UIKitanimated:references including controller and non-controller APIs is here.
UIColor,SKColor, andNSColor's constructors should default toalpha=1.0
NSNotificationCentertheobject:parameter should default to nil.
NSLayoutConstraintcan default to relation (relatedBy).Equal, multiplier1.0, constant0.0, secondItem (toItem)nil, second attribute (attribute).NotAnAttribute. One can argue that defaults should be limited to multiplier and constant as readability suffers by defaulting relation, secondItem, and secondAttribute and single-item constraints represent the minority of use-cases. However, there's also an argument for enhanced readabilityNSLayoutConstraint(item: view, attribute: .Width, constant: 400.0)and the defaulted arguments can still be used.
To simplify record fetches:
* CKModifyRecordsOperation
recordIDsToDelete: could default to nil.* CKQuery could introduce a default TruePredicate.
Please suggest additional defaults to help grow this list
Some other items:
UIAlertAction style: parameter default to .Default
UIStoryboard storyboardWithName:bundle: - bundle: should default to nil (same for UINib nibWithName:bundle:)
NSNotificationCenter various subscribe/unsubscribe calls should default object: parameter to nil