2012-02-19 11 views
41

Sto cercando di capire perché esistono sia gli oggetti CF che quelli NS, che sembrano fare la stessa cosa e sono intercambiabili tramite il collegamento senza pedaggio. Se, ad esempio, CFArray e NSArray fanno la stessa cosa, e posso lanciarli liberamente tra di loro, qual è il punto in entrambi i casi? Ci sono regole pratiche su quando utilizzare l'una sull'altra? Gli oggetti CF sono solo oggetti legacy da vecchi framework? Qualsiasi comprensione di ciò sarebbe molto apprezzata.Oggetti CF vs oggetti NS

+3

Va notato che a) non tutti i tipi di CF hanno un equivalente NS e viceversa, e b) non tutti i nomi i cui nomi sono uguali a parte il prefisso sono in effetti "senza pedaggio"; 'CFBundle' e' NSBundle', ad esempio, non lo sono.Altro [nei documenti] (https://developer.apple.com/library/mac/documentation/General/Conceptual/CocoaEncyclopedia/Toll-FreeBridgin/Toll-FreeBridgin.html), come sempre. –

risposta

58

Per rispondere alle vostre domande in ordine:

  1. Qual è il punto di entrambi esistente? Ci sono alcuni motivi.

    Se si desidera fornire un'API C, come l'API Carbon, e sono necessari elementi come array e dizionari di oggetti conteggiati di riferimento, si desidera una libreria come Core Foundation (che fornisce CFArray) e, naturalmente, è necessario avere un'API C.

    Se si desidera scrivere librerie per terze parti da utilizzare su Windows (ad esempio), è necessario fornire un'API C.

    Se si desidera scrivere una libreria di basso livello, ad esempio per l'interfaccia con il kernel del sistema operativo, e non si desidera il sovraccarico della messaggistica Objective-C, è necessaria un'API C.

    Quindi questi sono buoni motivi per avere Core Foundation, una libreria C pura.

    Ma se si desidera fornire un'API di livello superiore e più piacevole in Objective-C, si desidera oggetti Objective-C che rappresentino matrici, dizionari, oggetti conteggiati di riferimento e così via. Quindi hai bisogno di Foundation, che è una libreria Objective-C.

  2. Quando si deve utilizzare uno o l'altro? In generale, dovresti utilizzare le classi Objective-C (ad esempio NSArray) ogni volta che puoi, perché l'interfaccia Objective-C è più piacevole da utilizzare: myArray.count (o [myArray count]) è più facile da leggere e scrivere rispetto a CFArrayGetCount(myArray). Dovresti utilizzare l'API di Core Foundation solo quando ne hai davvero bisogno: quando sei su una piattaforma che non ha Objective-C, o quando hai bisogno di funzionalità che l'API di Core Foundation fornisce ma gli oggetti Objective-C non sono disponibili. Ad esempio, è possibile specificare i callback durante la creazione di CFArray o CFDictionary che consentono di memorizzare oggetti conteggiati non di riferimento. Le classi NSArray e NSDictionary non consentono di farlo: presumono sempre che stiate memorizzando oggetti conteggiati di riferimento.

  3. Gli oggetti CF sono solo oggetti legacy? Affatto. In effetti, Nextstep esisteva da anni con la sola libreria Objective-C Foundation e nessuna libreria (pubblica) Core Foundation. Quando Apple aveva bisogno di supportare sia l'API Carbon che l'API Cocoa oltre alle stesse strutture del sistema operativo di livello inferiore, hanno creato (o reso pubblico) Core Foundation per supportare entrambi.

Per inciso, alcune delle Core Foundation sono open source. Puoi trovare la parte open source per Mac OS X 10.10.5 qui: https://opensource.apple.com/source/CF/CF-1153.18/. Ho trovato il codice sorgente di CFRunLoop e CFStream per essere molto istruttivo.

+0

Sommario impressionante, Rob. Grazie! – Eric

1

CF sta per CoreFoundation. Gli oggetti esposti con CF nei loro nomi sono solo normali oggetti della Fondazione Core, scritti in C. Tutti gli oggetti sono collegati gratuitamente con i loro amici della Cocoa Touch Foundation su Objective-C land. Di solito sono puntatori opachi.

NS sta per NextStep, che era il vecchio sistema operativo su cui è stato creato Mac OS X. Gli oggetti con prefisso NS sono solitamente scritti interamente in Objective-C o C o anche in alcuni C++.

Dipende davvero da cosa è necessario fare ogni oggetto. È certamente più facile per me lavorare in puro Objective-C con NSString, quindi è per me lavorare in un mix di C e Objective-C con CFString, ma ci sono alcune cose che gli oggetti CF possono fare che gli oggetti NS semplicemente possono ' t (per lo più materiale di livello molto basso). Anche gli oggetti CF si dilatano molto di più in Ref, mutazioni e ispezioni rispetto alle loro controparti NS.

(Per riferimento futuro, esistono altri prefissi: CG per CoreGraphics, UI per UIKit, QL per QuickLook, AV per AVFoundation, MP per MediaPlayer, MF per MessageFoundation, GL per GLKit e MK per MapKit) (Se ne ho perso qualcuno, sarò lieto di modificare).

+2

Questa risposta è fondamentalmente corretta, ma potrebbe creare qualche confusione. Core Foundation non "usa oggetti basati su Objective C". In alcuni casi gli oggetti Cocoa vengono implementati utilizzando gli oggetti di Core Foundation, ma mai viceversa. Le app Cocoa devono collegare CoreFoundation.framework. Le app di Core Foundation non devono collegare Foundation.framework (che fornisce NSString e i suoi amici ObjC). Inoltre non mi riferisco a CF come "oggetti interni di Apple". Si tratta di un'API pubblica completa e comunemente utilizzata con altri framework Core come Core Text. Come dici tu, generalmente dovresti usare NS a meno che tu non abbia bisogno di CF. –

+0

Modificandolo ora. Grazie – CodaFi

+0

Cosa intendi quando dici che gli oggetti CF sono allocati staticamente? –

3

C'è un po 'di storia in questa domanda. Core Foundation è il cervello dell'operazione. È scritto principalmente in C. È stato creato con l'acquisizione di NEXT da parte di Apple e le loro API e deve molto a loro. Le classi NS * sono spesso solo interfacce astratte Objective C costruite in cima ai tipi CF *. Quindi, quando chiedi perché esistono sia CFArray che NSArray, la risposta è che in realtà no. NSArrays sono CFArrays, NSStrings sono CFStrings, ecc. Ecco perché è possibile il bridging senza pedaggio.

Per una lettura più interessante e dettagliata, vorrei fare riferimento a this blog post.

11

Core Foundation è un'API C per una varietà di strutture di dati comuni. La maggior parte di queste strutture dati ha equivalenti in Cocoa, ma non tutti. La maggior parte di quelli equivalenti sono a ponte gratuito, consentendo loro di essere usati in modo intercambiabile, ma non tutti.

Il bridging a pagamento è un trucco di implementazione molto intelligente. Se vuoi i dettagli sottostanti, vedi lo ridiculous_fish post che @Matt Wilding indica. È il più autorevole in materia (e una grande influenza su iOS:PTL capitolo 19 che spiega anche come funziona tutto). Ma non importa per la maggior parte degli scopi. Come nota Matt, puoi generalmente fingere che uno NSArray sia lo stesso di CFArrayRef. Questo non è vero in molti casi, ma a volte è vero, e abbastanza vicino per la maggior parte del tempo. È come dire che @"stuff" è lo stesso di NSString contenente stuff. È principalmente vero, ma non esattamente.

Quando OS 9 si spostava su OS X, era molto conveniente fornire l'accesso C alle strutture dati Objective-C-like. Molti framework di basso livello espongono oggi le API C per motivi di prestazioni. Non dovresti pensare a CF come "legacy" o "internal". Dovresti pensarlo come di basso livello e dovresti usarlo solo quando hai bisogno del potere che esso fornisce, o se hai a che fare con un framework di basso livello che lo richiede.

Gli oggetti CF sono spesso più flessibili delle loro controparti NS. Ad esempio, CFDictionaryRef può contenere chiavi e valori senza oggetto, mentre non è possibile impostare NSDictionary. (Naturalmente sono numero verde ponte, in modo da poter creare un non-mantenendo CFDictionaryRef e poi trattarlo come un NSDictionary. Tricky che ....)

Come Apple rilascia nuovi quadri, si noterà che spesso espongono prima le API C e successivamente aggiungono le API Objective-C. Questo è un motivo per cui è una buona idea imparare Core Foundation, anche se non lo usi tutti i giorni. Ma quando possibile, generalmente dovresti usare ObjC.

+0

Rob, ottima spiegazione. Hai sollevato un punto che pensavo fosse interessante. Qual è il diverso tra @ "stringa" e NSString contenente "stringa"? Ho pensato che @ "string" fosse implicito in NSString ... – Eric

+5

@ "string" è in realtà un '__NSCFConstantString', che è una sottoclasse (di ordinamento) di' NSString'. ("Sort-of" perché è una classe di bridge senza pedaggio, che non è esattamente la stessa di una sottoclasse.) Le stringhe costanti si trovano nel segmento __TEXT, non nell'heap (insieme al loro cstring sottostante, che è memorizzato separatamente) e ignorano le chiamate 'retain' e' release'. –