Re: [swift-users] So how do you implement a NSTextStorage subclass in Swift?

2017-02-13 Thread Michel Fortin via swift-users
Le 12 févr. 2017 à 18:41, Karl Wagner  a écrit :
> 
> I've seen this before; I considered it something to be resolved in AppKit. 
> Strings in Swift are values, and the framework expects it to be a reference. 
> Since NSTextStorage is itself a reference-type and informs its delegate of 
> changes, those frameworks should probably retain the NSTS itself and pull 
> Strings out as-needed.

Well, this is apparently not an AppKit problem because the `string` method is 
first defined in `NSAttributedString` in Foundation. `NSTextStorage` only 
inherits that method.

The cleanest fix I can see at the framework level is expose it as two 
properties in `NSAttributedString`:

// swift-only getter for the string, can't override this one
@nonobjc
final public var string: String { 
get { return backingString as String }
}

// this is the one mapped to `string` in objc, you can override this one
@objc(string)
public var backingString: NSString { get } 

This is somewhat analogous to what I'm doing with `method_setImplementation` in 
my solution to remap the method to a Swift method that has the right signature.

That would be source-breaking, but only for those who override the property. 
Pretty much all of these overrides are going to be violating the API contract 
anyway. They probably deserve the error so they can be fixed.

At this point though, I think the topic belong to somewhere else than 
swift-users. I'm just not sure where. I should probably file a radar against 
Foundation at the very least.

-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-users] So how do you implement a NSTextStorage subclass in Swift?

