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-CNombre en SwiftNotas
NSBlockOperationBlockOperation
NSBundleBundle
NSByteCountFormatterByteCountFormatter
NSCachedURLResponseCachedURLResponse
NSComparisonResultComparisonResult
NSDateComponentsFormatterDateComponentsFormatter
NSDateFormatterDateFormatter
NSDateIntervalFormatterDateIntervalFormatter
NSDistributedNotificationCenterDistributedNotificationCenter
NSEnergyFormatterEnergyFormatter
NSFileHandleFileHandle
NSFileManagerFileManager
NSFileManagerDelegateFileManagerDelegate
NSFileWrapperFileWrapper
NSFormatterFormatter
NSHostHost
NSHTTPCookieHTTPCookie
NSHTTPCookieStorageHTTPCookieStorage
NSHTTPURLResponseHTTPURLResponse
NSInputStreamInputStream
NSJSONSerializationJSONSerialization
NSLengthFormatterLengthFormatter
NSMassFormatterMassFormatter
NSMessagePortMessagePort
NSNetServiceNetService
NSNetServiceBrowserNetServiceBrowser
NSNetServiceBrowserDelegateNetServiceBrowserDelegate
NSNetServiceDelegateNetServiceDelegate
NSNotificationCenterNotificationCenter
NSNotificationNameNotificationName
NSNotificationQueueNotificationQueue
NSNumberFormatterNumberFormatter
NSOperatingSystemVersionOperatingSystemVersion
NSOperationOperation
NSOperationQueueOperationQueue
NSOutputStreamOutputStreamLa librería estándar de Swift tiene un tipo OutputStream que será renombrado a OutputStreamable.
NSPersonNameComponentsFormatterPersonNameComponentsFormatter
NSPipePipe
NSPortPort
NSPortDelegatePortDelegate
NSPortMessagePortMessage
NSProcessInfoProcessInfo
NSProgressProgress
NSProgressReportingProgressReporting
NSPropertyListSerializationPropertyListSerialization
NSQualityOfServiceQualityOfService
NSRunLoopRunLoop
NSScannerScanner
NSSocketPortSocketPort
NSStreamStream
NSStreamDelegateStreamDelegate
NSTaskProcessLa librería estándar tiene un tipo Process. Su funcionalidad será incorporada al tipo ProcessInfo haciendo que el actual enum desaparezca.
NSThreadThread
NSTimeIntervalTimeInterval
NSTimerTimer
NSUndoManagerUndoManager
NSURLAuthenticationChallengeURLAuthenticationChallenge
NSURLAuthenticationChallengeSenderURLAuthenticationChallengeSender
NSURLCacheURLCache
NSURLCredentialURLCredential
NSURLCredentialStorageURLCredentialStorage
NSURLProtectionSpaceURLProtectionSpace
NSURLProtocolURLProtocol
NSURLProtocolClientURLProtocolClient
NSURLRequestURLRequest
NSURLResponseURLResponse
NSURLSessionURLSession
NSURLSessionConfigurationURLSessionConfiguration
NSURLSessionDataDelegateURLSessionDataDelegate
NSURLSessionDataTaskURLSessionDataTask
NSURLSessionDelegateURLSessionDelegate
NSURLSessionDownloadDelegateURLSessionDownloadDelegate
NSURLSessionDownloadTaskURLSessionDownloadTask
NSURLSessionStreamDelegateURLSessionStreamDelegate
NSURLSessionStreamTaskURLSessionStreamTask
NSURLSessionTaskURLSessionTask
NSURLSessionTaskDelegateURLSessionTaskDelegate
NSURLSessionUploadTaskURLSessionUploadTask
NSUserDefaultsUserDefaults
NSXMLDocumentXMLDocument
NSXMLDTDXMLDTD
NSXMLDTDNodeXMLDTDNode
NSXMLElementXMLElement
NSXMLNodeXMLNode
NSXMLParserXMLParser
NSXMLParserDelegateXMLParserDelegate

Tipos embebidos

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

