Creating bootable macOS backups

If you use a Hackintosh you need a good backup solution. The chance of something going wrong is a bit higher than when running macOS on an Apple computer. Any macOS update can theoretically break your installation, you can break you Clover setup by accident or you SSD might just die.

With a good backup solution you should be up and running in a few minutes after any of those problems occur. I tried a few solutions as my requirements changed.

Initial image based backups

First I decided to use CloneZilla and backup the whole macOS SSD into an image file on another HDD every week. In case of failure I would be able to restore the image file to the SSD or any new SSD and be back up and running in about 30 minutes. I basically use macOS only for work, so restoring an at most week old backup did not seem like a problem, I would then just do a git pull and all the important data would be back.

The backups worked fine, when I bought a bigger SSD for macOS and just restored the latest backup image to it and everything went fine. I had to remember to boot CloneZilla every week and do the backup, but that was not that much of a problem, it became a weekly ritual.

The problem with image base backups

The problem is that requirements change over time, most of the time after problems you did not expect before.

Size dependent on the filesystem

CloneZilla works well with HFS+, can detect used and free space. This means it only backs up the used space, so the resulting image is not as big as your SSD and the process is fast. When you change the filesystem to APFS, for example when updating to Mojave this is no longer true. CloneZilla does not support APFS so it backs it up sector by sector, the resulting image is as big as the SSD and the process is quite slow.

Inflexibility for smaller fixes

One time I updated Clover and my Hackintosh did not boot, got stuck on some error message. The problem was that the Clover installer decided not to check OsxAptioFix3Drv-64.efi by default anymore and this module got deleted.

Doing a full restore from an image seemed like a waste of time when I just needed to restore one missing file. I used Clover on my Unibeast flash drive that I keep safe and booted the Hackintosh with it. This screwed up iMessage (different serial number). I then reinstalled Clover checking OsxAptioFix3Drv-64.efi, booted backed normally and fixed iMessage.

This made me realize that image based backups are not ideal for real world problems (you probably screw up your EFI or kexts more often that your SSD dies) and I got looking for some other solution.

Bootable macOS backups

I stumbled upon Carbon Copy Cloner; a backup tool that offers bootable backups for macOS. I bought another SSD for bootable backups and got to work.

Preparing the SSD

Once you plug in the backup SSD, you need to format it to Mac OS Extended (Journaled). Do not just format the existing partition (if any already exists), format the whole drive.

[Read More]

Simple bindable "no data" placeholder for UITableView

Almost every iOS application uses UITableView to display some kind of data and in many cases the data can be missing. In such situation you typically want to display some kind of “no data” placeholder. The placeholder fills in the empty space and can tell the user what needs to be done to get the data.

There are many ways wo implement such “no data” placeholder, including using libraries like UIEmptyState. If you just need to display a simple text message, there is an really easy way to implement it yourself, as I did in a recent project.

Showing and hiding the placeholder

The easiest way to create a “no data” placeholder for UITableView is to set it as the background view. It will be shown when there is no data in the UITableView so it will not be hidden under any other wiew.

I created a simple UITableView extension to show the placeholder with a specific message

extension UITableView {
    func setNoDataPlaceholder(_ message: String) {
        let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height))
        label.text = message
        // styling
        label.sizeToFit()

        self.isScrollEnabled = false
        self.backgroundView = label
        self.separatorStyle = .none
    }
}

To hide it when no longer needed I created another extension method

extension UITableView {
    func removeNoDataPlaceholder() {
        self.isScrollEnabled = true
        self.backgroundView = nil
        self.separatorStyle = .singleLine
    }
}

With this I would have to call those two extension method manually depending on the data in the UITableView which is unnecessary manual work.

[Read More]
ios  xcode  rxswift 

Switching my Hackintosh from NVIDIA to AMD because of Mojave

When I turned my computer into a Hackintosh about 2 years ago I was using an NVIDIA GTX 660 as my GPU and it worked without any additional drivers because of built-in support in Sierra. When I later bought a 4K display I could not make the GTX 660 drive the display at 4K@60Hz in macOS, although it worked well in Windows.

NVIDIA web drivers

I decided I needed a more powerful GPU anyway to play games on the new display in Windows so I bought a GTX 1060. It worked in Sierra and High Sierra thanks to the so called web drivers; GPU drivers provided my NVIDIA on their website. Without the web drivers you get no hardware acceleration, no 4K as maximum resolution, just one display working … the whole setup is basically unusable.

Those web drivers are version specific, every time the macOS build number changes after some update you need new ones (or to use a script to patch the previous ones). This is a bit annoying, you typically have to wait a few days after every macOS update for new drivers to become available and update then.

No web drivers for Mojave

When a new major version of macOS comes out, like Mojave, you cannot use web drivers for the previous version. NVIDIA needs to release new drivers and they now cannot do it without cooperation from Apple. Citing from the NVIDIA Developer forums

Developers using Macs with NVIDIA graphics cards are reporting that after upgrading from 10.13 to 10.14 (Mojave) they are experiencing rendering regressions and slow performance. Apple fully controls drivers for Mac OS. Unfortunately, NVIDIA currently cannot release a driver unless it is approved by Apple.

Apple basically blocks NVIDIA from releasing web drivers for Mojave, that is the reason the drivers are not out even now half, a year after Mojave release. If you are for example an iOS developer, XCode 10.2, the next version of Xcode, will only run on Mojave and you will not be able to use it unless you upgrade.

AMD GPUs in Mojave

Mojave natively supports some GPUs from AMD. You can buy a RX 560, RX 570, RX 580, Vega 56 or Vega 64 and it should work out of the box, no extra drivers needed. You not even have to install Lilu or Whatevergreen.

[Read More]

Debugging iOS network traffic

When working on an iOS app you may sometimes need to inspect or debug the network traffic between the app and the server to see what exactly is going on. Or you may be just curious to see what data other apps send about you to their servers. The way to achieve this is to run a proxy on your computer and route all the traffic from your iOS device through that proxy.

mitmproxy

Mitmproxy is a free and open source interactive HTTPS proxy. The UX is not as great as in paid app like Charles, but it is still good enough.

Installing and running

You install mitmproxy from homebrew

brew install mitmproxy

and run the command line interface with a simple mitmproxy proxy command. The command line interface takes some time to get used to. If you want something simpler, run the mitmweb command to get a web interface.

Setting up the iOS device

Proxy

When you have mitmproxy or mitmweb running you now need to set your iOS device to use that proxy. On your iOS device, go to Settings | Wi-Fi and to the properties of your Wi-Fi network. Switch the HTTP Proxy to manual and set the it to the IP address of your computer running mitmproxy and port 8080.

[Read More]

Why is there a "lag" in iOS gesture detection near the edges of the screen?

A few weeks ago I encountered a strange problem when working on an iOS application that seemed really strange at first sight.

The task

The task was simple. In the chat detail screen I had to add a voice recording button next to the message input. When the user started holding the button (.touchDown) the voice recording should have started, releasing the button (.touchUpInside) should have finish the recording and sliding to side (.touchDragOutside) should have canceled the voice recording.

The message input was located in the bottom right corner of the screen when keyboard was not shown

and moved up with the keyboard

The problem

When the keyboard was visible the quick recording button worked as expected, but when the quick recording button was at the bottom of the screen there was a “lag”, a delay of about 1 second, between touching the button and the .touchDown even firing.

[Read More]
swift  ios  xcode