2017-02-12 Thread Karl Wagner via swift-users
  
  
I've seen this before; I considered it something to be resolved in AppKit. 
Strings in Swift are values, and the framework expects it to be a reference. 
Since NSTextStorage is itself a reference-type and informs its delegate of 
changes, those frameworks should probably retain the NSTS itself and pull 
Strings out as-needed.
  
  
  

  
Once the new String model is done (long time yet), I would love it if Apple's 
CoreText team created a truly Swift (i.e. Protocol-based) NSTextStorage API. 
You wouldn't necessarily have to provide a stdlib String; any UTF16-encoded 
Unicode/StringProtocol instance could possibly suffice, allowing you to 
optimise storage through buffer-gaps and whatnot (doable today with 
NSMutableString subclass, but you can't subclass a struct).
  

  
- Karl
  
  
  

  
  
>   
> On Feb 10, 2017 at 10:51 pm,   (mailto:swift-users@swift.org)>  wrote:
>   
>   
>   
> Got some clarity on this from Apple folks on Twitter:   
> https://twitter.com/jtbandes/status/830159670559993856   
>
>   
> On Fri, Feb 10, 2017 at 12:54 PM, Michel Fortin   (mailto:michel.for...@michelf.ca)>  wrote:
>   
> >   
> > I did file one (30314719). I might not have explained the problem clearly 
> > enough, I suppose, because at the time I was misinterpreting the API 
> > contract thinking it was the new AppKit Touch Bar stuff that was violating 
> > it instead. That bug now sits closed and I hesitate opening a new bug for 
> > the same problem just to ask it to be fixed in another way.   Meanwhile I 
> > found an acceptable workaround that I attached to the existing bug report 
> > in addition and I posted all this to the list. Hopefully someone at the 
> > right place will notice.  
> >
> >   
> > But yeah... maybe I should file another bug, against Foundation's Swift 
> > interface this time, since NSTextStorage's string property comes from 
> > NSAttributedString. I'll think about it.  
> >   
> >
> >   
> >
> >   
> >   
> > >   
> > > Le 10 févr. 2017 à 11:36, Jacob Bandes-Storch   > > (mailto:jtban...@gmail.com)>  a écrit :
> > >   
> > >   
> > >   
> > > This seems like a bug (missing feature?) in how the API is imported for 
> > > Swift. You might consider filing a Radar.
> > >   
> > >   
> > >   
> > >   
> > > On Thu, Feb 9, 2017 at 3:12 PM Michel Fortin via swift-users  
> > >   wrote:
> > >   
> > > > The `string` property of `NSTextStorage` is of type `String`, but the 
> > > > contract it must implement is that it should return the backing store 
> > > > of the attributed string (the underlying `NSMutableString` used as the 
> > > > backing store). It seems to me that this makes it impossible to 
> > > > implement correctly a subclass of `NSTextStorage` in Swift, because 
> > > > Swift automatically wraps the `NSString` into a `String` and the 
> > > > underlying mutable storage is not passed around.
> > > >   
> > > >  Here's the documentation for that method:
> > > >   
> > > > https://developer.apple.com/reference/foundation/nsattributedstring/1412616-string
> > > >   
> > > >  In case the contract isn't clear from the documentation (it wasn't for 
> > > > me), I got a confirmation as a response in radar 30314719:
> > > >   >  It’s returning a copy of the backing store, but the contract is 
> > > > actually returning the backing store string. The copy storage 
> > > > declaration in the property spec is only used for setter implementation.
> > > >   
> > > >  So looks like this is impossible to model correctly in Swift due to 
> > > > the automatic bridging to `String`. Some APIs in AppKit expect the 
> > > > `NSString` they receive to mutate when mutating the text storage (touch 
> > > > bar suggestions in `NSTextView`) and will do bad things this isn't the 
> > > > case.
> > > >   
> > > >  Obviously, I can work around this by writing some Objective-C code, 
> > > > but it'd be better if I could avoid splitting the class implementation 
> > > > between two languages. There's another way using swizzling to map the 
> > > > Objective-C method to a Swift implementation of the same method that 
> > > > has the correct signature, and that's probably what I'll end up doing 
> > > > unless a better solution can be pointed out to me.
> > > >   
> > > >   
> > > >  --
> > > >  Michel Fortin
> > > >   https://michelf.ca (https://michelf.ca/)
> > > >   
> > > >  ___
> > > >  swift-users mailing list
> > > >   swift-users@swift.org (mailto:swift-users@swift.org)
> > > >   https://lists.swift.org/mailman/listinfo/swift-users
> > > >   
> >   
> >   
> >   
> >   
> >   
> >   
> >   
> >   
> >  --   
> >  Michel Fortin   
> >   https://michelf.ca
> >   
> >   
> >   
> >   
> >   
> >   
> >   
> >   
> >   
>___ swift-users mailing

Re: [swift-users] So how do you implement a NSTextStorage subclass in Swift?

2017-02-10 Thread Jacob Bandes-Storch via swift-users
Got some clarity on this from Apple folks on Twitter:
https://twitter.com/jtbandes/status/830159670559993856

On Fri, Feb 10, 2017 at 12:54 PM, Michel Fortin 
wrote:

