profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/bjhomer/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.

bjhomer/HSImageSidebarView 280

A view based on the sidebar in Apple's Keynote app for iPad.

bjhomer/HSCountingInputStream 48

A simple example of an NSInputStream subclass that will work correctly with NSURLRequest and CFHTTPMessageRef

bjhomer/HSBackspaceFriendlyTextField 12

A UITextField subclass that will tell you when the user hits the backspace key at the start of the field.

bjhomer/Demos 8

Random little projects that don't need their own repo

bjhomer/JSTokenField 7

An iOS token field based on the behaviour and functionality provided by Mail.app's email recipient field.

bjhomer/NotificationWatcher 2

A Mac OS X application that monitors all workspace and distributed notifications

bjhomer/safari-json-formatter 2

A Safari extension which makes valid JSON documents human-readable.

bjhomer/JSONView-for-Chrome 1

JSONView for Chrome

bjhomer/myfirstapp 1

Just playing with stackmob. Nothing interesting here.

push eventAutomattic/Automattic-Tracks-iOS

BJ Homer

commit sha d923cb3a0ecece12d87efdfd20172d1e5f2b756f

Merge pull request #186 from Automattic/bjhomer/swift-package-manager Add support for Swift Package Manager

view details

BJ Homer

commit sha c028613b0e87acac64bed1f152dcdfa096d45193

Merge branch 'develop' into johnny/fix-watch-session

view details

push time in 3 days

pull request commentAutomattic/Automattic-Tracks-iOS

Prevent tracks from stealing our watch connectivity session

Context: Tracks was unconditionally setting the WCSession's delegate, even though Day One already had one. This was causing a loss of functionality in Day One's watch app.

johnnydhicks

comment created time in 3 days

push eventAutomattic/Automattic-Tracks-iOS

BJ Homer

commit sha e38635ab1e6a1e5a2a025e7a99972e75e2804be9

Switch dependencies from Cocoapods to Swift Package Manager

view details

BJ Homer

commit sha 79e53d62534bf94064ae62576d95eb0f1658c90b

Adjust Sentry import to work with modules

view details

BJ Homer

commit sha fae1b2dc908b2eef6d7620aee4190ac97644c784

Remove OCMock as a SPM dependency, add it as an XCFramework. This is OCMock 3.8.1, downloaded from ocmock.org and built into an xcframework using the following command: ```bash xcodebuild -create-xcframework -framework OCMock/iOS/OCMock.framework -framework OCMock/Mac/OCMock.framework -output OCMock.xcframework ``` We were previously pulling in OCMock using Cocoapods, but we are migrating from that to Swift Package Manager. However, OCMock uses unsafe flags in its SPM package manifest, and Xcode 12.5 does not allow dependencies on a package with unsafe flags in its manifest. (Xcode 13 does, so long as you pin to a particular commit, but as of this writing Xcode 13 is still in beta.)

view details

BJ Homer

commit sha 63d5c11902a127bc33ae7f3dd6882169563619b5

Don't build tests unless we're doing the test action. Because tests don't run on iOS devices, our OCMock xcframework doesn't include a slice for physical devices. That means that the tests fail to compile if you're building them for an iOS device destination. But we don't need that anyway, because Xcode already prevents the tests from running in that case.

view details

BJ Homer

commit sha 604ecf4503865b9fb8d27da24b9e3e5a994a8c34

Fix a test to actually test something.

view details

BJ Homer

commit sha f761f6ca6617a52a163fc010443bedce0e7717b2

Standardize Tracks.framework headers

view details

BJ Homer

commit sha 05dec3e9fc26bb8387752ee0ae7178cab302b2fa

Split the library into a few separate targets, and reorganize the file structure accordingly.

view details

BJ Homer

commit sha 96381f5464044188c2c0d451122fc0d3419e197f

Start consolidating targets.

view details

BJ Homer

commit sha 584d54ad440778f505e34dd3fe9336fc9ae06c48

Add tests to SPM manifest

view details

BJ Homer

commit sha ef25da63a3454a3c7aaaa27418b6eb46fcf36337

Get TracksDemo compiling using SPM. Cocoapods have been removed from the demo app.

view details

BJ Homer

commit sha 4f2046bae5535bce3f94d2993c897985fbe890cb

Delete unnecessary dependencies!

view details

BJ Homer

commit sha 654f9f1ea6b34aebcf681fbbe116c9efdd2a9877

Make AutomatticExperiments a dependency of TracksService, so it can update it. This preserves backward-compatibility with everyone already using Tracks.

view details

BJ Homer

commit sha b8d6d8552e4860fccd0e1141803c89f9085ee9b4