Antiguo nombreNuevo nombre
NSActivityOptionsProcessInfo.ActivityOptions
NSAppleEventSendOptionsNSAppleEventDescriptor.SendOptions
NSAttributedStringEnumerationOptionsAttributedString.EnumerationOptions
NSBackgroundActivityResultNSBackgroundActivityScheduler.Result
NSByteCountFormatterCountStyleByteCountFormatter.CountStyle
NSByteCountFormatterUnitsByteCountFormatter.Units
NSCalculationErrorDecimal.CalculationError
NSCalendarOptionsCalendar.Options
NSCalendarUnitCalendar.Unit
NSComparisonPredicateModifierComparisonPredicate.Modifier
NSComparisonPredicateOptionsComparisonPredicate.Options
NSCompoundPredicateTypeCompoundPredicate.LogicalType
NSDataBase64DecodingOptionsNSData.Base64DecodingOptions
NSDataBase64EncodingOptionsNSData.Base64EncodingOptions
NSDataReadingOptionsNSData.ReadingOptions
NSDataSearchOptionsNSData.SearchOptions
NSDataWritingOptionsNSData.WritingOptions
NSDateFormatterBehaviorDateFormatter.Behavior
NSDateFormatterStyleDateFormatter.Style
NSDateIntervalFormatterStyleDateIntervalFormatter.Style
NSDecodingFailurePolicyCoder.DecodingFailurePolicy
NSDirectoryEnumerationOptionsFileManager.DirectoryEnumerationOptions
NSDistributedNotificationOptionsDistributedNotificationCenter.Options
NSEnergyFormatterUnitEnergyFormatter.Unit
NSExpressionTypeNSExpression.ExpressionType
NSFileCoordinatorReadingOptionsFileCoordinator.ReadingOptions
NSFileCoordinatorWritingOptionsFileCoordinator.WritingOptions
NSFileManagerItemReplacementOptionsFileManager.ItemReplacementOptions
NSFileManagerUnmountOptionsFileManager.UnmountOptions
NSFileVersionAddingOptionsFileVersion.AddingOptions
NSFileVersionReplacingOptionsFileVersion.ReplacingOptions
NSFileWrapperReadingOptionsFileWrapper.ReadingOptions
NSFileWrapperWritingOptionsFileWrapper.WritingOptions
NSFormattingContextFormatter.Context
NSFormattingUnitStyleFormatter.UnitStyle
NSHTTPCookieAcceptPolicyHTTPCookie.AcceptPolicy
NSInsertionPositionNSPositionalSpecifier.InsertionPosition
NSItemProviderErrorCodeNSItemProvider.ErrorCode
NSJSONReadingOptionsJSONSerialization.ReadingOptions
NSJSONWritingOptionsJSONSerialization.WritingOptions
NSLengthFormatterUnitLengthFormatter.Unit
NSLinguisticTaggerOptionsNSLinguisticTagger.Options
NSLocaleLanguageDirectionLocale.LanguageDirection
NSMachPortOptionsNSMachPort.Options
NSMassFormatterUnitMassFormatter.Unit
NSMatchingFlagsRegularExpression.MatchingFlags
NSMatchingOptionsRegularExpression.MatchingOptions
NSMeasurementFormatterUnitOptionsMeasurementFormatter.UnitOptions
NSNetServiceOptionsNetService.Options
NSNetServicesErrorNetService.ErrorCode
NSNotificationCoalescingNotificationQueue.NotificationCoalescing
NSNotificationSuspensionBehaviorDistributedNotificationCenter.SuspensionBehavior
NSNumberFormatterBehaviorNumberFormatter.Behavior
NSNumberFormatterPadPositionNumberFormatter.PadPosition
NSNumberFormatterRoundingModeNumberFormatter.RoundingMode
NSNumberFormatterStyleNumberFormatter.Style
NSOperationQueuePriorityOperation.QueuePriority
NSPersonNameComponentsFormatterOptionsPersonNameComponentsFormatter.Options
NSPersonNameComponentsFormatterStylePersonNameComponentsFormatter.Style
NSPointerFunctionsOptionsPointerFunctions.Options
NSPostingStyleNotificationQueue.PostingStyle
NSPredicateOperatorTypeComparisonPredicate.Operator
NSProcessInfoThermalStateProcessInfo.ThermalState
NSPropertyListFormatPropertyListSerialization.PropertyListFormat
NSPropertyListMutabilityOptionsPropertyListSerialization.MutabilityOptions
NSPropertyListReadOptionsPropertyListSerialization.ReadOptions
NSPropertyListWriteOptionsPropertyListSerialization.WriteOptions
NSRegularExpressionOptionsRegularExpression.Options
NSRelativePositionNSRelativeSpecifier.RelativePosition
NSSearchPathDirectoryFileManager.SearchPathDirectory
NSSearchPathDomainMaskFileManager.SearchPathDomainMask
NSSocketNativeHandleSocket.NativeHandle
NSStreamEventStream.Event
NSStreamStatusStream.Status
NSStringCompareOptionsNSString.CompareOptions
NSStringEncodingNSString.Encoding
NSStringEncodingConversionOptionsNSString.EncodingConversionOptions
NSStringEnumerationOptionsNSString.EnumerationOptions
NSTaskTerminationReasonTask.TerminationReason
NSTestComparisonOperationNSSpecifierTest.TestComparisonOperation
NSTextCheckingTypeTextCheckingResult.CheckingType
NSTimeZoneNameStyleTimeZone.NameStyle
NSURLCacheStoragePolicyURLCache.StoragePolicy
NSURLCredentialPersistenceURLCredential.Persistence
NSURLRelationshipFileManager.URLRelationship
NSURLRequestCachePolicyURLRequest.CachePolicy
NSURLRequestNetworkServiceTypeURLRequest.NetworkServiceType
NSURLSessionAuthChallengeDispositionURLSession.AuthChallengeDisposition
NSURLSessionResponseDispositionURLSession.ResponseDisposition
NSURLSessionTaskStateURLSessionTask.State
NSURLSessionTaskMetricsResourceFetchTypeURLSessionTaskMetrics.ResourceFetchType
NSUserNotificationActivationTypeNSUserNotification.ActivationType
NSVolumeEnumerationOptionsFileManager.VolumeEnumerationOptions
NSWhoseSubelementIdentifierNSWhoseSpecifier.SubelementIdentifier
NSXMLDocumentContentKindXMLDocument.ContentKind
NSXMLDTDNodeKindXMLDTDNode.Kind
NSXMLNodeKindXMLNode.Kind
NSXMLParserErrorXMLParser.ErrorCode
NSXMLParserExternalEntityResolvingPolicyXMLParser.ExternalEntityResolvingPolicy
NSXPCConnectionOptionsNSXPCConnection.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.

Etiquetas

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

También en

Cerrar
Botón volver arriba
Cerrar
Cerrar