Possible swift 3 method rewrite issue with NSRequestConcreteImplementation ?


(John Spurlock) #1

Minimal repro case below. I'm creating a custom NSCoder, but the
"encodeInt:forKey" call is not dispatched properly to my overridden method
when encoding an NSCalendar instance.

What am I missing here? Without source code for any of this, I'm at a dead
end.

Thanks,
- john

···

================================================

    private class FooCoder : NSCoder {
        override var allowsKeyedCoding : Bool { return true }

        override func encode(_ objv: AnyObject?, forKey key: String) {
            print("\(key) \(objv)") // called
        }

        override func encode(_ intv: Int, forKey key: String) {
            print("\(key) \(intv)") // never called
        }
    }

    func testCoder() {
        Calendar.current.encode(with: FooCoder()) // crashes at runtime,
result below
    }

Results in:

"NSInvalidArgumentException", "*** -encodeInt:forKey: only defined for
abstract class. Define -[_TtCC22Tests22TestsP33_1961FooCoder
encodeInt:forKey:]!"
(
0 CoreFoundation 0x00007fff84da34f2
__exceptionPreprocess + 178
1 libobjc.A.dylib 0x00007fff883caf7e
objc_exception_throw + 48
2 CoreFoundation 0x00007fff84e0a4bd +[NSException
raise:format:] + 205
3 Foundation 0x00007fff903ccdbd
NSRequestConcreteImplementation + 229
4 Foundation 0x00007fff9035323b
-[NSCalendar(NSCalendar) encodeWithCoder:] + 251


(Tony Parker) #2

Hi John,

Can you try this?

@objc(encodeInt:forKey:)
override func encode(_ intv: Int, forKey key: String) {
            print("\(key) \(intv)") // never called
}

- Tony

···

On Jul 18, 2016, at 12:11 AM, John Spurlock via swift-users <swift-users@swift.org> wrote:

Minimal repro case below. I'm creating a custom NSCoder, but the "encodeInt:forKey" call is not dispatched properly to my overridden method when encoding an NSCalendar instance.

What am I missing here? Without source code for any of this, I'm at a dead end.

Thanks,
- john

================================================

    private class FooCoder : NSCoder {
        override var allowsKeyedCoding : Bool { return true }
        
        override func encode(_ objv: AnyObject?, forKey key: String) {
            print("\(key) \(objv)") // called
        }
        
        override func encode(_ intv: Int, forKey key: String) {
            print("\(key) \(intv)") // never called
        }
    }
    
    func testCoder() {
        Calendar.current.encode(with: FooCoder()) // crashes at runtime, result below
    }

Results in:

"NSInvalidArgumentException", "*** -encodeInt:forKey: only defined for abstract class. Define -[_TtCC22Tests22TestsP33_1961FooCoder encodeInt:forKey:]!"
(
  0 CoreFoundation 0x00007fff84da34f2 __exceptionPreprocess + 178
  1 libobjc.A.dylib 0x00007fff883caf7e objc_exception_throw + 48
  2 CoreFoundation 0x00007fff84e0a4bd +[NSException raise:format:] + 205
  3 Foundation 0x00007fff903ccdbd NSRequestConcreteImplementation + 229
  4 Foundation 0x00007fff9035323b -[NSCalendar(NSCalendar) encodeWithCoder:] + 251
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Jacob Bandes-Storch) #3

Shouldn't that be implicit, since the function is `override`?

···

On Mon, Jul 18, 2016 at 5:25 PM, Tony Parker via swift-users < swift-users@swift.org> wrote:

Hi John,

Can you try this?

@objc(encodeInt:forKey:)
override func encode(_ intv: Int, forKey key: String) {
            print("\(key) \(intv)") // never called
}

- Tony

> On Jul 18, 2016, at 12:11 AM, John Spurlock via swift-users < > swift-users@swift.org> wrote:
>
> Minimal repro case below. I'm creating a custom NSCoder, but the
"encodeInt:forKey" call is not dispatched properly to my overridden method
when encoding an NSCalendar instance.
>
> What am I missing here? Without source code for any of this, I'm at a
dead end.
>
> Thanks,
> - john
>
> ================================================
>
> private class FooCoder : NSCoder {
> override var allowsKeyedCoding : Bool { return true }
>
> override func encode(_ objv: AnyObject?, forKey key: String) {
> print("\(key) \(objv)") // called
> }
>
> override func encode(_ intv: Int, forKey key: String) {
> print("\(key) \(intv)") // never called
> }
> }
>
> func testCoder() {
> Calendar.current.encode(with: FooCoder()) // crashes at
runtime, result below
> }
>
> Results in:
>
> "NSInvalidArgumentException", "*** -encodeInt:forKey: only defined for
abstract class. Define -[_TtCC22Tests22TestsP33_1961FooCoder
encodeInt:forKey:]!"
> (
> 0 CoreFoundation 0x00007fff84da34f2
__exceptionPreprocess + 178
> 1 libobjc.A.dylib 0x00007fff883caf7e
objc_exception_throw + 48
> 2 CoreFoundation 0x00007fff84e0a4bd
+[NSException raise:format:] + 205
> 3 Foundation 0x00007fff903ccdbd
NSRequestConcreteImplementation + 229
> 4 Foundation 0x00007fff9035323b
-[NSCalendar(NSCalendar) encodeWithCoder:] + 251
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

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


(John Spurlock) #4

Hi Tony - when I add that attribute, I get an error at compile-time:
Objective-C method has a different selector from the method it overrides
('encodeInt:forKey:' vs. 'encodeInteger:forKey:')

If I update to encodeInteger:forKey as the fix describes, it compiles, but
I'm getting the same original problem at runtime. i.e. "encodeInt:forKey:
only defined for abstract class"

Any other ideas? See the same thing over there? You should be able to
paste that into a new swift 3 test.

···

On Mon, Jul 18, 2016 at 8:25 PM, Tony Parker <anthony.parker@apple.com> wrote:

Hi John,

Can you try this?

@objc(encodeInt:forKey:)
override func encode(_ intv: Int, forKey key: String) {
            print("\(key) \(intv)") // never called
}

- Tony

> On Jul 18, 2016, at 12:11 AM, John Spurlock via swift-users < > swift-users@swift.org> wrote:
>
> Minimal repro case below. I'm creating a custom NSCoder, but the
"encodeInt:forKey" call is not dispatched properly to my overridden method
when encoding an NSCalendar instance.
>
> What am I missing here? Without source code for any of this, I'm at a
dead end.
>
> Thanks,
> - john
>
> ================================================
>
> private class FooCoder : NSCoder {
> override var allowsKeyedCoding : Bool { return true }
>
> override func encode(_ objv: AnyObject?, forKey key: String) {
> print("\(key) \(objv)") // called
> }
>
> override func encode(_ intv: Int, forKey key: String) {
> print("\(key) \(intv)") // never called
> }
> }
>
> func testCoder() {
> Calendar.current.encode(with: FooCoder()) // crashes at
runtime, result below
> }
>
> Results in:
>
> "NSInvalidArgumentException", "*** -encodeInt:forKey: only defined for
abstract class. Define -[_TtCC22Tests22TestsP33_1961FooCoder
encodeInt:forKey:]!"
> (
> 0 CoreFoundation 0x00007fff84da34f2
__exceptionPreprocess + 178
> 1 libobjc.A.dylib 0x00007fff883caf7e
objc_exception_throw + 48
> 2 CoreFoundation 0x00007fff84e0a4bd
+[NSException raise:format:] + 205
> 3 Foundation 0x00007fff903ccdbd
NSRequestConcreteImplementation + 229
> 4 Foundation 0x00007fff9035323b
-[NSCalendar(NSCalendar) encodeWithCoder:] + 251
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users


(Tony Parker) #5

Probably, but there could be a compiler bug or importer bug lurking here.

- Tony

···

On Jul 18, 2016, at 5:29 PM, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

Shouldn't that be implicit, since the function is `override`?

On Mon, Jul 18, 2016 at 5:25 PM, Tony Parker via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Hi John,

Can you try this?

@objc(encodeInt:forKey:)
override func encode(_ intv: Int, forKey key: String) {
            print("\(key) \(intv)") // never called
}

- Tony

> On Jul 18, 2016, at 12:11 AM, John Spurlock via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
>
> Minimal repro case below. I'm creating a custom NSCoder, but the "encodeInt:forKey" call is not dispatched properly to my overridden method when encoding an NSCalendar instance.
>
> What am I missing here? Without source code for any of this, I'm at a dead end.
>
> Thanks,
> - john
>
> ================================================
>
> private class FooCoder : NSCoder {
> override var allowsKeyedCoding : Bool { return true }
>
> override func encode(_ objv: AnyObject?, forKey key: String) {
> print("\(key) \(objv)") // called
> }
>
> override func encode(_ intv: Int, forKey key: String) {
> print("\(key) \(intv)") // never called
> }
> }
>
> func testCoder() {
> Calendar.current.encode(with: FooCoder()) // crashes at runtime, result below
> }
>
> Results in:
>
> "NSInvalidArgumentException", "*** -encodeInt:forKey: only defined for abstract class. Define -[_TtCC22Tests22TestsP33_1961FooCoder encodeInt:forKey:]!"
> (
> 0 CoreFoundation 0x00007fff84da34f2 __exceptionPreprocess + 178
> 1 libobjc.A.dylib 0x00007fff883caf7e objc_exception_throw + 48
> 2 CoreFoundation 0x00007fff84e0a4bd +[NSException raise:format:] + 205
> 3 Foundation 0x00007fff903ccdbd NSRequestConcreteImplementation + 229
> 4 Foundation 0x00007fff9035323b -[NSCalendar(NSCalendar) encodeWithCoder:] + 251
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org <mailto:swift-users@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Brent Royal-Gordon) #6

Hi Tony - when I add that attribute, I get an error at compile-time:
Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')

If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"

Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.

If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.

I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.

···

--
Brent Royal-Gordon
Architechies


(Tony Parker) #7

We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

···

On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

Hi Tony - when I add that attribute, I get an error at compile-time:
Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')

If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"

Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.

If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.

I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.

--
Brent Royal-Gordon
Architechies


(John Spurlock) #8

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997

Ensured it reproduces in xcode beta 3, swift version 3.0
(swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to
fix my custom NSCoder?

Thanks,
- john

···

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com> wrote:

We renamed some of these methods for Swift 3 in an attempt to remove some
of the confusion surrounding which of these did what - they were really
named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since
they were easily confused with the Swift Int type. I think we’ll have to
figure out a different approach here. John, please file a bug at
bugreport.apple.com and let me know the radar number, and we’ll look into
it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com> > wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it
overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles,
but I'm getting the same original problem at runtime. i.e.
"encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to
paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the
Swift version of the "Encoding General Data" section, and 27
(non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no
Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend
you file a radar against Foundation. If this is a primitive method for
NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>


(Brent Royal-Gordon) #9

Horrible possibility: `class_addMethod()` *is* available from Swift. You might be able to do some old-fashioned runtime hackery like:

  class MyCoder: NSCoder {
    @objc func __encodeInt(_ intv: Int, forKey: String) { ... }
    
    override class func initialize() {
      super.initialize()
      
      // XXX I think this needs to be guarded against being run more than once.
      let donor = class_getInstanceMethod(self, #selector(__encodeInt(_:forKey:)))
      class_addMethod(self, Selector("encodeInt:forKey:"), method_getImplementation(donor), method_getTypeEncoding(donor))
    }
    
    ...
  }

···

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com> wrote:

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

--
Brent Royal-Gordon
Architechies


(Tony Parker) #10

Please don’t resort to that; I’d rather fix the bug. =)

- Tony

···

On Jul 19, 2016, at 8:53 AM, Brent Royal-Gordon <brent@architechies.com> wrote:

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com> wrote:

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Horrible possibility: `class_addMethod()` *is* available from Swift. You might be able to do some old-fashioned runtime hackery like:

  class MyCoder: NSCoder {
    @objc func __encodeInt(_ intv: Int, forKey: String) { ... }
    
    override class func initialize() {
      super.initialize()
      
      // XXX I think this needs to be guarded against being run more than once.
      let donor = class_getInstanceMethod(self, #selector(__encodeInt(_:forKey:)))
      class_addMethod(self, Selector("encodeInt:forKey:"), method_getImplementation(donor), method_getTypeEncoding(donor))
    }
    
    ...
  }

--
Brent Royal-Gordon
Architechies


(Tony Parker) #11

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

···

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com <http://bugreport.apple.com/> and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>


(Brent Royal-Gordon) #12

You could just do the one and call it encodeCInt. I think people would understand that it's different because it's using a sort-of-foreign type.

···

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>


(Tony Parker) #13

I thought of the exact same name, but I'm not enthusiastic about the inconsistency this creates with all of the other decode methods on NSCoder. I'm discussing with a few people to decide what to do next.

- Tony

···

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

You could just do the one and call it encodeCInt. I think people would understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>


(John Spurlock) #14

1. Since encoding/decoding various types is the principal domain of this
type, it seems ok to be overly clear in the method names here.

2. Is there a way to systematically look for other types that may also have
this problem lurking with ints or other similar overload groups?

···

On Tue, Jul 19, 2016 at 9:52 PM, Tony Parker <anthony.parker@apple.com> wrote:

I thought of the exact same name, but I'm not enthusiastic about the
inconsistency this creates with all of the other decode methods on NSCoder.
I'm discussing with a few people to decide what to do next.

- Tony

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com> > wrote:

You could just do the one and call it encodeCInt. I think people would
understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following
methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing
without simply reverting these names back to Swift 2.2 style, so I think
that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com> > wrote:

Ok, filed a new bug for the encodeInt:forKey issue:
rdar://problem/27425997

Ensured it reproduces in xcode beta 3, swift version 3.0
(swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to
fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com> > wrote:

We renamed some of these methods for Swift 3 in an attempt to remove some
of the confusion surrounding which of these did what - they were really
named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since
they were easily confused with the Swift Int type. I think we’ll have to
figure out a different approach here. John, please file a bug at
bugreport.apple.com and let me know the radar number, and we’ll look
into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com> >> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it
overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles,
but I'm getting the same original problem at runtime. i.e.
"encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able
to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the
Swift version of the "Encoding General Data" section, and 27
(non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no
Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend
you file a radar against Foundation. If this is a primitive method for
NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>


(Tony Parker) #15

1. Since encoding/decoding various types is the principal domain of this type, it seems ok to be overly clear in the method names here.

Agreed; I’m trying out a few approaches to see what works best.

2. Is there a way to systematically look for other types that may also have this problem lurking with ints or other similar overload groups?

I don’t think so. I also know that the importer will happily create ambiguous method names, for example when importing two ObjC methods that are the same except that one has an options argument. The options gets a default value and presto - two methods with the same signature. We only find out when someone tries to use it in other source code.

- Tony

···

On Jul 20, 2016, at 5:17 AM, John Spurlock <john.spurlock@gmail.com> wrote:

On Tue, Jul 19, 2016 at 9:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
I thought of the exact same name, but I'm not enthusiastic about the inconsistency this creates with all of the other decode methods on NSCoder. I'm discussing with a few people to decide what to do next.

- Tony

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

You could just do the one and call it encodeCInt. I think people would understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997 <>

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com <http://bugreport.apple.com/> and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>


(Tony Parker) #16

FYI:

https://github.com/apple/swift/pull/3663

- Tony

···

On Jul 20, 2016, at 12:10 PM, Tony Parker via swift-users <swift-users@swift.org> wrote:

On Jul 20, 2016, at 5:17 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

1. Since encoding/decoding various types is the principal domain of this type, it seems ok to be overly clear in the method names here.

Agreed; I’m trying out a few approaches to see what works best.

2. Is there a way to systematically look for other types that may also have this problem lurking with ints or other similar overload groups?

I don’t think so. I also know that the importer will happily create ambiguous method names, for example when importing two ObjC methods that are the same except that one has an options argument. The options gets a default value and presto - two methods with the same signature. We only find out when someone tries to use it in other source code.

- Tony

On Tue, Jul 19, 2016 at 9:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
I thought of the exact same name, but I'm not enthusiastic about the inconsistency this creates with all of the other decode methods on NSCoder. I'm discussing with a few people to decide what to do next.

- Tony

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

You could just do the one and call it encodeCInt. I think people would understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997 <>

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com <http://bugreport.apple.com/> and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Jordan Rose) #17

I’m a bit late here, but I don’t see why this is necessary. John overrode 'encode(_: Int, forKey: String)’ instead of ‘encode(_: Int32, forKey: String)’. Sure, overloading makes this kind of mistake harder to spot, especially when the run-time error comes from Objective-C, but it’s hardly unusual for a Swifty program.

Jordan

···

On Jul 21, 2016, at 13:06, Tony Parker via swift-users <swift-users@swift.org> wrote:

FYI:

https://github.com/apple/swift/pull/3663

- Tony

On Jul 20, 2016, at 12:10 PM, Tony Parker via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

On Jul 20, 2016, at 5:17 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

1. Since encoding/decoding various types is the principal domain of this type, it seems ok to be overly clear in the method names here.

Agreed; I’m trying out a few approaches to see what works best.

2. Is there a way to systematically look for other types that may also have this problem lurking with ints or other similar overload groups?

I don’t think so. I also know that the importer will happily create ambiguous method names, for example when importing two ObjC methods that are the same except that one has an options argument. The options gets a default value and presto - two methods with the same signature. We only find out when someone tries to use it in other source code.

- Tony

On Tue, Jul 19, 2016 at 9:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
I thought of the exact same name, but I'm not enthusiastic about the inconsistency this creates with all of the other decode methods on NSCoder. I'm discussing with a few people to decide what to do next.

- Tony

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

You could just do the one and call it encodeCInt. I think people would understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997 <>

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com <http://bugreport.apple.com/> and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

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


(Tony Parker) #18

It’s because two separate methods in ObjC are apparently mapped to the exact same Swift signature on import.

- Tony

···

On Jul 21, 2016, at 2:46 PM, Jordan Rose <jordan_rose@apple.com> wrote:

I’m a bit late here, but I don’t see why this is necessary. John overrode 'encode(_: Int, forKey: String)’ instead of ‘encode(_: Int32, forKey: String)’. Sure, overloading makes this kind of mistake harder to spot, especially when the run-time error comes from Objective-C, but it’s hardly unusual for a Swifty program.

Jordan

On Jul 21, 2016, at 13:06, Tony Parker via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

FYI:

https://github.com/apple/swift/pull/3663

- Tony

On Jul 20, 2016, at 12:10 PM, Tony Parker via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

On Jul 20, 2016, at 5:17 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

1. Since encoding/decoding various types is the principal domain of this type, it seems ok to be overly clear in the method names here.

Agreed; I’m trying out a few approaches to see what works best.

2. Is there a way to systematically look for other types that may also have this problem lurking with ints or other similar overload groups?

I don’t think so. I also know that the importer will happily create ambiguous method names, for example when importing two ObjC methods that are the same except that one has an options argument. The options gets a default value and presto - two methods with the same signature. We only find out when someone tries to use it in other source code.

- Tony

On Tue, Jul 19, 2016 at 9:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
I thought of the exact same name, but I'm not enthusiastic about the inconsistency this creates with all of the other decode methods on NSCoder. I'm discussing with a few people to decide what to do next.

- Tony

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

You could just do the one and call it encodeCInt. I think people would understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997 <>

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com <http://bugreport.apple.com/> and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(John Spurlock) #19

Nope, that doesn't work, try it yourself.

I tried that, any many more variations, before posting the minimal repro
example here.

···

On Thu, Jul 21, 2016 at 5:46 PM, Jordan Rose <jordan_rose@apple.com> wrote:

I’m a bit late here, but I don’t see why this is necessary. John overrode
'encode(_: Int, forKey: String)’ instead of ‘encode(_: Int32, forKey:
String)’. Sure, overloading makes this kind of mistake harder to spot,
especially when the run-time error comes from Objective-C, but it’s hardly
unusual for a Swifty program.

Jordan

On Jul 21, 2016, at 13:06, Tony Parker via swift-users < > swift-users@swift.org> wrote:

FYI:

https://github.com/apple/swift/pull/3663

- Tony

On Jul 20, 2016, at 12:10 PM, Tony Parker via swift-users < > swift-users@swift.org> wrote:

On Jul 20, 2016, at 5:17 AM, John Spurlock <john.spurlock@gmail.com> > wrote:

1. Since encoding/decoding various types is the principal domain of this
type, it seems ok to be overly clear in the method names here.

Agreed; I’m trying out a few approaches to see what works best.

2. Is there a way to systematically look for other types that may also
have this problem lurking with ints or other similar overload groups?

I don’t think so. I also know that the importer will happily create
ambiguous method names, for example when importing two ObjC methods that
are the same except that one has an options argument. The options gets a
default value and presto - two methods with the same signature. We only
find out when someone tries to use it in other source code.

- Tony

On Tue, Jul 19, 2016 at 9:52 PM, Tony Parker <anthony.parker@apple.com> > wrote:

I thought of the exact same name, but I'm not enthusiastic about the
inconsistency this creates with all of the other decode methods on NSCoder.
I'm discussing with a few people to decide what to do next.

- Tony

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com> >> wrote:

You could just do the one and call it encodeCInt. I think people would
understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com> >> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following
methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing
without simply reverting these names back to Swift 2.2 style, so I think
that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com> >> wrote:

Ok, filed a new bug for the encodeInt:forKey issue:
rdar://problem/27425997

Ensured it reproduces in xcode beta 3, swift version 3.0
(swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to
fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com> >> wrote:

We renamed some of these methods for Swift 3 in an attempt to remove
some of the confusion surrounding which of these did what - they were
really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since
they were easily confused with the Swift Int type. I think we’ll have to
figure out a different approach here. John, please file a bug at
bugreport.apple.com and let me know the radar number, and we’ll look
into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon < >>> brent@architechies.com> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it
overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it
compiles, but I'm getting the same original problem at runtime. i.e.
"encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able
to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the
Swift version of the "Encoding General Data" section, and 27
(non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no
Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend
you file a radar against Foundation. If this is a primitive method for
NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>

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

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


(Jordan Rose) #20

But they aren’t. One takes an Int and the other takes an Int32. John just overrode the wrong one.

Jordan

···

On Jul 21, 2016, at 14:52, Tony Parker <anthony.parker@apple.com> wrote:

It’s because two separate methods in ObjC are apparently mapped to the exact same Swift signature on import.

- Tony

On Jul 21, 2016, at 2:46 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

I’m a bit late here, but I don’t see why this is necessary. John overrode 'encode(_: Int, forKey: String)’ instead of ‘encode(_: Int32, forKey: String)’. Sure, overloading makes this kind of mistake harder to spot, especially when the run-time error comes from Objective-C, but it’s hardly unusual for a Swifty program.

Jordan

On Jul 21, 2016, at 13:06, Tony Parker via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

FYI:

https://github.com/apple/swift/pull/3663

- Tony

On Jul 20, 2016, at 12:10 PM, Tony Parker via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

On Jul 20, 2016, at 5:17 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

1. Since encoding/decoding various types is the principal domain of this type, it seems ok to be overly clear in the method names here.

Agreed; I’m trying out a few approaches to see what works best.

2. Is there a way to systematically look for other types that may also have this problem lurking with ints or other similar overload groups?

I don’t think so. I also know that the importer will happily create ambiguous method names, for example when importing two ObjC methods that are the same except that one has an options argument. The options gets a default value and presto - two methods with the same signature. We only find out when someone tries to use it in other source code.

- Tony

On Tue, Jul 19, 2016 at 9:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
I thought of the exact same name, but I'm not enthusiastic about the inconsistency this creates with all of the other decode methods on NSCoder. I'm discussing with a few people to decide what to do next.

- Tony

On Jul 19, 2016, at 6:32 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

You could just do the one and call it encodeCInt. I think people would understand that it's different because it's using a sort-of-foreign type.

--
Brent Royal-Gordon
Sent from my iPhone

On Jul 19, 2016, at 4:33 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:

Hi John,

Thanks for filing the bug.

The root cause of the issue is that the importer would turn the following methods into the same name:

- (void)encodeInt:(int)x forKey:(NSString *)k;
- (void)encodeInt32:(uint32_t)x forKey:(NSString *)k;

Plus, there is the added confusion that this method:

- (void)encodeInteger:(NSInteger)x forKey:(NSString *)k;

is imported into Swift like this:

func encode(_ x: Int, forKey k : String)

where, as you can see, “Int” means “NSInteger”, but not the C “int”.

I’m not really sure how to resolve this and still allow for subclassing without simply reverting these names back to Swift 2.2 style, so I think that’s probably what I’ll have to do:

func encodeInt(_ x : Int32, forKey k : String)
func encodeInt32(_ x : Int32, forKey k : String)
func encodeInt64(_ x : Int64, forKey k : String)
func encodeInteger(_ x : Int, forKey k : String)

and so on, for all of the encode methods, so they are consistent.

- Tony

On Jul 19, 2016, at 8:20 AM, John Spurlock <john.spurlock@gmail.com <mailto:john.spurlock@gmail.com>> wrote:

Ok, filed a new bug for the encodeInt:forKey issue: rdar://problem/27425997 <>

Ensured it reproduces in xcode beta 3, swift version 3.0 (swiftlang-800.0.34.6 clang-800.0.33)

Is there anything I can do in the meantime as a swift-only workaround to fix my custom NSCoder?

Thanks,
- john

On Mon, Jul 18, 2016 at 10:52 PM, Tony Parker <anthony.parker@apple.com <mailto:anthony.parker@apple.com>> wrote:
We renamed some of these methods for Swift 3 in an attempt to remove some of the confusion surrounding which of these did what - they were really named for C types and not Swift ones.

encodeInt:forKey: and decodeInt:forKey: are the two missing ones, since they were easily confused with the Swift Int type. I think we’ll have to figure out a different approach here. John, please file a bug at bugreport.apple.com <http://bugreport.apple.com/> and let me know the radar number, and we’ll look into it.

Thanks,
- Tony

> On Jul 18, 2016, at 6:33 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:
>
>> Hi Tony - when I add that attribute, I get an error at compile-time:
>> Objective-C method has a different selector from the method it overrides ('encodeInt:forKey:' vs. 'encodeInteger:forKey:')
>>
>> If I update to encodeInteger:forKey as the fix describes, it compiles, but I'm getting the same original problem at runtime. i.e. "encodeInt:forKey: only defined for abstract class"
>>
>> Any other ideas? See the same thing over there? You should be able to paste that into a new swift 3 test.
>
> If you look at the NSCoder documentation, you'll see 25 methods in the Swift version of the "Encoding General Data" section, and 27 (non-deprecated) in the Objective-C version. `-encodeInt:forKey:` has no Swift equivalent. I'm not sure what the other missing method is.
>
> I think this is probably a bug or design oversight, and I'd recommend you file a radar against Foundation. If this is a primitive method for NSCoding, it needs to be accessible from Swift.
>
> --
> Brent Royal-Gordon
> Architechies
>

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users