Determining which frameworks use UIWebView

Apple has deprecated UIWebView and will not be accepting new apps with UIWebView starting April 2020 and app updates with UIWebView starting December 2020. If your app uses UIWebView you should replace it with WKWebView.

The check for UIWebView has already been implemented as a warning after a build submission:

ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of app updates that use UIWebView APIs starting from December 2020. See for more information.

Removing UIWebView from your app might seem quite straightforward, but you probably use some 3rd party libraries and they might also contain UIWebView. You need to find all of them and update them, if available, or replace them. This process is not exactly trivial.

If you use 3rd party libraries as code, for example via Cocoapods, you can just do a text search for UIWebView in their sources.

For example doing grep -r 'UIWebView' . in RxSwift sources prior to 5.1.0 gives you a lot of results as RxSwift has included UIWebView binding before 5.1.0.

❯ grep -r 'UIWebView' .
./RxCocoa/iOS/UIWebView+Rx.swift://  UIWebView+Rx.swift
./RxCocoa/iOS/UIWebView+Rx.swift:    extension Reactive where Base: UIWebView {
./RxCocoa/iOS/UIWebView+Rx.swift:        public var delegate: DelegateProxy<UIWebView, UIWebViewDelegate> {
./RxCocoa/iOS/UIWebView+Rx.swift:                .methodInvoked(#selector(UIWebViewDelegate.webViewDidStartLoad(_:)))
./RxCocoa/iOS/UIWebView+Rx.swift:                .methodInvoked(#selector(UIWebViewDelegate.webViewDidFinishLoad(_:)))
./RxCocoa/iOS/UIWebView+Rx.swift:                .methodInvoked(#selector(UIWebViewDelegate.webView(_:didFailLoadWithError:)))
./RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift:extension UIWebView: HasDelegate {
./RxCocoa/iOS/Proxies/RxWebViewDelegateProxy.swift:    public typealias Delegate = UIWebViewDelegate

If your 3rd party libraries come as a .framework file without sources, there is a different way to check for UIWebView.

You can use nm to get the symbols table of the executable in a .framework and do a grep there

❯ nm AWSDK.framework/AWSDK | grep -i UIWebView
                 U _OBJC_CLASS_$_UIWebView
                 U _OBJC_CLASS_$_UIWebView
0000000000002a00 S __OBJC_LABEL_PROTOCOL_$_UIWebViewDelegate
0000000000002998 D __OBJC_PROTOCOL_$_UIWebViewDelegate
0000000000002348 s l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_UIWebViewDelegate
00000000000023b0 s l_OBJC_$_PROTOCOL_METHOD_TYPES_UIWebViewDelegate
0000000000002330 s l_OBJC_$_PROTOCOL_REFS_UIWebViewDelegate
000000000000aaa0 S __OBJC_LABEL_PROTOCOL_$_UIWebViewDelegate
000000000000a858 D __OBJC_PROTOCOL_$_UIWebViewDelegate
0000000000005780 s l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_UIWebViewDelegate
00000000000057e8 s l_OBJC_$_PROTOCOL_METHOD_TYPES_UIWebViewDelegate
0000000000005768 s l_OBJC_$_PROTOCOL_REFS_UIWebViewDelegate
iOS  Xcode 

Faster way to download and install Xcode

As an iOS developer you need to periodically update your Xcode, on your own machine and on your CI/CD server if you automate your development workflow. There are multiple ways to do this so do not waste your time and use the fastest way possible.

Forget Mac App Store, use Apple Developer Portal

Installing Xcode from the Mac App Store might seem like a convenient way to do so but it is too slow and inflexible. You cannot use the Mac App Store to install multiple version of Xcode at the same time if you need them, like when testing with a Xcode beta for an upcoming iOS release. Download from the Mac App Store is incredibly slow and sometimes not even available for days after release (like 11.2.1).

The place to go is the Apple Developer Portal where you can find all the Xcode versions, including the betas.

Faster download with aria2

Downloading Xcode from the Apple Developer Portal is faster than using the Mac App Store, but it can be made even better. You just need to use the right tools.

Install aria2 from Homebrew and uses this Ruby script from Ian Dundas:

#!/usr/bin/env ruby

print "What is the URL of your Apple Downloads resource?\nURL:"
url = gets.strip

print "What is the ADCDownloadAuth cookie token:\nADCDownloadAuth: "
token = gets.strip

command = "aria2c --header \"Host:\" --header \"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\" --header \"Upgrade-Insecure-Requests: 1\" --header \"Cookie: ADCDownloadAuth=#{token}\" --header \"User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B72 Safari/602.1\" --header \"Accept-Language: en-us\" -x 16 -s 16 #{url} -d ~/Downloads"


This script downloads the given Xcode by URL from the Apple Developer Portal, but uses up to 16 separate connections to do so. You will see a significant download speed improvement.

Make sure you use the “More” site at even for downloading the latest version of Xcode.

When copying the ADCDownloadAuth cookie make sure you copy the correct value, Safari adds all kinds stuff around it when you just use “copy value”.

Faster install with xip and deleting previous Xcode first

When you install the Xcode xip file you need to extract it. You can double click it in Finder and wait or you can use

xip -x Xcode11.xip

Using xip from the command line is much faster because it does not verify the file signature like double clicking in Finder. Of course this is a potential security risk, so it is up to you to decide if it is worth it.

Another trick is not to drag the extracted to /Applications immediately but delete the existing /Applications/ first. I guess this is related to Finder first getting the list of those thousands of files in the before the update.

iOS  Swift  Xcode 

Changing UIApplication base class

When developing an iOS application you might get into a situation when you need to change the UIApplication base class. It is often a requirement when using various MDM SDKs, like the Mobile Iron AppConnect SDK. There are two ways to do that in a Swift application, both with some advantages and disadvantages.

Declarative method with Info.plist

The first method to change the UIApplication base class is using Info.plist. It is quite simple, you just need to add a new key NSPrincipalClass with a string value representing the name of the desired class, like AppConnectUIApplication when using the Mobile Iron AppConnect SDK.


No actual code changes are required.

Code method with main.swift

The second method is a bit more complicated but more flexible at the same time. First you need to remove @UIApplicationMain from your AppDelegate class definition. Then you add a main.swift to the root of your project that looks like this

import AppConnect
import UIKit


The third parameter in the UIApplicationMain call is the name of the desired class, ACUIApplicationClassName in this example.

[Read More]
iOS  Swift  Xcode 

Creating iOS context menu with highlight and dim

The iOS messaging application I work on features a context menu in the chat. You long-press any message in the chat and the context menu appears. This menu was originally implemented using the standard UIMenuController.

The UIMenuController is an old-style iOS API that is hard to use and does not work very well. In some situations tapping its items just did not call the assigned selectors and the menu did not work.

As part of the ongoing redesign of the application I decided to implement a new custom context menu that would look as the designer imagined and more importantly work reliably. I did not want to use any 3rd party library to keep it as simple and possible.

Using just UIKit I came up with a context menu with a dim effect and a highlight on the selected item

Here is how I approached building it.

[Read More]
iOS  Swift  Xcode 

Changing UIAlertAction text color

If you use the standard iOS UIAlertController to present the user with a list of actions, there is not much you can do about styling each of the UIAlertActions shown.

The text of the shown UIAlertAction uses the UIView's tint color, so you can use the UIAppearence API to change it to any color you want, but the same color for all the UIAlertActions. If you set the style to destructive instead of default, the text is shown as red, not affected by the tint color.

UIAlertController with one default and one destructive action might then look like this with dark blue set as the global tint color using UIAppearence:

The red color for the destructive option does not look that great, especially if your app uses a different shade of red everywhere else.

If you dive deep into Apple documentation you will find a KVC called titleTextColor. This KVC allows you to set exactly what you need, the color for the UIAlertAction text.

[Read More]
iOS  Xcode