>
> https://github.com/apple/swift-evolution/blob/master/proposals/0058-objectivecbridgeable.md
There are a number of things I'm not really clear on.
* * *
Consider this Objective-C API:
ObjCFizzer* myFizzer;
Which of these represents how it is imported?
var myFizzer: ObjCFizzer
var myFizzer: Fizzer
Suppose there is also a subclass (say, ObjCMutableFizzer), and we have this
Objective-C API:
ObjCMutableFizzer* mutableFizzer;
Which of these represents how it is imported?
var myMutableFizzer: ObjCMutableFizzer
var myMutableFizzer: Fizzer
On the basis of NSArray and friends, I assume they come across like this:
var myFizzer: Fizzer
var myMutableFizzer: ObjCMutableFizzer
Is that correct?
* * *
I assume that you can use casts to implicitly cross the bridge in both
directions, even when Objective-C is not involved. That is, you could write
something like this:
ObjCFizzer() as Fizzer
Is that correct?
If you can cross the bridge purely in Swift, does the object type actually have
to be @objc? Why?
If it does not have to be @objc, is this perhaps better thought of as an
`ObjectBridgeable` protocol which allows cast-based conversion of any type to
an equivalent class, and which also does Objective-C bridging if the class
happens to be @objc? (This looser definition might help us if we ever
interoperate with other object systems on different platforms.)
* * *
Suppose you have a value of type `ObjCMutableFizzer`:
let mutableFizzer: ObjCMutableFizzer = ...
Can you write `mutableFizzer as! Fizzer`? In other words, if a type is bridged
to a particular class, is it also bridged to its subclasses?
Based on the examples from Foundation, I suspect the answer is "yes".
* * *
Foundation classes can sometimes be bridged using an upcast (a plain `as`),
which cannot crash. Is this possible with ObjectiveCBridgeable? If so, how? If
not, will Foundation classes lose that ability?
If this feature can't be expressed with ObjectiveCBridgeable, is this seen as a
shortcoming we should try to overcome, or the proper design? I worry about the
unnecessary proliferation of exclamation points, especially since many style
guides strongly discourage them, which will turn this into an unnecessary
proliferation of unnecessary `if let`s.
* * *
I'm confused by a statement in the "Ambiguity and Casting" section:
2. A Swift type may bridge to an Objective-C base class then provide
different subclass instances at runtime, but no other Swift type may bridge to
that base class or any of its subclasses.
i. The compiler should emit a diagnostic when it detects two
Swift types attempting to bridge to the same ObjectiveCType.
Does this mean that each bridged class must have exactly one corresponding
Swift type? Or does it mean that if a bridged type has more than one
corresponding Swift class, an explicit cast is always needed? Or merely that it
may sometimes be needed?
There are examples in the frameworks of many types bridging to a single class.
For instance, a whole hoard of numeric types bridge to NSNumber; Swift handles
this by exposing Swift types like `[Int]` as `NSArray<NSNumber*>*`, but doesn't
do any converting when going in the opposite direction. Is that how this new
protocol works, or does it do something else?
* * *
I'm confused by the SWIFT_BRIDGED() macro. Why does it exist? Doesn't the
ObjectiveCBridgeable conformance provide all the information needed? What
happens if you don't include it? (Perhaps you get the one-way bridging behavior
seen with `NSNumber`?)
* * *
The "Resilience" section says:
Adding or removing conformance to ObjectiveCBridgeable, or changing the
ObjectiveCType is a fragile (breaking) change.
Why is this? In particular, why is adding a conformance a breaking change? That
isn't the normal rule for protocols.
* * *
Probably a stupid question, but I want to be certain since the example does
something else: There would not be some kind of circularity problem with
defining `ObjCFizzer` in terms of `Fizzer`, would there? For instance:
class ObjCFizzer: NSObject {
fileprivate var fizzer: Fizzer
fileprivate init(_ fizzer: Fizzer) {
self.fizzer = fizzer
}
var fizzyString: String? {
guard case .case1(let string) = fizzer else { return
nil }
return string
}
var fizzyX: Int? {
guard case .case2(let x, _) = fizzer else { return nil }
return x
}
var fizzyY: Int? {
guard case .case2(_, let y) = fizzer else { return nil }
return y
}
}
extension ObjCFizzer {
convenience init(string: String) {
self.init(.case1(string))
}
convenience init(x: Int, y: Int) {
fizzer = .case2(x, y)
}
}
I have a place in my code where I would like to use ObjectiveCBridgeable, but
it uses a pattern like this, so I'd like to make sure I'll be able to adopt the
feature.
* * *
In general, I feel like this proposal is written in a way which is accessible
to the people who participated in the original discussion, but not to others.
This is a proposal which contains seven uses of the word "thunk" and zero uses
(as opposed to conformances) of the proposed protocol in examples. It seems to
imply that existing bridging of Foundation types might change, but does not
explain what those changes will mean for user code. It is fundamentally an
Objective-C bridging feature, but it contains no examples of Objective-C.
In theory I think this proposal is a great idea, but in practice I understand
the specifics of it so poorly that I can't really endorse it without some
clarifications. Hopefully someone can explain things a little more clearly so
that I can lend my support, or at least give a more specific and helpful
critique.
--
Brent Royal-Gordon
Architechies
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution