Upgradation of iOS

Brief about the iOS Upgrade.

Upgrading the iOS app from iOS10/iOS11 to iOS12 is a very tedious task. Developers have to face many issues while migrating the application from iOS10/iOS11 to iOS12. There are a lot of crucial things need to understand before migrating of apps. There are lots of challenges for all the developers as well as companies who are developing the iOS application. Every year Apple releases a new IOS version due to that many app's functionalities is getting broken due to compatibility to the latest version of IOS. Many classes and method were getting deprecated due to that app functionality suddenly getting broken. All companies and developers should be cautious about this issue and need to check consistent customer reviews after updating iOS.

article

Sometimes Customer doesn’t know whether they have to upgrade the device to the latest version or not because they are not aware of the impact. As a developer we should keep reminding to the customers, not to upgrade the IOS version of the device till the apps are not tested thoroughly in the latest version of IOS. It’s highly recommended to have project managed under source control. This will allow us to easily review the changes that were applied via the migration assistant and to discard them and re-try the migration if needed.

To migrate the existing app from iOS10/iOS11 to iOS12. Most typical changes related to Swift version. If Project already develops in Objective-c language, then there is less effort is required to make changes because in Objective-c language is stable and Apple doesn’t make any changes every year. The migration provides an opportunity to revisit an existing Swift App and improve its architecture, logic, and performance by replacing pieces of it in with upgraded Swift. It provides the compatibility of a higher and lower version of iOS devices.

Every year Apple releases new iOS and Latest Swift version, then It comes with a lot of code improvements for which the best way to start is to watch the WWDC session then Some of the improvements are easy to implement in the existing code. In this article, Nex Mobility iOS App Development Company describes a simple way to migration including deprecated code replace with the new code.

Perquisite’s for iOS Upgrade

  • Apple Updated MacOS
  • Latest XCode version
  • iPad and iPhone updated to latest version
  • Updated CLI and Tool Chain for iOS

Mandatory steps to do iOS upgrade

  • Before starting the migration, Developer needs to compile the older code including test cases in the latest XCode. If any compiler error appears then it has to resolve first then the developers can proceed for the migration because the compiler won’t allow the code to migrate in latest swift version.
  • Developers need to select Legacy build system to compile the code in the XCode.

    article
  • The developer needs to install a toolchain in the latest XCode.

    article
  • The Developer needs to check the current version of the swift language in which the app initially develop. They have to select the latest version in the settings to update it and then proceed to compile the code then it will show all the deprecated, latest changes in syntax and other error related to the latest iOS.

    article
  • Developer’s essential to create it Swift inference as default because, Before Swift 4, the compiler made certain Swift declarations automatically available to Objective-C. For sample, if one subclassed from NSObject, the compiler generated Objective-C entry points for all ways in such classes. The mechanism is called @objc inference.

  • In Swift 4, such automatic @objc inference is deprecated because it is costly to create all those Objective-C entry topics. When "Swift 3 @objc Inference" setting is set to "On", it permits the old code to work. However, it will display deprecation cautions that need to address. It is recommended to "fix" these cautions and switch the setting to "Default", which is the default for new Swift projects.

    article
  • Developers can update, the code to the latest version and it will be compatible with the latest iOS. It can be done manually and partially with the XCode facility, but the app must successfully compile into the latest XCode with an error.

  • Steps to move using XCode, but it will not convert the entire code or some parts of the code, need to be manually done.

    article article

Major and Generic Code changes for iOS 12 Upgrade from iOS11/iOS10

(Objective-C/Swift to Swift 4.2)

