November 1, 2021

AdGuard Home on Ubiquiti Cloud Key

I have been running a filtering DNS instance on my Synology for a while as described by Gerzon on his blog, which originally was detailed on old Synology forums - but those URLs no longer work. This set up was running fine. I have used this DNS instance to host records for internal network, and I could always add some one-off blocks to it as well on as-needed basis. But I wasn't keeping it up-to-date with filter list updates, and so I was looking for a way to automate the update process.

While looking for alternative solutions (such as PiHole) I have and stumbled upon AdGuard Home package, which looked exactly what I needed, and more, with features as per-client configuration. So I have decided to give it a whirl, and install it on another host - to keep existing set up running just in case I needed a backup. UniFi Cloud Key Plus was a target for my AdGuard set up, and it was a breeze. A Reddit user has described installation steps here. With differences being, I have not yet installed a Micro SD card into Cloud Key, so I have installed it into /opt/adguard, and stored AdGuard's data in /var/opt/adguard.

mkdir /opt/adguard && cd /opt/adguard
# unzip adguard here
mkdir /var/opt/adguard
ln -s /var/opt/adguard data
# proceed with install steps

That's it! Now I can have it all: nice UI with DNS query logging capabilities, benefits of auto-updating filters, and per-client control over devices on my network on top of that. 🎉

Posted by Vadim at 5:23 PM | Comments (0) | TrackBack (0)

October 16, 2021

Aperture on macOS Big Sur 11.6

Thanks to the Tyshawn's Retroactive app, it is still possible to run Apple's Aperture app on the latest macOS versions. At the moment, I'm running Aperture on macOS Big Sur 11.6 with the help of Retroactive 1.9. It even comes with extensive deep dive article explaining how it came together. Neat!

While Retroactive has a couple of issues - primarily I see that thumbnails don't refresh as quickly and reliably as they are supposed to - but it is still pretty much usable. One issue I have noticed which wasn't mentioned is it seems that the Aperture's login item responsible for updating iCloud's photo stream has stopped working, and macOS repeatedly tries to re-open it every 10 seconds... That doesn't sound optimal.

Oct 9 00:01:16 iMac com.apple.xpc.launchd[1] (com.apple.photostream-agent[99515]): LaunchServices returned a bundle URL that does not match with the LoginItem's known association.
Oct 9 00:01:16 iMac com.apple.xpc.launchd[1] (com.apple.photostream-agent[99515]): Service exited with abnormal code: 78
Oct 9 00:01:16 iMac com.apple.xpc.launchd[1] (com.apple.photostream-agent): Service only ran for 0 seconds. Pushing respawn out by 10 seconds.

Since I am not using iCloud with Aperture, my solution was simply to disable it.

launchctl disable com.apple.photostream-agent
launchctl remove com.apple.photostream-agent

This does not stop macOS from loading it next time you reboot your mac. So to prevent it from loading next time, I've also hidden it from the OS.

cd /Applications/Aperture.app/Contents/Library/LoginItems
sudo mv PhotoStreamAgent.app PhotoStreamAgent.app.disabled
sudo chmod 700 PhotoStreamAgent.app.disabled

That was it.

Posted by Vadim at 2:19 PM | Comments (0) | TrackBack (0)

June 29, 2021

Independent watchOS Apps

Speaking of watchOS apps, it looks like developing a full fledged application running entirely on watchOS is not yet possible: there is no networking to speak of on watchOS. 😔

If you need anything beyond basic HTTP or CloudKit, the only option is to use WatchConnectivity framework to funnel all networking through the extension running on the iPhone. 😢

The only hope is that it will be added in the future.

Posted by Vadim at 6:40 PM | Comments (0) | TrackBack (0)

June 13, 2021

Finishing Failed Transactions

On the topic of regressions in minor iOS updates, there was another one a bit ago on iOS 13.4 release, as I recall. That one was in the StoreKit API, and it has changed the way how failed transactions are being processed.

Normally, you have to finish every transaction passed into your SKPaymentQueue delegate once you are done processing it, and that includes failed transactions. However that wasn't the case on iOS 13.3 and earlier releases: failed transactions did not require finishTransaction: call and were removed from the queue even if they were not acknowledged.

Starting with iOS 13.4 though, you have to acknowledge all transactions.

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

Posted by Vadim at 11:31 AM | Comments (0) | TrackBack (0)

May 4, 2021

OpenSSL on Apple Watch

I needed OpenSSL library for the project I've been meaning to start for Apple Watch. So I've checked in all the usual places, and found out that one wasn't made available yet, so I thought I'd take that on myself.

That meant compiling it for watchOS platform, and four different architectures: armv7k and arm64_32 for device, and x86_64 and arm64 for the Simulator. That last one is a new addition in Xcode 12 to support new M1 Macs. I don't have one yet, but it would help to prepare for the future.

And that presents first problem. Earlier, before M1 arrived, it was possible to combine a library built for, say, iOS platform on arm64 architecture with library built for iOS Simulator on x86_64 into single Mach-O universal binary (or "fat library"), and Xcode was able to figure out which one goes where, even though universal binary does not identify platforms for each included architecture. Now with both M1 and iOS devices running on arm64 architecture, we have two platforms with the same architecture, and it is not possible to create such universal binary at all.

So the solution is to create separate "fat libraries" for each individual platform. That means separate library for:

  • iOS,
  • iOS Simulator,
  • tvOS,
  • tvOS Simulator,
  • watchOS,
  • watchOS Simulator,
  • ... and Catalyst, of course.

This presents second problem. Previously, you'd just drop single libcrypto.a (and libssl.a, if needed) into your project, and call it a day, but now you have to figure out how to make Xcode use one file, libcrypto-iOS.a, on device, and another, libcrypto-iOS-Sim.a, on Simulator.

Solution to the second problem is new XCFramework framework format. It combines libraries for all of these platforms (and corresponding header files) into single directory, and then Xcode magically picks just the right library automatically. 🎩 It can be easily created using xcodebuild by passing it a few parameters.

Resulting script is available on GitHub, and there is also a pull request against parent repository. And below is requisite screen shot of OpenSSL library running on watchOS as a proof that it works:

WatchOS-OpenSSL.png

Posted by Vadim at 6:59 PM | Comments (0) | TrackBack (0)

April 27, 2021

Regressions on Minor iOS Updates

We've gotten used to getting new iOS version every year, and to a requisite regression cycle to make sure new iOS version has not broken anything inside the apps. In recent years though, there have been significant changes in SDK even between minor releases, and I'm not talking about feature additions, but regressions in core libraries, such as UIKit.

As one example of such regression, update from iOS 13.1 to iOS 13.2 introduced breaking change to UIAlertController. Before, it worked just fine when presented as an action sheet on iPad in compact environment on iOS 13.1 or earlier:

UIAlerController-ActionSheet-iPad.png

With iOS 13.2 and later, this is no longer the case, and running the same code results in runtime exception:

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UIAlertController: 0x7f9cc9056a00>) of style UIAlertControllerStyleActionSheet from UINavigationController (<UINavigationController: 0x7f9cca030600>). The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.'

Oh well... 😞

Posted by Vadim at 7:13 PM | Comments (0) | TrackBack (0)