
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 → privateOptional 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_onceQOS_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 GenericCoreDataTableViewController 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 .UITableViewControllerinherit all the functionality NSFetchResultsController, you just have to make CoreDataTableViewControlleryour superclass and define it public varwith a name fetchedResultsController. You set this variable, and CoreDataTableViewControllerwill use it to answer all questions UITableViewDataSource, as well as the delegate NSFetchedResultsControllerwho will track the database changes.var fetchedResultsControllerandcellForRowAt.CoreDataTableViewController, we create NSFetchResultsControllerusing an initializer, which includes a query as an argument request, and then assign it to a variable varwith 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 3query has NSFetchRequest<NSFetchRequestResult>become Generic, and therefore has become a Genericclass NSFetchResultsController<NSFetchRequestResult>.public varwith the name fetchedResultsControllerwith which we work in CoreDataTableViewController, also became Genericin Swift 3after the application of the migration "robot":
CoreDataTableViewControllermust 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 storyboarddo not work Generic.CoreDataTableViewControllerextremely convenient and allows you to avoid duplication of code in all Table Viewworking c Core Data?PhotosCDTVCin the part of the definition of a variable with a name fetchedResultsControllerin which the result of the selection in the query is determined only by the fact that it must perform the protocol NSFetchRequestResult( Swift 3):
fetchedResultsControllerin our superclass requires CoreDataTableViewController, that is, in fact, “robot” performed “type casting” UP (upcast) of our result of selecting a database object Photobefore 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 Photoin the cellForRowAtmigration method , the robot performs the opposite operation - “casting of the type” DOWN (downcast) - with the help of the operator as?( Swift 3):
CoreDataTableViewControllermigration “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 :
setCoreDataStackthat 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 #selectorwith an argument unfamiliar to me setter:
#selectorand I found a wonderful article “Hannibal #selector” .Swift 3You 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