Update Podspec to _hopefully_ still work

view details

BJ Homer

commit sha c9a8a560b3df72fdb0ac76a62ca3f526885eb76d

Make Tracks still work for Cocoapods.

view details

BJ Homer

commit sha 8a9138db3503f457211ee987e9469e7100b7a593

Update Readme.

view details

BJ Homer

commit sha 3cfaf4f37e4f58ea90e986b05d4806d4e1db1642

Rename ABTesting to Experiments

view details

BJ Homer

commit sha f54988ee34aa5040292bf33831c96d1e5b5ff5c4

Reimplement a small bit of ObjC in Swift. This prevents us from needing an entirely separate module for just one ObjC file.

view details

BJ Homer

commit sha 396f8fcb70d782c5a281b1bfec5a0f0665b65458

Fix a test that was failing under SPM

view details

BJ Homer

commit sha 3dadc0b01d10d5a9899ce897946977e8be649fd8

Rename the library product to "AutomatticTracks". Calling it "AutomatticTracksiOS" felt wrong, since it also works on Mac.

view details

BJ Homer

commit sha 2dd75d8806ac11ed94043c90bf256774f9e90ae3

Remove unused xcodeproj file.

view details

push time in 3 days

delete branch Automattic/Automattic-Tracks-iOS

delete branch : bjhomer/swift-package-manager

delete time in 3 days

PR merged Automattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

This PR adds support for Swift Package Manager!

Don't be scared off by the huge number of changes. The majority of the deletions are removing the old .xcodeproj package that is no longer needed, and the majority of the additions are in the new Package.swift file that describes the package structure.

A few highlights to help guide you through this PR:

Source compatibility

This should be fully source-compatible with anyone using Tracks via Cocoapods. (Please check me on that, though!) And switching an existing project over to SPM from Cocoapods should be as simple as adding the SPM dependency and removing the Cocoapod. No code changes should be required.

Organizational changes

When built under SPM, the single "AutomatticTracks" library has now been split into multiple separate modules that implement the various pieces of functionality

  • AutomatticTracksEvents for reporting events
  • AutomatticExperiments for running A/B tests using ExPlat
  • AutomatticRemoteLogging for uploading app logs and crash logs
  • AutomatticCrashLoggingUI for displaying crash logs in a SwiftUI view
  • AutomatticTracks imports all of the above

There are also a couple other modules that just implement shared code: AutomatticTracksModel and AutomatticTracksModelObjC. These aren't very useful on their own, but it seemed useful to pull out the common code.

If you're using the library via Cocoapods, we still just expose import AutomatticTracks as before, so there should be no source changes needed there.

Directory structure

The directory structure has also changed. SPM really wants all files of a single target to belong to a single directory. Because SPM can't have Swift and ObjC code in the same target, I had to make some changes anyway, and since I was doing so, I decided to bring them more in line with what SPM would usually produce. Here's a rough overview of the changes:

  • Before: Screen Shot 2021-07-27 at 9 16 50 AM
  • After: Screen Shot 2021-07-27 at 9 17 12 AM

Most of those loose files have just been deleted, as they were unnecessary.

Other changes of note.

  • The README has been updated to explain how to install using SPM.
  • The "Reachability" dependency has been removed. It was using deprecated technology, which is now implemented using nw_path_monitor.
  • I've commented inline on other changes, where relevant.
+1216 -2938

11 comments

136 changed files

bjhomer

pr closed time in 3 days

pull request commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

Great, I'm gonna merge it!

bjhomer

comment created time in 3 days

pull request commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

I've added .swiftpm/xcode to the gitignore, and I've committed the IDEWorkspaceChecks plist file.

I'm on Xcode 13 b5 instead of b4, so it's possible the SPM looping behavior is related to that… but I wouldn't put my hopes on that.

bjhomer

comment created time in 13 days

push eventAutomattic/Automattic-Tracks-iOS

BJ Homer

commit sha 731adc2c513a2a89f14dbe725159c53e1e455089

Update gitignore and add Xcode-generated file

view details

push time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>-	<key>IDEDidComputeMac32BitWarning</key>+	<key>com.apple.security.app-sandbox</key>

I don't object to checking in the IDEChecks file for the demo project, though.

bjhomer

comment created time in 13 days

PullRequestReviewEvent

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>-	<key>IDEDidComputeMac32BitWarning</key>+	<key>com.apple.security.app-sandbox</key>

Ah, yep. Opening the .xcodeproj file directly is the expected way to run the demo project; the Package.swift file doesn't reference it at all. (Which makes sense, because users of the library don't need to know about it.)

If you want to just open the library code, you can double-click on the Package.swift file, and it will open the whole Swift Package structure in Xcode.

