If you want your subscriber to finish after the first one then use .first()

If you want your subscriber to wait until the last one then finish then use .last()

If you want something in between you use .output(in:) which accepts a range to specify which posts to respond to before finishing. It’s not the most intuitive sounding name, but it does the job. Also .prefix() seems to be derived from it.


Combine makes it easy to make your subscriber auto-cancel after a timeout.

let exampleNotification = Notification.Name("com.example")
NotificationCenter.default.publisher(for: exampleNotification, object: nil)
.timeout(.seconds(3), scheduler: DispatchQueue.main)
.subscribe(Subscribers.Sink(receiveCompletion: { result in
print("completion", result)
}, receiveValue: { value in
print("value", value)
}))

There are a couple of things that might not be obvious.

  • The timeout is the amount of time after the last post. If there are zero posts then it would timeout in exactly 3 seconds (or whatever you’ve specified). But if you received a post after 2 seconds then it would timeout 3 seconds after that. It is kind of like a debounce

Do you want your app to do something in response to the user changing their dark/light mode value from the macOS System Preferences?

Use KVO on the “effectiveAppearance” property

NSApplication.shared.publisher(for: \.effectiveAppearance).sink { 
// Do something when effectiveAppearance changes value
}

Saw this in the release notes

Key-Value Observation removal facilities now employ deterministic bookkeeping methods. Cases that would have produced hard-to-diagnose crashes, especially those where KVO signals problems accessing deallocated observer pointers or observers associated with incorrect objects, now produce an exception pinpointing which observed object needs a missed removeObserver(_:) call, and by which observers. This exception was previously thrown as ‘best effort’ when KVO could detect the problem; the new deterministic bookkeeping allows it to be thrown for all cases where removeObserver(_:) is needed.

The improved determinism also allows improved Swift API handling. Instances of NSKeyValueObservation, produced by the…


As a working professional iOS developer, you have undoubtedly needed to use both Objective-C and Swift in the same package. And almost like it was fate, you would need to use global strings. Maybe this is for a user facing string or maybe it is something internal like your public key to a 3rd party API.

Regardless of the reason, global constant strings are needed and to keep Objective-C/Swift compatibility you would need to use NS_STRING_ENUM to make a group of Objective-C global strings available to Swift files. …


In a previous story I wrote about how you can use swift to make a type-safe and generic notification system that can pretty much replace all uses of NSNotification.

However, if you are working professional, chances are that your code base is a blend of Objective-C and Swift, therefore any “swift-only” features are to be avoided. There is a solution of course. We must make the api compatible with swift and objective-c! But not just compatible, we must make the swift-facing side swifty!

Objective-c supports lightweight generics which is more like annotation then generics. Swift can use the annotation to…


prefix operator ++prefix func ++(lhs: String) -> String {
return lhs + "pre"
}
postfix operator ++postfix func ++(rhs: String) -> String {
return rhs + "post"
}
var n = "0"++n++ // What will this print?

What does ++n++ create? Before you read the article for the answer or try it out in playgrounds, leave a comment down below with your answer!

Coming from a C/C++ background we had ++ and -- as prefix and postfix operators. …


Its not natively supported, so you’d have to create something on your own.

There are several solutions out there:

  1. Hacky Method
  2. Maintaining an Array of each case

And then there is my way, which is similar to Maintaining an array but I use a switch statement to guarantee that I did not miss a case. The compiler will tell me if a case is not handled by the switch

enum Planet: String {
case Mercury
case Venus
case Earth
case Mars
}
extension Planet {
static var array: [Planet] {
var a: [Planet] =…


Theres a wealth of goodies in this update. Here are some of my favorite ones

Range properties marked as IBInspectable now appear in the inspector. (31337282)

@IBInspectable var range: NSRange = NSRange(location: 0, length: 2)

They added NSRange as an ibinspectible. I made the mistake of thinking it would be Swift’s Range struct which would allow things like 0..<2, but they actually meant Obj-c’s NSRange

Interface Builder now supports connecting outlets and actions to a Swift file when the destination’s type is a protocol-typed class. (17023935)

This feature has been missing for quite some time. …


Objective-c has light weight generics that allows you to write a generic class. Suppose we had a class dedicated to processing data into a different type.

NS_ASSUME_NONNULL_BEGIN@interface NSDataProcessor <__covariant T: id> : NSObject
- (T _Nullable)processData:(NSData *)data;
@end
NS_ASSUME_NONNULL_END

A generic class like this allows us to specify that we want the data processing to return a type of NSString rather than a type of id. Xcode will help us ensure the type validity.

However, there is a bit of an elephant in the room. How would swift use this?

Derrick Ho

Creative Coder

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store