Xcode 8.2
will be the latest release that supports the transition version of Swift 2.3
. Therefore, we need to urgently think about migrating to Swift 3
.ScrollView
, working with the Twitter server, and Core Data database, working with the Cloud Kit cloud service, and Map Kit . And all this was written in Swift 2.2
( stanford.edu ), and I needed to transfer all applications to Swift 3
. A summary of the Stanford course lectures in Russian can be found on the About Stanford Lectures website, and the code for Swift 2.3 on Github and for Swift 3 on Github .Swift 3
, then in Xcode 8
you need to run the migration tool (a kind of “robot”) using the menu Edit → Convert → to Current Swift Syntax :Swift 2
source code and the Swift 3
code that generated this “robot”:Xcode 8.1
and Xcode 8.2
works perfectly compared to the initial version in Xcode 8.0
, with which I had to start. The new migration “robot” is inventive and very reasonable. Using the example of this map of differences, it is possible to study perfectly the changes that certain syntactic constructions underwent in Swift 3
. The migration “robot” does a great job of replacing names, method signatures and properties, transforming, if necessary, previously common properties in Generic (for example, NSFetchRequest
, which is not Generic in Swift 2
, but is in Swift 3
). It can replace the whole code with whole “patterns”, for example, singleton, if it was executed by old means using dispatch_once(&onceToken)
.Swift 3
. In applications, 2-3 errors and 3-4 warnings remain. Therefore, your next step will be to open the “errors and warnings” navigator (if any) and examine them all one by one:json
variable, which in Swift 3
is represented by a “robot” as Any
, although we work with it as with a reference variable. The result is:String?
in Any
. This can be corrected in three ways and thus remove this warning:Optional
value,Any
with the code as Any
.nil
:Swift 2
and Swift 3
. All this code is technically correct, but it can be either redundant or inefficient or lead to execution errors. Some of these situations are of a general nature, and some are highly dependent on the specifics of your application.fileprivate
back to private
.Swift 3
all private
access levels are replaced with the new fileprivate
access fileprivate
, because the private
in Swift 2
made fileprvate
.private
with new fileprivate
, that is, expanded the scope of access to private
variables and methods.fileprivate
access level at all, but you have to solve it yourself in your development team and fix it manually.Swift 3
will replace all public
access levels that were in Swift 2
with a new access level open
. This applies only to classes.Swift 3
:open
class is available and may have subclasses outside the module in which it is defined. Properties and methods of the open
class are available and can be overridden outside the module in which the class is defined.public
class is available, but cannot have subclasses outside the module in which it is defined. The properties and methods of the public
class are available, but cannot be overridated outside the module in which the class is defined.open
access level is what was public
in previous versions of Swift
, and the public
access level is more limited. Chris Lattner said in SE-0177: Allow distinguishing between public access and public overridability that in Swift 3
, the access level open
simply more public than public
. You can also see the SE-0025 Scoped Access Level .Swift 3
we will not return the access level open
back to public
. Here we are all happy.Swift 3
is arranged in descending order:open
→ public
→ internal
→ fileprivate
→ private
Optional
values in Swift 3
.Swift 2
to Swift 3
sometimes code appears in front of some classes:Swift 2
it was possible to compare Optional
values, for example, thus:Swift 3
this option was removed ( SE-0121 - Remove Optional Comparison Operators ) and to preserve this code in Swift 3
migration “robot” adds the above code, which, of course, is convenient at the initial stage of switching to Swift 3
, but not nicely, as if you encounter comparison of Optional
values in several classes located in separate files, then the above code will be added many times. This code must be removed, the problem will immediately be identified, and the problem must be solved on the spot. First, we get rid of Optional
using the if let
syntax, and then we make the necessary comparison. For example:Swift 3
does not provide automatic compatibility (bridging) of numbers with NSNumber
.Swift 2
many types, if necessary, were automatically combined (“bridging”) with instances of some NSObject NSObject
, for example, String
in NSString
, or Int
, Float
, ... in NSNumber
. In Swift 3
you will have to do this conversion explicitly ( SE -0072 Fully eliminate implicit bridging conversions from Swift ). For example, in Swift 2
we had code to convert a number to a string:Swift 3
after the migration "robot" we get the error:Double
to NSNumber
, and we can use two conversion methods — using the as
operator:NSNumber
initializer:dispatch_once
QOS_CLASS_USER_INITIATED
parallel queue with the subsequent transition to the main queue to display data on the UI on Swift 2
looks like this:global(priority: qos)
function global(priority: qos)
, which will be abolished in iOS 10
:global (qos: .userInitiated)
:dispatch_once
, which is abolished in Swift 3
, and it should be replaced with either a global, or a static variable or a constant.Swift 2
:Swift 3
after the work of the migration “robot”:lazy
variable __once
, which is represented as a performed closure, and we are warned that the variable onceToken
not used. It really is no longer needed, and we remove this line:…inPlace
, when switching to Swift 3
.Swift 3
returns to the convention on naming methods and functions that was in Swift 1
, that is, functions and methods are named depending on whether they create a “side effect”. And that's great. Let's give a couple of examples.x.distance (to: y)
x = y.union(z)
X
be sorted, then I will say: “ X
sort ( sort
) yourself or add X
( append
) to yourself Y
”:x.sort ()
x.append(y)
y.formUnion(z)
Swift 3
groups methods into two categories: methods that take action in place — think of them as Verbs — and methods that return the result of performing a specific action without affecting the original object — think of them as Nouns .ed
”, then everything happens “by place”: sort ()
, reverse ()
, enumerate ()
. These are Verbs . Every time Swift 3
modifies a method by adding the end “ ed
” or “ ing
”: sorted ()
, reversed ()
, enumerated ()
, then we have a return value. This is a noun .Swift 2
to Swift 3
. The fact is that in Swift 2
all functions and methods that work “in place” contain the word “ InPlace
” in their name, so the sortInPlace ()
function is used for sorting by place, and the function Swift 2 in Swift 2 returns sorted array In Swift 3, as seen from the examples above, sort ()
renamed to sorted ()
, and sortInPlace ()
to sort ()
.sort ()
method has different semantics in Swift 2
and in Swift 3
. But this is not a bad thing, because if both Swift 2
and Swift 3
have a couple of functions (both with and without side effects), then the migration “robot” will brilliantly replace one name with another:Swift 2
, and one remained in Swift 3
? For example, in Swift 2
were insetInPlace
and insetBy
, and in Swift 3
was, for some reason, one - insetBy
? The migration “robot” will not help us in this case - it will leave the old name of the function - insetInPlace
- which, of course, will give an error, and we will have to fix it manually.Swift 2
with the presence of “ inPlace
” in the name require special attention when switching to Swift 3
.one()
method, which increases the size of the bbox
rectangle until it is “swallowed” by some other rectangle. This strongly simplified example has a real prototype, namely the AxesDrawer
class, which was provided in the Stanford course for drawing the axes of the graph in Task 3. It is there that the case presented below meets and had to deal with when translating the AxesDrawer
class from Swift 2.3
to Swift 3
.Swift 2
I can use the insetInPlace
method for the insetInPlace
rectangles, which will increase the size of the rectangle by dx
along the X axis and by dy
along the Y axis:insetInPlace
method, because the rectangle changes "in place".Swift 3
, then it will leave the insetInPlace
method unchanged, since there is no analog to it in Swift 3
, and we will get an error:Swift 3
there is only the insetBy
method, we apply it, the error disappears, and we are offered to change the var bbox
variable to let bbox
constant:insetBy
method insetBy
not change the rectangle “in place”, but returns a modified value, which we do not use in the while
, but this too for some reason there is no message, so a VERY DANGEROUS situation was created, when we "looped" our code forever.insetBy
value returned by the insetBy
method:let bbox
constant to the var bbox
variable, and we do this:…inPlace
when switching to Swift 3
.Swift 3
the NSFetchRequest <NSFetchRequestResult>
request to the Core Data
database has become Generic
CoreDataTableViewController
class provided by Stanford University for working with Core Data in the table is automatically provided when using the migration tool. Let's look at how this happens.Core Data
framework, then you should note that the database query, which in Swift 2
was NSFetchRequest
, in Swift 3
became Generic
NSFetchRequest <NSFetchRequestResult>
, and therefore, became Generic
and the class NSFetchResultsController<NSFetchRequestResult>
In Swift 3
they became dependent on the selectable result, which the NSFetchRequestResult
protocol should implement:NSManagedObject
objects in the Core Data
database automatically execute the NSFetchRequestResult
protocol and we can "legally" consider them as the result of a query.Swift 2
query and its execution look like this:Swift 3
we can indicate in the request the type of the result we get (in our case, Photo
), and thus avoid additional “type casting”:results
in Swift 3
, it will be [Photo]
, which will allow us to extract the Photo
attribute of the Photo
database object:Swift 3
, then we would get a code in which the result of the selection of results
is determined only by the fact that it must perform the NSFetchRequestResult
protocol:as ? [Photo]
as ? [Photo]
to retrieve the unique
attribute of a Photo
database object. We see that the migration “robot” is again trying to “slip” a more generalized solution, quite workable, but less effective and less “readable” than the above “manual” version. Therefore, after the work of the migration "robot" we will have to edit the code manually.Core Data
, where the migration “robot”, working as shown above, offers a brilliant code in Swift 3
. This is the NSFetchResultsController
class, which in Swift 3
as well as the NSFetchRequest
request became Generic
, that is, NSFetchResultsController<NSFetchRequestResult>
. As a result, some difficulties arose when using the fantastically convenient class CoreDataTableViewController
, which was developed at Stanford, in Swift 3
.CoreDataTableViewController
class CoreDataTableViewController
. When you have a huge amount of information in the database, the Table View
is an excellent means of displaying this information. In 99% of cases, either the Table View
or the Collection View
used to display the contents of large databases. And it is so common that Apple provided us in iOS with an excellent NSFetchedResultsController
class that “ NSFetchRequest
” an NSFetchRequest
request to a UITableView
table.NSFetchRequest
returns new results and the table is updated. So the database can change “behind the scenes”, but the UITableView
table always remains in sync with it.NSFetchResultsController
provides us with methods of the UITableViewDataSource
and UITableViewDelegate
protocols, such as numberOfSectionsInTableView
, numberOfRowsInSections
, etc. The only method that it does not implement is cellForRowAt
. You yourself will have to implement it, because to implement the cellForRowAt
method, cellForRowAt
need to know the custom UI for the table cell, and you are the only one who knows what data and how it is placed on the screen. But as for the other methods of the UITableViewDataSource
protocol, even such as sectionHeaders
and everything else, the NSFetchedResultsController
takes over.NSFetchResultsController
?request
, configure its predicate and sort, and the NSFetchResultsController
will NSFetchResultsController
output to the table.NSFetchResultsController
also monitors all changes in the database and synchronizes them with the Table View
.NSFetchResultsControllerDelegate
, whose methods you are requested to copy without change from the documentation to your class.NSFetchResultsController
is easy, but it turns out that I have to implement the delegate methods of NSFetchResultsControllerDelegate
?” - you think.CoreDataTableViewController
.NSFetchResultsController
documentation, but also rewritten from Objective-C
to Swift
.UITableViewController
inherit all the functionality NSFetchResultsController
, you just have to make CoreDataTableViewController
your superclass and define it public var
with a name fetchedResultsController
. You set this variable, and CoreDataTableViewController
will use it to answer all questions UITableViewDataSource
, as well as the delegate NSFetchedResultsController
who will track the database changes.var fetchedResultsController
andcellForRowAt
.CoreDataTableViewController
, we create NSFetchResultsController
using an initializer, which includes a query as an argument request
, and then assign it to a variable var
with a name fetchedResultsController
. As soon as you do this, the table with the list of photos will automatically update ( Swift 2
):cellForRowAtIndexPath
( Swift 2
):Swift 2
, but the Swift 3
query has NSFetchRequest<NSFetchRequestResult>
become Generic
, and therefore has become a Generic
class NSFetchResultsController<NSFetchRequestResult>
.public var
with the name fetchedResultsController
with which we work in CoreDataTableViewController
, also became Generic
in Swift 3
after the application of the migration "robot":CoreDataTableViewController
must be done Generic
, but we will not do this, because its subclasses, for example, such as the one above PhotosCDTVC
, are used on storyboard
, and the classes storyboard
do not work Generic
.CoreDataTableViewController
extremely convenient and allows you to avoid duplication of code in all Table View
working c Core Data
?PhotosCDTVC
in the part of the definition of a variable with a name fetchedResultsController
in which the result of the selection in the query is determined only by the fact that it must perform the protocol NSFetchRequestResult
( Swift 3
):fetchedResultsController
in our superclass requires CoreDataTableViewController
, that is, in fact, “robot” performed “type casting” UP (upcast) of our result of selecting a database object Photo
before NSFetchRequestResult
. It is clear that we will get the result of the type sampling NSFetchRequestResult
, so when it comes time to work with a real object Photo
in the cellForRowAt
migration method , the robot performs the opposite operation - “casting of the type” DOWN (downcast) - with the help of the operator as?
( Swift 3
):CoreDataTableViewController
migration “robot” worked perfectly. You do not need to change or supplement anything.#selector
, getter:
setter:
Objective-C .Swift 3
#selector
, Objective-C
, , setter
getter
.Swift
, Core Data
, public API var coreDataStack
:AppDelegate
— Objective-C setter
setCoreDataStack
Swift
coreDataStack
. raywenderlich.com :setCoreDataStack
that is clearly not in the application. This code remained until I decided to switch to Swift 3
. What was my surprise when I discovered how delicate the migration “robot” managed with this code — he used the syntax #selector
with an argument unfamiliar to me setter
:#selector
and I found a wonderful article “Hannibal #selector” .Swift 3
You will receive a warning if you do not use the return value of the function Void
.Swift 2
, Void
. . , , @warn_unused_result
. , , , . , sortInPlace
.Swift 3
. , , . , Swift 3
@discardableResult
.Swift 2
:[UIViewController]?
. , , , _
():Swift 2
Swift 3
— . , , , . , Swift 2.0
. «» Xcode 8.1
8.2
Swift 3
. , Swift 3
, - , Swift 2
, «». , .Source: https://habr.com/ru/post/316320/
All Articles