bjhomer

comment created time in 13 days

PullRequestReviewEvent

pull request commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

@mokagio

Is it just me? I'm approving this under the assumption that it's just me.

I am not seeing that repeated package resolution thing, either in Xcode 12.5 or in Xcode 13 betas. So either it's just you, or maybe you're using a different version of Xcode than the ones I've tested on.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 final class ApplicationFacade {  #if os(iOS) +private extension UIApplication {+    // When compiling with Swift Package Manager, it wants us to+    // use only extension-safe API. We still want to use UIApplication+    // when it's available, while not using extension-unsafe API+    // when not available. So we're going to be sneaky about getting+    // `UIApplication.shared`, but only when it should already be safe.+    static var sharedIfAvailable: UIApplication? {++        guard Bundle.main.bundleURL.pathExtension != "appex"+        else { return nil }++        let sharedAppSelector = Selector(("sharedApplication"))+        if let appClass = NSClassFromString("UIApplication"),+           let performableClass = (appClass as Any) as? NSObjectProtocol,+           performableClass.responds(to: sharedAppSelector),+           let performResult = performableClass.perform(sharedAppSelector),+           let app = performResult.takeUnretainedValue() as? UIApplication {++            return app+        }+        return nil

I ended up having this implemented twice (once in Swift, once in ObjC), so I'm just going to remove this one and reuse the one that already exists at a lower layer.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 final class ApplicationFacade {             return "unavailable"         } -        return UIApplication.shared.applicationState.descriptionForEventTag+        if let app = UIApplication.sharedIfAvailable {+            return app.applicationState.descriptionForEventTag+        }+        else {+            return "unavailable"+        }

I'll do that.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 - (void)setRemoteCallsEnabled:(BOOL)remoteCallsEnabled  */ - (void)updateDeviceInformationFromReachability {-    self.deviceInformation.isWiFiConnected = self.reachability.isReachableViaWiFi;-    self.deviceInformation.isOnline = self.reachability.isReachable;+    if (self.networkPath != nil) {+        nw_path_status_t pathStatus = nw_path_get_status(self.networkPath);+        self.deviceInformation.isWiFiConnected = nw_path_uses_interface_type(self.networkPath, nw_interface_type_wifi);+        self.deviceInformation.isOnline = (pathStatus == nw_path_status_satisfied || pathStatus == nw_path_status_satisfiable);+    }+    else {

Is there a specific style guide I should be following here? I generally refer the style I've used here; I find it a bit easier to read. But I don't feel strongly enough to push back if there's already a consensus on doing it as you suggested.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 class CrashLoggingTests: XCTestCase {     func testWhenRunningOniOSThenEventsAreSentWithApplicationState() throws {         let crashLogging = try CrashLogging(dataProvider: mockDataProvider).start()         let event = crashLogging.beforeSend(event: Event(level: .debug))+        #if SWIFT_PACKAGE+        // When building for SPM, there is no active application for the tests.+        XCTAssertEqual("unavailable", event?.tags?["app.state"])

Yeah, I found that when running tests via swift test, a bunch of stuff didn't work because there was no simulator and no app context. I had to change the CI tests to run via xcodebuild still (which I didn't realize was possible at first.) So this change does fix one failure in when running tests via swift test, but isn't sufficient to make them fully succeed in that mode.

I'm fine taking this out if we don't feel like it's useful.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 import XCTest import Sentry +#if SWIFT_PACKAGE+@testable import AutomatticTracksModel+@testable import AutomatticRemoteLogging+#else @testable import AutomatticTracks+#endif  class CrashLoggingTests: XCTestCase {      private var mockDataProvider = MockCrashLoggingDataProvider()      override func setUp() {         mockDataProvider.sentryDSN = validDSN+        UserDefaults.standard.setValue(true, forKey: "force-crash-logging")     }      override func tearDown() {         mockDataProvider.reset()+        UserDefaults.standard.removeObject(forKey: "force-crash-logging")

Yeah, I'll do that.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

+//+//  File.swift+//  +//+//  Created by BJ Homer on 7/27/21.+//+

Depending on how soon we're willing to support Xcode 13 in CI builds, we may be able to just remove this workaround altogether. But if we need to support Xcode 12 in CI builds for a while, then yeah, a comment here would make sense.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>-	<key>IDEDidComputeMac32BitWarning</key>+	<key>com.apple.security.app-sandbox</key>

The checks file was removed when I removed the entire .xcworkspace file. It's no longer needed, since Package.swift now serves as the project structure. You can see the commit where it was removed here.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

+import Foundation+

I think you're right.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

