Skip to content

Instantly share code, notes, and snippets.

@AliSoftware
Last active August 18, 2021 19:41
Show Gist options
  • Save AliSoftware/1d5dc559543056a9ca175ef9a580c240 to your computer and use it in GitHub Desktop.
Save AliSoftware/1d5dc559543056a9ca175ef9a580c240 to your computer and use it in GitHub Desktop.
TypeSafe copy()/mutableCopy() (NSCopying/NSMutableCopying) in Swift
import Foundation
//: Swift type-safe protocol versions of (Mutable)Copying
protocol SwiftCopying {
associatedtype NonMutableType = Self
func clone() -> NonMutableType
}
extension SwiftCopying where Self: NSCopying {
func clone() -> NonMutableType {
return self.copy() as! NonMutableType
}
}
protocol SwiftMutableCopying {
associatedtype MutableType
func mutableClone() -> MutableType
}
extension SwiftMutableCopying where Self: NSMutableCopying {
func mutableClone() -> MutableType {
return self.mutableCopy() as! MutableType
}
}
//: Some convenience wrapper for the mutableClone/clone dance
extension SwiftMutableCopying where Self.MutableType: SwiftCopying {
func mutate(using mutation: (Self.MutableType) -> Void) -> Self.MutableType.NonMutableType {
let mutableInstance = self.mutableClone()
mutation(mutableInstance)
return mutableInstance.clone()
}
}
//: Make existing types conform
// Some Foundation types (non-exhaustive)
extension NSString: SwiftCopying, SwiftMutableCopying { typealias MutableType = NSMutableString }
extension NSArray: SwiftCopying, SwiftMutableCopying { typealias MutableType = NSMutableArray }
extension NSDictionary: SwiftCopying, SwiftMutableCopying { typealias MutableType = NSMutableDictionary }
extension NSAttributedString: SwiftCopying, SwiftMutableCopying { typealias MutableType = NSMutableAttributedString }
// Can be useful for other frameworks' types too
import UserNotifications
extension UNNotificationContent: SwiftCopying, SwiftMutableCopying { typealias MutableType = UNMutableNotificationContent }
//: Usage Example
let s1: NSString = "Hello"
// Manual mutableClone/clone() dance
let s2: NSMutableString = s1.mutableClone()
s2.append(" World")
let s3: NSString = s2.clone()
print(s3) // "Hello World"
// Using convenience mutate(using:) method
let s4: NSString = s3.mutate { $0.append("!!!") }
print(s4) // "Hello World!!!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment