> On Mar 25, 2017, at 11:46 PM, Brent Royal-Gordon via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> On Mar 24, 2017, at 10:09 AM, Douglas Gregor <dgre...@apple.com> wrote:
>> 
>>> I'm actually not worried about methods so much as properties. KVC is 
>>> completely untyped on the Objective-C side, and there are several different 
>>> mechanisms there which use KVC with poorly validated external strings, like 
>>> bindings, sort descriptors, and predicates. Tons of migration errors are 
>>> going to escape into production if we do this,
>> 
>> We can avoid these by migrating conservatively (have the migrator add @objc 
>> everywhere it’s inferred in Swift 3).
> 
> We can do that, but personally, I really hate these kinds of conservative 
> migrations. It might be unavoidable, though.
> 
>>> Have you considered a deprecation cycle (for instance, having Swift 4 
>>> thunks log a warning that they're going away in Swift 5)?
>> 
>> I think Swift 3 -> Swift 4 is the deprecation cycle, no?
> 
> But there was no indication during Swift 3 that this feature was going away. 
> As I understand it, a deprecation cycle introduces advanced warning of a 
> change so you have time to prepare for it; that's not available here.
> 
> My concern is that, because the tools are not really aware of KVC, we can't 
> count on the compiler to lead developers to missing `@objc` properties. Folks 
> are only going to find those mistakes through testing, and they're inevitably 
> going to miss a few spots. So some poor schmuck is going to migrate their 
> code to Swift 4 without realizing this is an issue at all, accidentally miss 
> a few spots in their testing, ship it, and have to deal with weird crashes 
> out of nowhere. They're going to say, "My code worked just fine before. Swift 
> 4 broke it!" And they won't be wrong.
> 
> I'd be more comfortable with a version-long deprecation cycle that gave 
> developers plenty of time to notice these bugs. Failing that, I'd at least 
> like to see them get backtraces containing a symbol name like 
> `YouCantInvokeASwiftMemberThroughTheObjectiveCRuntimeUnlessItsMarkedWithAtObjc`
>  so the nature of the problem and its solution will be more obvious. 
> (Preferably, this function would log the instance and selector, so if people 
> got both the logs and the backtrace, the diagnosis would be as simple as we 
> can make it.)
> 
> (Actually, I wonder if we could install a `-doesNotRecognizeSelector:` 
> override in Swift classes which looked for a matching member in the Swift 
> runtime metadata and, if it found one, called the `YouCantInvoke…` function? 
> That would be lower overhead than generating stubs at compile time, and the 
> slowness of searching the runtime metadata wouldn't matter much since it was 
> going to crash anyway. I'm not sure if it might remove useful information 
> from the backtrace, though. Maybe in Swift 5, when these bugs will be more 
> rare. Or maybe in `SwiftObject`.)
> 
>> Plus, inheritance from an Objective-C class is often incidental: you do it 
>> because you need an NSObjectProtocol conformance, or something else expects 
>> NSObject. I haven’t heard of developers inheriting from NSObject solely to 
>> get @objc inference for their members.
> 
> You do it because you need a particular object to interact with Objective-C. 
> In that circumstance, I don't think the compiler is wrong to assume that you 
> want to expose as many members as possible to Objective-C.

In my experience, there are two types of projects nowadays (in regards to 
Swift-ObjC interop):

1) New projects that are generally pure Swift or include some ObjC files as a 
bridge for interaction with C++ or some other stuff Swift can't currently do. 
In such case, the NSObject inheritence is usually due to the NSObjectProtocol 
requirement defined by most delegates in Cocoa (Touch). In such cases, you're 
usually expecting just the delegate methods to be exposed to the ObjC runtime.

2) Projects with mixed Swift/ObjC code, where you usually really need to expose 
as many members to ObjC as possible. As you need to communicate with your 
objects from ObjC, you need to indeed have most declaractions as @objc.

As it is, however, just the public API and it's usually just a temporary fix, 
I'm personally fine with marking them as @objc. By "temporary fix" I mean that 
with the future ahead, the ObjC code will eventually get rewritten to Swift, so 
it's a fix as long as you need to expose the API to ObjC.


All things considered, I do agree that it's a huge change that would come too 
quickly and would agree on deprecating this in Swift 4 and removing in Swift 5.

Please keep in mind that for a one-person team such as myself, testing of e.g. 
5 apps thoroughly simply takes a lot of time and as the releases of Swift are 
usually (or have been historically) in line with releases of new OS versions, 
there's a lot of pressure during those months leading to these releases on 
developers and postponing this change while giving them the tools (deprecation 
messages, breakpoint symbols) would IMHO help a lot.


> 
>>> you already have to specify `dynamic` to avoid optimizations;
>> 
>> Conceptually, ‘dynamic’ is orthogonal to ‘@objc’. In today’s implementation, 
>> we can only implement ‘dynamic’ via the Objective-C runtime, hence this 
>> proposal’s requirement to write both.
> 
> I understand that, but again, I think it's defensible for the compiler to 
> assume that, if you want dynamic behavior in a class where you've already 
> enabled Objective-C interop, you probably want that dynamic behavior to be 
> compatible with Objective-C.
> 
> I guess we just take different standpoints on Objective-C interop. My belief 
> is that, if you state an intention to have a type interoperate with 
> Objective-C, Swift should try to expose as many of its members to Objective-C 
> as possible. I think you believe that Swift should expose as *little* as 
> possible to Objective-C.
> 
> Because of that difference, I actually think I'd be *more* likely to support 
> removing inference by requiring an explicit `@nonobjc` on members of 
> Objective-C-compatible classes which aren't compatible with Objective-C. That 
> is, writing:
> 
>       class Foo: NSObject {
>               var bar: Int?
>       }
> 
> Is an error; you have to write:
> 
>       class Foo: NSObject {
>               @nonobjc var bar: Int?
>       }
> 
> I don't really like that answer very much, but I like it more than I would 
> like requiring `@objc` if `bar` were a plain `Int`.
> 
>>> Would you like the request for bridging notarized and filed in triplicate?
> 
> (By the way, in reading this later, I realized this part might have sounded a 
> little too angry. I was trying to be funny. Nobody complained, but I'm sorry 
> if I missed the mark here.)
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to