4

What is a bridging conversion in Swift? What does "bridging" mean?

I get a warning in the following code where I marked with a comment saying "// warning":

import UIKit
import CloudKit

let int: UInt8 = 1
let data: Data? = Data([int])
let record: CKRecord = CKRecord(recordType: "record_type")
record.setObject(data as? CKRecordValue, forKey: "field") // warning

The warning says:

Conditional downcast from 'Data?' to 'CKRecordValue' (aka '__CKRecordObjCValue') is a bridging conversion; did you mean to use 'as'?

I also have code that uses a bridging conversion:

import Foundation
import CoreData


extension Vision {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Vision> {
        return NSFetchRequest<Vision>(entityName: "Vision")
    }

    @NSManaged public var media: NSObject?

}

private var privateEntityInstance: Vision
private var privateMedia: Data? = nil

privateEntityInstance.media = privateMedia as NSObject?

where privateEntityInstance.media is an optional and privateMedia is also an optional. Would that code work, so that CoreData will save the appropriate value of the media attribute whether it be an NSObject or a nil?

daniel
  • 1,446
  • 3
  • 29
  • 65

1 Answers1

5
  • as? CKRecordValue is conditional downcast (from a less specific to a more specific type)
  • as CKRecordValue? is a bridging conversion (for example from a concrete type to a protocol or from a Swift type to its Objective-C counterpart) . This is the syntax the compiler expects.

However in Swift 5 Data conforms to CKRecordValueProtocol so you can write

let int: UInt8 = 1
let data = Data([int])
let record = CKRecord(recordType: "record_type")
record["field"] = data

It's recommended to prefer always Key Subscription record["field"] over setObject:forKey: because the latter requires the bridge cast to an object e.g.

let data = Data([int]) as NSData // or as CKRecordValue
...
record.setObject(data, forKey: "field")

And don't annotate a worse type (optional) Data? than the actual type (non-optional) Data.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • What does "bridging conversion" mean? What does "bridging" mean? – daniel Aug 01 '19 at 11:52
  • 1
    A bridge cast is a type cast on the same level in your case a concrete type to a protocol. – vadian Aug 01 '19 at 11:55
  • Ok. I get it. I think a bridge is also a cast between a Swift type and an Objective-C type. Am I correct? – daniel Aug 01 '19 at 12:03
  • 1
    Yes, I added an example. PS: If `media` is supposed to contain always raw `Data` declare it as `Data` – vadian Aug 01 '19 at 12:04
  • I set media in the xcdatamodeld file as an optional in the Data Model Inspector. That is why I also set media as optional in the Core Data Properties class that I call "Vision". Isn't that what I'm supposed to do if a value isn't required but can be nil in Core Data? – daniel Aug 01 '19 at 12:17
  • 1
    You can declare the property as optional and assign a non-optional value. There is no reason to **annotate** the type as optional. More important is to prefer Swift strong-typed `Data` over Objective-C no-type `NSObject`. The Core Data framework performs the bridge casts implicitly. – vadian Aug 01 '19 at 12:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/197353/discussion-between-daniel-brower-and-vadian). – daniel Aug 01 '19 at 14:16