> I did file one (30314719). I might not have explained the problem clearly
> enough, I suppose, because at the time I was misinterpreting the API
> contract thinking it was the new AppKit Touch Bar stuff that was violating
> it instead. That bug now sits closed and I hesitate opening a new bug for
> the same problem just to ask it to be fixed in another way. Meanwhile I
> found an acceptable workaround that I attached to the existing bug report
> in addition and I posted all this to the list. Hopefully someone at the
> right place will notice.
>
> But yeah... maybe I should file another bug, against Foundation's Swift
> interface this time, since NSTextStorage's string property comes from
> NSAttributedString. I'll think about it.
>
>
> Le 10 févr. 2017 à 11:36, Jacob Bandes-Storch  a
> écrit :
>
> This seems like a bug (missing feature?) in how the API is imported for
> Swift. You might consider filing a Radar.
>
> On Thu, Feb 9, 2017 at 3:12 PM Michel Fortin via swift-users <
> swift-users@swift.org> wrote:
>
>> The `string` property of `NSTextStorage` is of type `String`, but the
>> contract it must implement is that it should return the backing store of
>> the attributed string (the underlying `NSMutableString` used as the backing
>> store). It seems to me that this makes it impossible to implement correctly
>> a subclass of `NSTextStorage` in Swift, because Swift automatically wraps
>> the `NSString` into a `String` and the underlying mutable storage is not
>> passed around.
>>
>> Here's the documentation for that method:
>> https://developer.apple.com/reference/foundation/
>> nsattributedstring/1412616-string
>>
>> In case the contract isn't clear from the documentation (it wasn't for
>> me), I got a confirmation as a response in radar 30314719:
>> > It’s returning a copy of the backing store, but the contract is
>> actually returning the backing store string. The copy storage declaration
>> in the property spec is only used for setter implementation.
>>
>> So looks like this is impossible to model correctly in Swift due to the
>> automatic bridging to `String`. Some APIs in AppKit expect the `NSString`
>> they receive to mutate when mutating the text storage (touch bar
>> suggestions in `NSTextView`) and will do bad things this isn't the case.
>>
>> Obviously, I can work around this by writing some Objective-C code, but
>> it'd be better if I could avoid splitting the class implementation between
>> two languages. There's another way using swizzling to map the Objective-C
>> method to a Swift implementation of the same method that has the correct
>> signature, and that's probably what I'll end up doing unless a better
>> solution can be pointed out to me.
>>
>>
>> --
>> Michel Fortin
>> https://michelf.ca
>>
>> ___
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>
> --
> Michel Fortin
> https://michelf.ca
>
>
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] So how do you implement a NSTextStorage subclass in Swift?

2017-02-10 Thread Jacob Bandes-Storch via swift-users
This seems like a bug (missing feature?) in how the API is imported for
Swift. You might consider filing a Radar.

On Thu, Feb 9, 2017 at 3:12 PM Michel Fortin via swift-users <
swift-users@swift.org> wrote:

> The `string` property of `NSTextStorage` is of type `String`, but the
> contract it must implement is that it should return the backing store of
> the attributed string (the underlying `NSMutableString` used as the backing
> store). It seems to me that this makes it impossible to implement correctly
> a subclass of `NSTextStorage` in Swift, because Swift automatically wraps
> the `NSString` into a `String` and the underlying mutable storage is not
> passed around.
>
> Here's the documentation for that method:
>
> https://developer.apple.com/reference/foundation/nsattributedstring/1412616-string
>
> In case the contract isn't clear from the documentation (it wasn't for
> me), I got a confirmation as a response in radar 30314719:
> > It’s returning a copy of the backing store, but the contract is actually
> returning the backing store string. The copy storage declaration in the
> property spec is only used for setter implementation.
>
> So looks like this is impossible to model correctly in Swift due to the
> automatic bridging to `String`. Some APIs in AppKit expect the `NSString`
> they receive to mutate when mutating the text storage (touch bar
> suggestions in `NSTextView`) and will do bad things this isn't the case.
>
> Obviously, I can work around this by writing some Objective-C code, but
> it'd be better if I could avoid splitting the class implementation between
> two languages. There's another way using swizzling to map the Objective-C
> method to a Swift implementation of the same method that has the correct
> signature, and that's probably what I'll end up doing unless a better
> solution can be pointed out to me.
>
>
> --
> Michel Fortin
> https://michelf.ca
>
> ___
> 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


Re: [swift-users] So how do you implement a NSTextStorage subclass in Swift?

2017-02-10 Thread Michel Fortin via swift-users
In case this is useful to someone, this is the workaround I'll be using:

