Safari View Controller

In the earlier iOS versions, we had UIWebViewController - it was made to show users some web pages. In iOS9, Safari View Controller has been introduced. It has much more interesting features so that we will focus on the latter one.

As with the maps, we will need to import SafariServices framework into our app. We can do it in Rakefile:

        app.frameworks += [ 'MapKit', 'SafariServices' ]
      

Unfortunately, SFSafariViewController can't be added inside of your layout - it is a View Controller and not a view. We can subclass it in order to customize it, but we can't add it to our layout. SFSafariViewController can be opened as a modal or a usual screen.

If you want to render a web view inside of your layout, you can use UIWebView or WKWebView, but they have some downsides, for example, if a user is logged in in your app in iOS Safari, his session won't be shared with UIWebView or WKWebView, and he will have to log in twice.

In most apps it is enough to open a modal view controller with some web site (for example for authorisation, or just to display some content), and SFSafariViewController can do it well.

Let's prepare the main Table View inside tutorial_app to show the web view:

        def set_table_data
          @data = [
            {
              cells: [
                {
                  title: "Collection Views",
                }, {
                  title: "Map Views",
                }, {
                  title: "Web View",
                }
              ]
            }
          ]
        end

        # ... other HomeScreen code ...

        def tableView(table, didSelectRowAtIndexPath: index)
          if index.row == 0
            open CollectionScreen.new
          elsif index.row == 1
            open MapScreen.new
          elsif index.row == 2
            url = 'http://google.com'.nsurl
            open SFSafariViewController.alloc.initWithURL url, entersReaderIfAvailable: false
          end
        end
      
On the moment of writing, ProMotion could not work with Safari View Controllers yet, so we can't use the pretty new method to initialize a screen. So we have to use SFSafariViewController.alloc.initWithURL url, entersReaderIfAvailable: false which creates a web screen with a given URL. URL here is not a string, but an object of NSURL class. With sugarcube, you can quickly convert a usual string into the instance of NSURL just with nsurl method. You also need to be sure to use "http://" or "https://" URLs, otherwise the app will crash. As a result, next screen will be opened:

Subclassing

If you need to customize SFSafariViewController you can subclass it, and override whatever methods you would like. Let's create a WebScreen class that can be created with a WebScreen.create method. To customize URL of the screen, a developer should be able to pass it as a parameter. Let's create /app/screens/web_screen.rb:

        class WebScreen < SFSafariViewController
          def self.create(params={})
            url = params[:url]
            SFSafariViewController.alloc.initWithURL url, entersReaderIfAvailable: false
          end
        end
        
As you can see create method only calls that huge initWithURL url, entersReaderIfAvailable: false method for you. Now you should be able to create new web screens with less code:
        def tableView(table, didSelectRowAtIndexPath: index)

          # beginning of the method ...

          elsif index.row == 2
            open WebScreen.create url: "https://mova.io".nsurl

          # rest od the method ...
        end
      

Since we are finishing this chapter, let's make a commit:

        git add .
        git commit -m "Web Screen added"
      

More info on SFSafariViewController can be found on Apple Docs

Book Index | Next