Objective-C/Swift Swift 4.2
activityIndicatorStyle Style
addChildViewController addChild
didMove(toParentViewController didMove(toParent
MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, MKCoordinateRegion(center: coordinates, latitudinalMeters: regionDistance, longitudinalMeters:
MKMapRectIsNull MKMapRect.null.isNull
NSAttributedStringKey NSAttributedString.Key
NSLayoutAttribute NSLayoutConstraint.Attribute
NSLayoutRelation NSLayoutConstraint.Relation
NSNotification.Name.UIResponder.keyboardDidShowNotification UIResponder.keyboardDidShowNotification
removeFromParentViewController removeFromParent
UIAlertActionStyle UIAlertAction.Style
UIAlertControllerStyle UIAlertController.Style
UIApplicationLaunchOptionsKey UIApplication.LaunchOptionsKey
UIApplicationOpenSettingsURLString UIApplication.openSettingsURLString
UICollectionElementKindSectionHeader UICollectionView.elementKindSectionHeader
UICollectionViewScrollPosition UICollectionView.ScrollPosition
UIControlContentHorizontalAlignment UIControl.ContentHorizontalAlignment
UIControlState UIControl.State
UIDatePickerMode UIDatePicker.Mode
UIEdgeInsetsMake(0, 0, 0, UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
UIImagePickerControllerSourceType UIImagePickerController.SourceType
UIImageRenderingMode UIImage.RenderingMode
UIKeyboardFrameBeginUserInfoKey UIResponder.keyboardFrameBeginUserInfoKey
UITableViewAutomaticDimension UITableView.automaticDimension
UITableViewCellSeparatorStyle UITableViewCell.SeparatorStyle
UIViewAnimationCurve UIView.AnimationCurve
UIViewAnimationOptions UIView.AnimationOptions
UIViewAutoresizing UIView.AutoresizingMask
willMove(toParentViewController willMove(toParent

Before Upgrade Code:-

class func getMapRectForOverlays(_ overlays: [MKOverlay], _ flyTo: inout MKMapRect) { for overlay in overlays { if MKMapRectIsNull(flyTo) { flyTo = overlay.boundingMapRect } else { flyTo = flyTo.union(overlay.boundingMapRect) } } }

After Upgrade Code :-

class func getMapRectForOverlays(_ overlays: [MKOverlay], _ flyTo: inout MKMapRect) { for overlay in overlays { if MKMapRect.null.isNull { flyTo = overlay.boundingMapRect } else { flyTo = flyTo.union(overlay.boundingMapRect) } } }

Audio session setCategory not working in Swift 4.2 because Apple has changed some of the things in instance method so, a developer needs to add audio session category, mode, and desired options.

Before upgrade:

do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) } catch { print(error) }

After upgrade:

Please try the below code in your project

  1. First code

    do { try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default) try AVAudioSession.sharedInstance().setActive(true) } catch { print(error) }

    or

  2. Second Code

    do { if# available(iOS 11.0, *) { try audioSession.setCategory(.playback, mode: .default, policy: .longForm, options: []) } else if# available(iOS 10.0, *) { try audioSession.setCategory(.playback, mode: .default, options: []) } else { // Compiler error: 'setCategory' is unavailable in Swift try audioSession.setCategory(AVAudioSession.Category.playback)}} catch let error {print("Unable to configure audio sesson category: (error)")}
  • libMobileGestalt MobileGestalt MGIsDeviceOneOfType is not supported on this platform in iOS12 swift4.2 and app was crashing

    There will be multiple cause but in iOS12 Swift4.2 it was happening due to private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any] ? ) - > Bool { Removed the "Private" from the app delegate then it will resolve the crashing issue as well as "libMobileGestalt MobileGestalt MGIsDeviceOneOfType. MGIsDeviceOneOfType" error

  • WkWebview cookies were not generating in iOS12 swift4.2 after entering login credentials in an app, but it was generating cookies in iOS11 in header response only. When we change the code in iOS12, then it was working in both iOS11 & iOS12 devices.

    • Solution:-

    • Before Upgrade:-

      if let httpResponse = navigationResponse.response as ? HTTPURLResponse { if let headers = httpResponse.allHeaderFields as ? [String: String], let url = httpResponse.url { let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: url) print("cookies", cookies.debugDescription) for cooki in cookies {} } }
    • After Upgrade 12:-

    • Code will change and we need to add if-else condition

      if# available(iOS 11.0, *) { webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { [weak self](cookies) in for cooki in cookies {} } else { if let httpResponse = navigationResponse.response as ? HTTPURLResponse { if let headers = httpResponse.allHeaderFields as ? [String: String], let url = httpResponse.url { let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: url) print("cookies", cookies.debugDescription) for cooki in cookies {} } } }
  • Setting set image to UIImageView in Xcode 10 was not working

      Solution:-

    • Jpeg assets in asset catalogs are not found on iOS 12 or earlier for apps built with Xcode 9. So First we need to convert all JPEG Image into PNG.

  • Multiple commands produce and Copy Pods Resources error on build older code in latest Xcode 10

    • Problem:-

      Xcode throwing multiple commands produce and Copy Pods Resources error. It was not allowing to update to latest swift 4.2 Showing below Messages

      1. Multiple commands produce

        '/Users/manishagarwal/Library/Developer/Xcode/DerivedData/travel_FlyNow-cloncbemcwhmwicliovlcfadgzvq/Build/Intermediates.noindex/SwiftMigration/travel_FlyNow/Products/Debug-iphoneos/travel_FlyNow.app':

      2. Target 'travel_FlyNow' has create directory command with output

        '/Users/manishagarwal/Library/Developer/Xcode/DerivedData/travel_FlyNow-cloncbemcwhmwicliovlcfadgzvq/Build/Intermediates.noindex/SwiftMigration/travel_FlyNow/Products/Debug-iphoneos/travel_FlyNow.app'

      3. That command depends on command in Target 'travel_FlyNow'

        Script phase “[CP] Copy Pods Resources”

      Solution:-

      1. Step1 - Check cocopods file is duplicate.If it duplicate in project then delete it (remove reference) 

      2. Step2 - Remove Copy bundle resources form build phase

      3. Step3 - Go to Xcode top menu - > file -> workspace settings, changed default build system to legacy build system

    Some issue occurred related to 1 Auto readable tableview 2 Notification 3 UIControl 4 UIEdgeInsetsInsetRect 5 WebView 6 UIApplicationState

    1. Stopped auto readable width in table view from iOS12 onwards

      Table view's cellLayoutMarginsFollowReadableWidth property has changed for iOS 12 default. It was true by default in previous iOS releases but initializing in iOS 12 default is now incorrect. If you are not using the interface builder and you want to follow the cell margin to read width, then you need to set the property explicitly for iOS 12:

      tableView.cellLayoutMarginsFollowReadableWidth = true

    2. UIWebView and WebView are formally deprecated in iOS 12 so, migrate WebView to WKWebView

    3. UIControl.Event.primaryActionTriggered changed to primaryActionTriggered

      button.addTarget(self, action: #selector(flightdetails), for: UIControl.Event.primaryActionTriggered) to: button.addTarget(self, action: #selector(flightdetails), for: .primaryActionTriggered)
    4. UIEdgeInsetsInsetRect Changed in swift 4.2

      // Swift 4.0 let container = CGRect(x: 0, y: 0, width: 100, height: 100) let margin = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) let content = UIEdgeInsetsInsetRect(container, margin) // Swift 4.2 let container = CGRect(x: 0, y: 0, width: 100, height: 100) let margin = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) let content = container.inset(by: margin)
    5. Notification.Name.UIContentSizeCategoryDidChange becomes

      UIContentSizeCategory.didChangeNotification // Swift 4.0 NotificationCenter.default.addObserver(self, selector: #selector(didChangeTextSize(_:)), name: Notification.Name.UIContentSizeCategoryDidChange, object: nil) // Swift 4.2 NotificationCenter.default.addObserver(self, selector: #selector(didChangeTextSize(_:)), name: UIContentSizeCategory.didChangeNotification, object: nil)
    6. UIApplicationState is comes under the UIApplication in swift 4.2

      // Swift 4.0 let appState = UIApplicationState.active // Swift 4.2 let appState = UIApplication.State.active
  • ImagePicker Error - Cannot subscript a value of type '[String : Any]' with an index of type 'UIImagePickerController.InfoKey'

    • Solution:-

      func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

      changed to

      func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){

      Before:-

      The function defined in Swift 4.0 and it got changed in swift 4.2

      func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) { let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage let imageData = UIImageJPEGRepresentation(chosenImage, 0.5) let mediaObject = MediaObject() mediaObject.attachmentId = SIAFormats.generateVRCommentID(employeeID: AppUtilities.sharedInstance.employeeId, date: Date()) mediaObject.attachmentType = "PHOTO" mediaObject.attachmentFile = imageData?.base64EncodedString(options: []) self.mediaData.append(mediaObject) dismiss(animated: true, completion: nil) }

      After:-

      The signature of the method has changed in Swift 4.2

      func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { guard let selectedImage = info[.originalImage] as? UIImage else { fatalError("Expected a dictionary containing an image, but was provided the following: \(info)") } //let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage let imageData = selectedImage.jpegData(compressionQuality: 0.5) //let imageData = UIImageJPEGRepresentation(selectedImage, 0.5) let mediaObject = MediaObject() mediaObject.attachmentId = SIAFormats.generateVRCommentID(employeeID: AppUtilities.sharedInstance.employeeId, date: Date()) mediaObject.attachmentType = "PHOTO" mediaObject.attachmentFile = imageData?.base64EncodedString(options: []) self.mediaData.append(mediaObject) dismiss(animated: true, completion: nil) }
  • Library not found for -lstdc++.6 error on a final compilation of project during iOS12 upgrade because Apple has removed -lstdc++.6 from the older simulator.

Solution:-

  1. Either copy the libstdc++.*dylib from the iOS 11.4 simulator runtime to the iOS 12.0 simulator runtime in addition to copying the libstdc++.tbd between the SDKs or better approach is to update libc++ in place of libstdc++

  2. Building with libstdc++ was deprecated with Xcode 8 and is not supported in Xcode 10 when targeting iOS. C++ projects must now migrate to libc++ and are recommended to set a deployment target of iOS 7 or later. Besides changing the C++ Standard Library build setting, developers should audit hard-coded linker flags and target dependencies to remove references to libstdc++ (including -lstdc++, -lstdc++.6.0.9, libstdc++.6.0.9.tbd, and libstdc++.6.0.9.dylib). Project dependencies such as static archives that build against libstdc++ will also need to rebuild against libc++

  3. Add it under "Other Linker Flags" under "Linking" section of the "Build Settings" tab on your project's settings.

Read more:

  1. How to Create a Ruler Control with Swift - Part 1
  2. How to Create Sidebar View Using Third Party Library In iOS