```
class CustomTextStorage: NSTextStorage {

private let backingStore: NSMutableAttributedString

// This method should never get called from Objective-C as it doesn't 
respect 
// the API contract because of the wrapping in `String`.
//
// This could get called directly from Swift code when dispatching 
without 
// passing by the Objective-C runtime. So it must still produce the 
right 
// thing for Swift.
override var string: String {
return backingStore.string
}

// Objective-C method implementation for `string` is remapped to this 
method to 
// avoid wrapping the result in `String`. With the correct method 
signature 
// we can return the backing store string object.
var backingNSString: NSString {
return backingStore.mutableString
}

// call once at program initialization:
static func fixupStringMethod() {
let theClass = CustomTextStorage.self
let badStringMeth = class_getInstanceMethod(theClass, 
#selector(getter: string))
let goodStringMeth = class_getInstanceMethod(theClass, 
#selector(getter: backingNSString))
let goodImp = method_getImplementation(goodStringMeth)
method_setImplementation(badStringMeth, goodImp)
}

// ... rest of the class goes here ...
}
```

> Le 9 févr. 2017 à 18:12, Michel Fortin via swift-users 
>  a écrit :
> 
> The `string` property of `NSTextStorage` is of type `String`, but the 
> contract it must implement is that it should return the backing store of the 
> attributed string (the underlying `NSMutableString` used as the backing 
> store). It seems to me that this makes it impossible to implement correctly a 
> subclass of `NSTextStorage` in Swift, because Swift automatically wraps the 
> `NSString` into a `String` and the underlying mutable storage is not passed 
> around.
> 
> Here's the documentation for that method:
> https://developer.apple.com/reference/foundation/nsattributedstring/1412616-string
> 
> In case the contract isn't clear from the documentation (it wasn't for me), I 
> got a confirmation as a response in radar 30314719:
>> It’s returning a copy of the backing store, but the contract is actually 
>> returning the backing store string. The copy storage declaration in the 
>> property spec is only used for setter implementation.
> 
> So looks like this is impossible to model correctly in Swift due to the 
> automatic bridging to `String`. Some APIs in AppKit expect the `NSString` 
> they receive to mutate when mutating the text storage (touch bar suggestions 
> in `NSTextView`) and will do bad things this isn't the case.
> 
> Obviously, I can work around this by writing some Objective-C code, but it'd 
> be better if I could avoid splitting the class implementation between two 
> languages. There's another way using swizzling to map the Objective-C method 
> to a Swift implementation of the same method that has the correct signature, 
> and that's probably what I'll end up doing unless a better solution can be 
> pointed out to me.


-- 
Michel Fortin
https://michelf.ca

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


[swift-users] So how do you implement a NSTextStorage subclass in Swift?

2017-02-09 Thread Michel Fortin via swift-users
The `string` property of `NSTextStorage` is of type `String`, but the contract 
it must implement is that it should return the backing store of the attributed 
string (the underlying `NSMutableString` used as the backing store). It seems 
to me that this makes it impossible to implement correctly a subclass of 
`NSTextStorage` in Swift, because Swift automatically wraps the `NSString` into 
a `String` and the underlying mutable storage is not passed around.

Here's the documentation for that method:
https://developer.apple.com/reference/foundation/nsattributedstring/1412616-string

In case the contract isn't clear from the documentation (it wasn't for me), I 
got a confirmation as a response in radar 30314719:
> It’s returning a copy of the backing store, but the contract is actually 
> returning the backing store string. The copy storage declaration in the 
> property spec is only used for setter implementation.

So looks like this is impossible to model correctly in Swift due to the 
automatic bridging to `String`. Some APIs in AppKit expect the `NSString` they 
receive to mutate when mutating the text storage (touch bar suggestions in 
`NSTextView`) and will do bad things this isn't the case.

Obviously, I can work around this by writing some Objective-C code, but it'd be 
better if I could avoid splitting the class implementation between two 
languages. There's another way using swizzling to map the Objective-C method to 
a Swift implementation of the same method that has the correct signature, and 
that's probably what I'll end up doing unless a better solution can be pointed 
out to me.


-- 
Michel Fortin
https://michelf.ca

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