Making copy & paste work with NSTextField

When I started working on my open-source Localization Editor, which is a macOS application, I encountered some things that were a bit strange compared to iOS development. One of those things is that copy & paste does not automatically work on a NSTextField.

To be exact, copy & paste works on a NSTextField as long as you do not delete the Edit menu from the standard Main menu. If you do that for some reason, you have to implement all the copy & paste functionality yourself.

The key to the implementation is overriding the performKeyEquivalent method and manually checking for cmd + c/v/x/z/a

final class EditableNSTextField: NSTextField {

    private let commandKey = NSEvent.ModifierFlags.command.rawValue
    private let commandShiftKey = NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue

    override func performKeyEquivalent(with event: NSEvent) -> Bool {
        if event.type == NSEvent.EventType.keyDown {
            if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandKey {
                switch event.charactersIgnoringModifiers! {
                case "x":
                    if NSApp.sendAction(#selector(NSText.cut(_:)), to: nil, from: self) { return true }
                case "c":
                    if NSApp.sendAction(#selector(NSText.copy(_:)), to: nil, from: self) { return true }
                case "v":
                    if NSApp.sendAction(#selector(NSText.paste(_:)), to: nil, from: self) { return true }
                case "z":
                    if NSApp.sendAction(Selector(("undo:")), to: nil, from: self) { return true }
                case "a":
                    if NSApp.sendAction(#selector(NSResponder.selectAll(_:)), to: nil, from: self) { return true }
                default:
                    break
                }
            } else if (event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue) == commandShiftKey {
                if event.charactersIgnoringModifiers == "Z" {
                    if NSApp.sendAction(Selector(("redo:")), to: nil, from: self) { return true }
                }
            }
        }
        return super.performKeyEquivalent(with: event)
    }
}
macos  swift 

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]

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]

Using CloneZilla for regular hackintosh backups

If you are a macOS user you may be used to Time Machine as the standard for backups. Time Machine is fine if you want to backup your files and configuration, but if for example your disk dies or your hackintosh completely breaks with some bad update, there are better and faster ways to get it up and running again.

Requirements

Basically everything comes down to your backup requirements. These are mine

  • full backup of the macOS SSD including EFI with Clover
  • backups that can be restored without any additional configuration to the current macOS SSD or a new one in case of a disk failure
  • no need for the ability to restore single files (all work data are in Git and Dropbox)
  • reasonable backup and restore speed

Looking at different backup solutions I chose Clonezilla. It is not exactly the most user-friendly solution, but it is a very powerful one if you know what you are doing.

[Read More]