Swift

Swift 3, análisis de cambios (II). Muerte del NS.

Seguimos con el especial de Swift 3 (del que podéis leer la primera parte aquí y en esta ocasión vamos a centrarnos en uno de los cambios más importantes y que acaba de ser aprobado en su versión final. Nos referimos al cambio de evolución SE-0086 que corresponde a «Eliminar el prefijo NS en la Fundación de Swift».

Este es uno de los principales cambios por los que nuestro código no funcionará en Swift 3, pero al ser una equivalencia de 1 a 1 mediante tablas aprobadas, la adaptación de estos cambios mediante el asistente de migración (en la mayoría de los casos) será rápida e «indolora».

Reglas del cambio

La eliminación o no del prefijo vendrá derivada de una serie de condiciones pre-establecidas para conseguir una coherencia en el cambio en sí.

  • Si la clase es específica de Objective-C, o heredada desde su runtime y el espacio de nombres NS, se mantendrá el prefijo NS. Caso de objetos como: NSObject, NSAutoReleasePool, NSException o NSProxy.
  • Si la clase es específica de la plataforma, se mantendrá el prefijo NS. Aunque algunos ahora pertenecen a la Fundación del lenguaje, su espacio de nombres es de un framework de mayor nivel como UIKit o AppKit. Por lo tanto, todas aquellas que pertenezcan a APIs de mayor nivel conservarán el prefijo, como NSUserNotificacion o NSBackgroundActivity.
  • Si la clase tiene un equivalente como tipo por valor, conservará el prefijo, como NSArray o NSString.
  • Si la clase tendrá en un futuro próximo un equivalente de tipo por valor, conservará igualmente el prefijo, como NSAttributedString o NSPredicate.
  • La clases y protocolos NSLock tendrá una importancia especial en los esfuerzos generales de concurrencia en futuras versiones del lenguaje, por lo que mantendrán el prefijo.
  • Hay algunos tipos de colección implementados en la Fundación que normalmente son genéricos sobre objetos y no sobre el tipo Any. Arreglar esto requerirá que varios tipos se conviertan en structs, por lo que los tipos específicos equivalentes de Objective-C se convertirían en específicos del lenguaje y obligarán a que no se quite el prefijo NS en un futuro próximo. Así que algunos como NSCache, NSMapTable o NSOrderedSet conservarán su nombre de cara al futuro cambio en Swift.
  • Algunos tipos perderán el prefijo pero también cambiarán de nombre, para darles uno más claro y descriptivo, como el caso de NSTask que pasará a llamarse Process.

Tabla de cambios de nombre

Siguiendo estas reglas, los siguientes tipos en Objective-C perderán el prefijo NS pasando a tener un nombre sin él.

Nombre en Objective-C Nombre en Swift Notas
NSBlockOperation BlockOperation
NSBundle Bundle
NSByteCountFormatter ByteCountFormatter
NSCachedURLResponse CachedURLResponse
NSComparisonResult ComparisonResult
NSDateComponentsFormatter DateComponentsFormatter
NSDateFormatter DateFormatter
NSDateIntervalFormatter DateIntervalFormatter
NSDistributedNotificationCenter DistributedNotificationCenter
NSEnergyFormatter EnergyFormatter
NSFileHandle FileHandle
NSFileManager FileManager
NSFileManagerDelegate FileManagerDelegate
NSFileWrapper FileWrapper
NSFormatter Formatter
NSHost Host
NSHTTPCookie HTTPCookie
NSHTTPCookieStorage HTTPCookieStorage
NSHTTPURLResponse HTTPURLResponse
NSInputStream InputStream
NSJSONSerialization JSONSerialization
NSLengthFormatter LengthFormatter
NSMassFormatter MassFormatter
NSMessagePort MessagePort
NSNetService NetService
NSNetServiceBrowser NetServiceBrowser
NSNetServiceBrowserDelegate NetServiceBrowserDelegate
NSNetServiceDelegate NetServiceDelegate
NSNotificationCenter NotificationCenter
NSNotificationName NotificationName
NSNotificationQueue NotificationQueue
NSNumberFormatter NumberFormatter
NSOperatingSystemVersion OperatingSystemVersion
NSOperation Operation
NSOperationQueue OperationQueue
NSOutputStream OutputStream La librería estándar de Swift tiene un tipo OutputStream que será renombrado a OutputStreamable.
NSPersonNameComponentsFormatter PersonNameComponentsFormatter
NSPipe Pipe
NSPort Port
NSPortDelegate PortDelegate
NSPortMessage PortMessage
NSProcessInfo ProcessInfo
NSProgress Progress
NSProgressReporting ProgressReporting
NSPropertyListSerialization PropertyListSerialization
NSQualityOfService QualityOfService
NSRunLoop RunLoop
NSScanner Scanner
NSSocketPort SocketPort
NSStream Stream
NSStreamDelegate StreamDelegate
NSTask Process La librería estándar tiene un tipo Process. Su funcionalidad será incorporada al tipo ProcessInfo haciendo que el actual enum desaparezca.
NSThread Thread
NSTimeInterval TimeInterval
NSTimer Timer
NSUndoManager UndoManager
NSURLAuthenticationChallenge URLAuthenticationChallenge
NSURLAuthenticationChallengeSender URLAuthenticationChallengeSender
NSURLCache URLCache
NSURLCredential URLCredential
NSURLCredentialStorage URLCredentialStorage
NSURLProtectionSpace URLProtectionSpace
NSURLProtocol URLProtocol
NSURLProtocolClient URLProtocolClient
NSURLRequest URLRequest
NSURLResponse URLResponse
NSURLSession URLSession
NSURLSessionConfiguration URLSessionConfiguration
NSURLSessionDataDelegate URLSessionDataDelegate
NSURLSessionDataTask URLSessionDataTask
NSURLSessionDelegate URLSessionDelegate
NSURLSessionDownloadDelegate URLSessionDownloadDelegate
NSURLSessionDownloadTask URLSessionDownloadTask
NSURLSessionStreamDelegate URLSessionStreamDelegate
NSURLSessionStreamTask URLSessionStreamTask
NSURLSessionTask URLSessionTask
NSURLSessionTaskDelegate URLSessionTaskDelegate
NSURLSessionUploadTask URLSessionUploadTask
NSUserDefaults UserDefaults
NSXMLDocument XMLDocument
NSXMLDTD XMLDTD
NSXMLDTDNode XMLDTDNode
NSXMLElement XMLElement
NSXMLNode XMLNode
NSXMLParser XMLParser
NSXMLParserDelegate XMLParserDelegate

Tipos embebidos

Los siguientes tipos serán elevados a la clase contenedora como subtipo, formando parte de la misma.

Antiguo nombre Nuevo nombre
NSActivityOptions ProcessInfo.ActivityOptions
NSAppleEventSendOptions NSAppleEventDescriptor.SendOptions
NSAttributedStringEnumerationOptions AttributedString.EnumerationOptions
NSBackgroundActivityResult NSBackgroundActivityScheduler.Result
NSByteCountFormatterCountStyle ByteCountFormatter.CountStyle
NSByteCountFormatterUnits ByteCountFormatter.Units
NSCalculationError Decimal.CalculationError
NSCalendarOptions Calendar.Options
NSCalendarUnit Calendar.Unit
NSComparisonPredicateModifier ComparisonPredicate.Modifier
NSComparisonPredicateOptions ComparisonPredicate.Options
NSCompoundPredicateType CompoundPredicate.LogicalType
NSDataBase64DecodingOptions NSData.Base64DecodingOptions
NSDataBase64EncodingOptions NSData.Base64EncodingOptions
NSDataReadingOptions NSData.ReadingOptions
NSDataSearchOptions NSData.SearchOptions
NSDataWritingOptions NSData.WritingOptions
NSDateFormatterBehavior DateFormatter.Behavior
NSDateFormatterStyle DateFormatter.Style
NSDateIntervalFormatterStyle DateIntervalFormatter.Style
NSDecodingFailurePolicy Coder.DecodingFailurePolicy
NSDirectoryEnumerationOptions FileManager.DirectoryEnumerationOptions
NSDistributedNotificationOptions DistributedNotificationCenter.Options
NSEnergyFormatterUnit EnergyFormatter.Unit
NSExpressionType NSExpression.ExpressionType
NSFileCoordinatorReadingOptions FileCoordinator.ReadingOptions
NSFileCoordinatorWritingOptions FileCoordinator.WritingOptions
NSFileManagerItemReplacementOptions FileManager.ItemReplacementOptions
NSFileManagerUnmountOptions FileManager.UnmountOptions
NSFileVersionAddingOptions FileVersion.AddingOptions
NSFileVersionReplacingOptions FileVersion.ReplacingOptions
NSFileWrapperReadingOptions FileWrapper.ReadingOptions
NSFileWrapperWritingOptions FileWrapper.WritingOptions
NSFormattingContext Formatter.Context
NSFormattingUnitStyle Formatter.UnitStyle
NSHTTPCookieAcceptPolicy HTTPCookie.AcceptPolicy
NSInsertionPosition NSPositionalSpecifier.InsertionPosition
NSItemProviderErrorCode NSItemProvider.ErrorCode
NSJSONReadingOptions JSONSerialization.ReadingOptions
NSJSONWritingOptions JSONSerialization.WritingOptions
NSLengthFormatterUnit LengthFormatter.Unit
NSLinguisticTaggerOptions NSLinguisticTagger.Options
NSLocaleLanguageDirection Locale.LanguageDirection
NSMachPortOptions NSMachPort.Options
NSMassFormatterUnit MassFormatter.Unit
NSMatchingFlags RegularExpression.MatchingFlags
NSMatchingOptions RegularExpression.MatchingOptions
NSMeasurementFormatterUnitOptions MeasurementFormatter.UnitOptions
NSNetServiceOptions NetService.Options
NSNetServicesError NetService.ErrorCode
NSNotificationCoalescing NotificationQueue.NotificationCoalescing
NSNotificationSuspensionBehavior DistributedNotificationCenter.SuspensionBehavior
NSNumberFormatterBehavior NumberFormatter.Behavior
NSNumberFormatterPadPosition NumberFormatter.PadPosition
NSNumberFormatterRoundingMode NumberFormatter.RoundingMode
NSNumberFormatterStyle NumberFormatter.Style
NSOperationQueuePriority Operation.QueuePriority
NSPersonNameComponentsFormatterOptions PersonNameComponentsFormatter.Options
NSPersonNameComponentsFormatterStyle PersonNameComponentsFormatter.Style
NSPointerFunctionsOptions PointerFunctions.Options
NSPostingStyle NotificationQueue.PostingStyle
NSPredicateOperatorType ComparisonPredicate.Operator
NSProcessInfoThermalState ProcessInfo.ThermalState
NSPropertyListFormat PropertyListSerialization.PropertyListFormat
NSPropertyListMutabilityOptions PropertyListSerialization.MutabilityOptions
NSPropertyListReadOptions PropertyListSerialization.ReadOptions
NSPropertyListWriteOptions PropertyListSerialization.WriteOptions
NSRegularExpressionOptions RegularExpression.Options
NSRelativePosition NSRelativeSpecifier.RelativePosition
NSSearchPathDirectory FileManager.SearchPathDirectory
NSSearchPathDomainMask FileManager.SearchPathDomainMask
NSSocketNativeHandle Socket.NativeHandle
NSStreamEvent Stream.Event
NSStreamStatus Stream.Status
NSStringCompareOptions NSString.CompareOptions
NSStringEncoding NSString.Encoding
NSStringEncodingConversionOptions NSString.EncodingConversionOptions
NSStringEnumerationOptions NSString.EnumerationOptions
NSTaskTerminationReason Task.TerminationReason
NSTestComparisonOperation NSSpecifierTest.TestComparisonOperation
NSTextCheckingType TextCheckingResult.CheckingType
NSTimeZoneNameStyle TimeZone.NameStyle
NSURLCacheStoragePolicy URLCache.StoragePolicy
NSURLCredentialPersistence URLCredential.Persistence
NSURLRelationship FileManager.URLRelationship
NSURLRequestCachePolicy URLRequest.CachePolicy
NSURLRequestNetworkServiceType URLRequest.NetworkServiceType
NSURLSessionAuthChallengeDisposition URLSession.AuthChallengeDisposition
NSURLSessionResponseDisposition URLSession.ResponseDisposition
NSURLSessionTaskState URLSessionTask.State
NSURLSessionTaskMetricsResourceFetchType URLSessionTaskMetrics.ResourceFetchType
NSUserNotificationActivationType NSUserNotification.ActivationType
NSVolumeEnumerationOptions FileManager.VolumeEnumerationOptions
NSWhoseSubelementIdentifier NSWhoseSpecifier.SubelementIdentifier
NSXMLDocumentContentKind XMLDocument.ContentKind
NSXMLDTDNodeKind XMLDTDNode.Kind
NSXMLNodeKind XMLNode.Kind
NSXMLParserError XMLParser.ErrorCode
NSXMLParserExternalEntityResolvingPolicy XMLParser.ExternalEntityResolvingPolicy
NSXPCConnectionOptions NSXPCConnection.Options

Enumeraciones actualizadas

Los miembros de la enumeración NSExpressionType pierden su sufijo y quedan de la siguiente forma:

extension Expression {
    public enum ExpressionType : UInt {
        case constantValue
        case evaluatedObject
        case variable
        case keyPath
        case function
        case unionSet
        case intersectSet
        case minusSet
        case subquery
        case aggregate
        case anyKey
        case block
        @available(OSX 10.11, iOS 9.0, *)
        case conditional
    }

Las enumeraciones asociadas a ComparisonPredicate igualmente pierden el sufijo, quedando así:

extension ComparisonPredicate {
    public struct Options : OptionSet {
        public init(rawValue: UInt)
        public static var caseInsensitive: ComparisonPredicate.Options { get }
        public static var diacriticInsensitive: ComparisonPredicate.Options { get }
        public static var normalized: ComparisonPredicate.Options { get }
    }

    public enum Modifier : UInt {
        case direct
        case all
        case any
    }

    public enum Operator : UInt {
        case lessThan
        case lessThanOrEqualTo
        case greaterThan
        case greaterThanOrEqualTo
        case equalTo
        case notEqualTo
        case matches
        case like
        case beginsWith
        case endsWith
        case `in`
        case customSelector
        case contains
        case between
    }
}

Los tipos NSDateFormatterStyle y NSDateIntervalFormatterStyle también pierden el sufijo y la opción no pasa a ser none.

extension DateIntervalFormatter {
    @available(OSX 10.10, iOS 8.0, *)
    public enum Style : UInt {
        case none
        case short
        case medium
        case long
        case full
    }
}

Igualmente NSNumberFormatterStyle también perderá el sufijo y no pasa a ser none para mayor coherencia.

extension NumberFormatter {
   public enum Style : UInt {
        case none
        case decimal
        case currency
        case percent
        case scientific
        case spellOut
        @available(OSX 10.11, iOS 9.0, *)
        case ordinal
        @available(OSX 10.11, iOS 9.0, *)
        case currencyISOCode
        @available(OSX 10.11, iOS 9.0, *)
        case currencyPlural
        @available(OSX 10.11, iOS 9.0, *)
        case currencyAccounting
    }
}

Los tipos enumerados NSXMLDocumentContentKind, NSXMLDTDNodeKind y NSXMLNodeKind cambian de nombre a los siguientes según las definiciones, por orden.

extension XMLDocument {
    public enum ContentKind : UInt {
        case xml
        case xhtml
        case html
        case text
    }
}

extension XMLDTDNode {
    public enum Kind : UInt {
        case generalEntity
        case parsedEntity
        case unparsedEntity
        case parameterEntity
        case predefinedEntity
        case cdataAttribute
        case idAttribute
        case idRefAttribute
        case idRefsAttribute
        case entityAttribute
        case entitiesAttribute
        case nmTokenAttribute
        case nmTokensAttribute
        case enumerationAttribute
        case notationAttribute
        case undefinedElementDeclaration
        case emptyElementDeclaration
        case anyElementDeclaration
        case mixedElementDeclaration
        case elementDeclarationElement
    }
}

extension XMLNode {
    public enum Kind : UInt {
        case invalid
        case document
        case element
        case attribute
        case namespace
        case processingInstruction
        case comment
        case text
        case dtd
        case entityDeclaration
        case attributeDeclaration
        case elementDeclaration
        case notationDeclaration
    }
}

Todas las enumeraciones que no están en esta sección conservarán el prefijo NS. En futuras versiones del lenguaje serán evaluados caso por caso para contemplar si han de ser renombrados o no.

NSStringEncoding

Por último, el tipo NSStringEncoding tiene una serie de constantes que serán renombradas como miembros de la estructura de tipo RawRepresentable llamada String.Encoding.

extension String {
    public struct Encoding : RawRepresentable {
        public var rawValue: UInt
        public init(rawValue: UInt)

        public static var ascii { get }
        public static var nextstep { get }
        public static var japaneseEUC { get }
        public static var utf8 { get }
        public static var isoLatin1 { get }
        public static var symbol { get }
        public static var nonLossyASCII { get }
        public static var shiftJIS { get }
        public static var isoLatin2 { get }
        public static var unicode { get }
        public static var windowsCP1251 { get }
        public static var windowsCP1252 { get }
        public static var windowsCP1253 { get }
        public static var windowsCP1254 { get }
        public static var windowsCP1250 { get }
        public static var iso2022JP { get }
        public static var macOSRoman { get }
        public static var utf16 { get }
        public static var utf16BigEndian { get }
        public static var utf16LittleEndian { get }
        public static var utf32 { get }
        public static var utf32BigEndian { get }
        public static var utf32LittleEndian { get }
    }
}

Conclusiones

Como vemos, los cambios no son pocos ni muchos menos. Pero son fáciles de intuir y la mayoría convertibles fácilmente con ayuda del asistente de migración.

En mi experiencia con Swift 3, no he tenido ni un solo problema pues la ayuda del lenguaje te proporciona la nueva clase en cuanto empiezas a escribir la antigua, y si no, el propio compilador te lanza una advertencia. Así que el proceso de adaptación será fácil.

Nos vemos la próxima semana con la siguiente entrega y Good Apple Coding.

Julio César Fernández

Analista, consultor y periodista tecnológico, desarrollador, empresario, productor audiovisual, actor de doblaje e ingeniero de vídeo y audio.

Artículos relacionados

Botón volver arriba