[swift-evolution] #available has a huge anti-pattern.

Kevin Ballard kevin at sb.org
Thu Feb 4 18:55:37 CST 2016


How do you introduce backfill extensions only for older systems? I just tested this with

extension String {
    @available(iOS, obsoleted=9.0)
    func localizedStandardContainsString(str: String) -> Bool {
        NSLog("calling %@", __FUNCTION__)
        return rangeOfString(str, options: [.CaseInsensitiveSearch, .DiacriticInsensitiveSearch], locale: NSLocale.currentLocale()) != nil
    }
}

but despite the `obsoleted=9.0`, my implementation here is in fact invoked from the code `"foobarbaz".localizedStandardContainsString("bar")` when running in the iOS 9.2 Simulator.

This behavior isn't really all that surprising, but since there's no way within that method to explicitly invoke the "real" method (since I've shadowed it so there's no way to refer to the framework-provided one), I can't even introduce my own #available() check within the method.

What you can do is introduce a different API that uses #available() to call the real API or fall back to a compatibility implementation, but I wouldn't call that a "backfill" since it's a different API.

-Kevin Ballard

On Tue, Feb 2, 2016, at 08:26 AM, Joe Groff via swift-evolution wrote:
> Polyfills have their own tradeoffs; they tend to encourage constant accretion of glue code as new versions get added if there's no pressure to drop old versions, leading to a significant amount of the multi-megabyte Javascript framework downloads we all complain about these days. That said, you might be able to use the related `@available` attribute to introduce backfill extensions that are only available on older systems.
> 
> -Joe
> 
>> On Feb 2, 2016, at 2:03 AM, James Campbell via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> Coming from a web background (before my iOS career) to me #avaliable has huge problem. It encourages fragility.
>> 
>> In my eyes we should encourage two types of detection: Features to make code more adaptable to different environments and language version detection: so we can understand the actual code.
>> 
>> See this example below:
>> 
>> func magic(object: Object)
>> {
>>   if(#avaliable(9.0, 10))
>>  {
>>   object.foo()
>>  }
>> }
>> 
>> Ideally for me I would love to check if the foo function exists like so:
>> 
>> func iOS9OnlyProtocolFunction(object: Object)
>> {
>>   if(#avaliable(Object.foo))
>>  {
>>     object.foo()
>>  }
>> else 
>> {
>>   object.baz()
>>  }
>> }
>> 
>> I think this encourages feature detection which results in less fragile code. What I would love to do is also to extend this to extensions so we could encourage polyfills.
>> 
>> extend object where not_avaliable(Object.foo) 
>> {
>>   func foo() 
>>  {
>>    //Polyfill for platforms which don't support the Object.foo method
>>  }
>> }
>> 
>> Not sure about compiler details but being able to polyfill the function results in much cleaner code for me. I love this approach from the web, so I created my own Objective-C Library to do this:
>> 
>> https://github.com/jcampbell05/Polly
>> *___________________________________*


>> *James⎥Lead Engineer*


>> *james at supmenow.com⎥supmenow.com*


>> *Sup*


>> *Runway East
*


>> *10 Finsbury Square*


>> *London*


>> *
EC2A 1AF *


>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _________________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution


More information about the swift-evolution mailing list