+//+//  SentryClient+Shim.swift+//  AutomatticTracksiOS+//+//  Created by BJ Homer on 7/27/21.+//++import Foundation

We are using things like object.responds(to selector:) from Foundation. That's going to be imported transitively, though, so you're right that we probably don't actually need this one.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

+@import Foundation;++NS_ASSUME_NONNULL_BEGIN++@protocol TracksLoggingDelegate <NSObject>++- (void)logError:(NSString *)str;+- (void)logWarning:(NSString *)str;+- (void)logInfo:(NSString *)str;+- (void)logDebug:(NSString *)str;+- (void)logVerbose:(NSString *)str;++@end++// Free functions for logging through the TracksLogging delegate.+void TracksLogError(NSString *str, ...) NS_FORMAT_FUNCTION(1, 2);+void TracksLogWarn(NSString *str, ...) NS_FORMAT_FUNCTION(1, 2);+void TracksLogInfo(NSString *str, ...) NS_FORMAT_FUNCTION(1, 2);+void TracksLogDebug(NSString *str, ...) NS_FORMAT_FUNCTION(1, 2);+void TracksLogVerbose(NSString *str, ...) NS_FORMAT_FUNCTION(1, 2);+++@protocol TracksLoggingConfiguration <NSObject>+@property (class, nullable) id<TracksLoggingDelegate> delegate;+@end+++/**+ There's some funny layering going on here. We want to+ expose the `TracksLogging` class publicly, and that works+ better if we define it in Swift. If we define it in ObjC,+ then it doesn't get re-exported when we do+ `@_exported import AutomatticTracksModelObjC` in Swift,+ because @_exported only re-exports Swift symbols. So then+ all clients end up having to `import AutomatticTracksModelObjC`,+ which isn't really a great experience. So we want to define+ it in Swift++ However, because the ObjC code needs to be able to *use* the+ logging delegate, we need to somehow get access to it from+ a layer higher.++ So what we're doing is having the ObjC code load the Swift+ class using NSClassFromString, and then verify that it+ conforms to the expected protocol. This is effectively+ "reaching up" one layer to access it, but it solves our+ symbol exporting problem.+ */

I did have an Apple employee mention in a private conversation that @_exported is supposed to export ObjC symbols as well, but that doesn't seem to be working.

bjhomer

comment created time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

 extension CrashLogging {     } } -// MARK: - Event Logging-extension Event {+internal extension TracksUser {

Yeah, internal is the default. I sometimes do this just to make it clear to the reader that these methods are not being exposed publicly.

bjhomer

comment created time in 13 days

PullRequestReviewEvent

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

+import Foundation

Nope, not required. I'll remove it.

bjhomer

comment created time in 13 days

PullRequestReviewEvent

push eventAutomattic/Automattic-Tracks-iOS

BJ Homer

commit sha 9eba0c59db39c6537a6c2e3a056dfd2e8fb6af49

Apply more suggestions from code review

view details

push time in 13 days

push eventAutomattic/Automattic-Tracks-iOS

BJ Homer

commit sha 601366136b601fac6169159f81840da6a31d7121

Apply suggestions from code review Co-authored-by: Gio Lodi <giovanni.lodi42@gmail.com>

view details

push time in 13 days

Pull request review commentAutomattic/Automattic-Tracks-iOS

Add support for Swift Package Manager

+// swift-tools-version:5.3+// The swift-tools-version declares the minimum version of Swift required to build this package.++import PackageDescription++let package = Package(+    name: "AutomatticTracksiOS",+    platforms: [.macOS(.v10_14), .iOS(.v12)],+    products: [+        // Products define the executables and libraries a package produces, and make them visible to other packages.+        .library(+            name: "AutomatticTracks",+            targets: ["AutomatticTracksEvents",+                      "AutomatticRemoteLogging",+                      "AutomatticExperiments",+                      "AutomatticCrashLoggingUI",+                      "AutomatticTracksModel",+                      "AutomatticTracksModelObjC",+                      "AutomatticTracks",+            ]),++        // Xcode 12 has an issue where the first build after+        // cleaning fails if there is a dependency that vends+        // a binary .xcframework. We are working around this+        // on CI by first building this "_WorkaroundSPM"+        // target that _only_ builds that one dependency.+        // We ignore any failures when building this target.+        // Then we go on to build the actual product, which+        // builds correctly.

Yes, it works fine on Xcode 13. When I originally put up this PR, Xcode 13 was still a few months out so I was shooting for compatibility with Xcode 12. But since the final Xcode 13 build is likely to be coming out this week, we may be able to just drop this altogether. (On the other hand, this workaround doesn't cause any problems in Xcode 13 either.)

bjhomer

comment created time in 13 days