2013-10-25 11 views
8

Ho visto diversi post che trattano questo argomento per quanto riguarda iOS, ma l'una o due menzioni di OS X dicono solo di costruire un framework invece di una libreria statica. (Non riesco a trovare il post con istruzioni decenti per il framework.)Come posso includere un pennino in una libreria statica di OS X?

Ho creato il mio progetto come libreria statica e ho codificato il tutto di conseguenza. Ora, voglio semplicemente mettere il mio framework in un'applicazione demo e si lamenta di un pennino mancante. Come stopgap, ho copiato il pennino nel progetto genitore, ma voglio compartimentare correttamente l'intera cosa.

Qual è l'approccio migliore?

Edit:

per il contesto: ho creato un pennino per inizializzare un NSWindowController in un'applicazione per Mac.

+0

Creare invece il VC in codice? – Kevin

+0

Potrei aver frainteso il problema ma sembra che ci siano pochi post su Internet. Ecco alcuni: * http://www.galloway.me.uk/tutorials/ios-library-with-resources/ * http://www.arcanelab.com/post/43939133725/creating-and -using-a-static-library-with-a-resource –

+0

Sono andato avanti e ho creato un esempio funzionante. Ci sono volute poche ore! Controlla la mia risposta. – nielsbot

risposta

7

No, non è possibile, perché una libreria statica non è uguale a un "pacchetto".

Una libreria statica è un singolo file che contiene classi, codice e variabili che sono stati collegati dal creatore della libreria. Non "contiene" altri file, è essenzialmente un database di codice compilato. Anche se sarebbe possibile inserire i dati per gli xibs, Xcode non avrebbe modo di sapere che era lì dentro, poiché li cerca come singoli file sul filesystem.

Opzione 1: (non buono)

Basta tenere la XI ter con la libreria statica con un file README incluse le istruzioni. Un po 'sciocco, ma veloce e non orribile visto che hai già tutto.

Opzione 2: (discreta)

Si può creare un "quadro", che è essenzialmente un insieme di codice, le risorse, le impostazioni, ecc, che possono essere riutilizzati da molteplici progetti

di Apple Doc per il quadro: https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html

https://developer.apple.com/library/mac/documentation/macosx/conceptual/BPFrameworks/Tasks/CreatingFrameworks.html

guida a caso per OS X Frameworks: (è con la versione precedente di Xcode, ma è lo stesso concetto) http://www.intridea.com/blog/2010/12/28/a-visual-guide-to-creating-an-embeddable-framework-for-mac-osx

[UPDATE 1] Nota che non funziona con iOS, in quanto quadri in bundle app non sono consentiti dalle regole di App Store. (Il codice caricato dinamicamente non è comunque). [Si ringrazia @nielsbot che mi ricordano di questo nei commenti.]

[UPDATE 2] Leggi tutto su iOS 8 hanno cambiato un sacco di cose in questo senso. (Non posso parlare che a causa della NDA di Apple)

+0

Il quadro è la strada da percorrere. –

+1

non funzionerà con iOS, dal momento che le strutture dei pacchetti di app non sono consentite dalle regole di App Store. (Bene, il codice caricato dinamicamente non è in ogni caso) – nielsbot

+0

Sono andato avanti e ho creato un esempio funzionante. Ci sono volute poche ore! Controlla la mia risposta. – nielsbot

1

semplicemente convertire si pennino in una classe C Obiettivo: http://kosmaczewski.net/projects/nib2objc/

quindi includere che come si farebbe con la vostra altra fonte *

* mai fatto, ma in teoria dovrebbe funzionare, giusto?

+1

Le cose che le persone fanno per la reputazione. : p Sto scherzando, suggerimento interessante, indagherò. – Moshe

+0

Beh, una libreria statica non è pensata per avere informazioni UI al suo interno. – Mojtaba

1

Come altri hanno sottolineato, il raggruppamento di un file di pennini con una libreria statica nello stesso modo in cui è possibile raggruppare un pennino con un framework non è possibile. Una libreria statica contiene solo codice compilato. Non è un contenitore per una raccolta di codice e altre risorse.

Detto questo, se sei serio riguardo a questo hai un'opzione che avrebbe lo stesso effetto. Fondamentalmente sarai basato su64 codificare il tuo pennino in una stringa e ricostituirlo in fase di runtime. Ecco la mia ricetta:

1) compila il tuo file .xib in formato binario .nib. Usa XCode o ibtool.

2) utilizzare uno strumento per codificare il .nib come testo di base64. Su OSX è possibile utilizzare openssl per fare questo dal terminale:

openssl base64 -in myNib.nib -out myNib.txt 

3) copia/incolla la stringa Base64 in uno dei file di origine. Costruire un NSString da esso:

NSString* base64 = @"\ 
TklCQXJjaGl2ZQEAAAAJAAAAHgAAADIAAAA2AAAAjAAAAG4AAADuAwAAEQAAAPwG\ 
AACHgIaChoGPh4eCjoGJj46CnYGCnoGCn4GBoIKEooaKqIGOqYGCqoGQq4iMs4WC\ 
uIGEuYePwIaBxoWMy4SCz4GG0IGI0YWM1oGE14aL3YeO5IGE5YeC7IGF7YGKVUlG\ 

... 

ZVN0cmluZwCHgQ0AAABVSUZvbnQAiIBOU0FycmF5AIeATlNGb250AI6AVUlQcm94\ 
eU9iamVjdACIgQMAAABVSUNvbG9yAIeAVUlWaWV3AA=="; 

4) scrivere codice per decodificare la stringa base64 in un NSData:

NSData* d = [[NSData alloc] initWithBase64EncodedString: base64 options: NSDataBase64DecodingIgnoreUnknownCharacters]; 

5) costruire un'UINib dal NSData:

UINib* nib = [UINib nibWithData: d bundle: nil]; 

6) Usa il tuo pennino:

NSArray* nibItems = [nib instantiateWithOwner: nil options: 0]; 

Ora potresti finire per dover cambiare alcune cose nel tuo codice. Se stai creando i controller di visualizzazione dei pennini utilizzando init o initWithNibName:bundle:, questo non funzionerà. Perché? Poiché tali meccanismi appaiono in un pacchetto (in genere il pacchetto di app) per il pennino e il pennino non sarà lì. Ma puoi aggiustare qualsiasi controller di vista nel tuo codice per caricare dal tuo UINib che abbiamo appena ricostituito. Ecco un collegamento che descrive un processo per questo: http://www.indelible.org/ink/nib-loading/

È possibile trovare rapidamente che sono necessarie altre risorse per il codice oltre al proprio .nib. Per esempio. immagini. È possibile utilizzare lo stesso approccio per incorporare immagini o qualsiasi altra risorsa nella libreria statica.

A mio parere, il costo per gli sviluppatori del flusso di lavoro necessario per mantenere aggiornato questo pennino incorporato è piuttosto alto. Se fossi in me, creerei solo un quadro e lo distribuirò.

+0

Se hai intenzione di seguire questa rotta, non preoccuparti di codificarlo con Base64; basta creare un array C dei valori di byte non elaborati e quindi assegnare "NSData" con quello. Detto questo, funzionerà, ma aumenterà anche le dimensioni del tuo file binario. –

+0

@Dave DeLong. Bene, non avevo pensato di usare un array c. Avresti ancora bisogno di uno strumento per codificare il binario in notazione esadecimale, sì? – TomSwift

+0

Sì, avrai ancora bisogno di uno strumento per generare il codice. –

4

Ok mi sono preso il tempo di mettere insieme un esempio di come è possibile farlo. E 'costruito su @ risposta di TomSwift e questo: http://www.cocoanetics.com/2012/02/xcode-build-rules/

ho caricato un progetto di esempio qui: https://github.com/nielsbot/StaticLibraryXIB

Si aggiunge una regola personalizzata per i file XIB al vostro obiettivo libreria statica. Inserisce un metodo di classe su NSNib che istanzia il tuo XIB ogni volta che viene chiamato. Il metodo è il nome del tuo XIB. Quindi se hai "TestNib.xib", chiameresti +[NSNib TestNib].

Più in dettaglio:

  1. Aggiungi un compilatore personalizzato per i file XIB (Questo è in realtà solo un po 'di script di shell che vogliamo eseguire per ogni file XIB nel progetto)

    a) Nelle regole di build lib statiche, inserisci "XIB" nella casella di ricerca e fai clic sul pulsante "Copia in target" per creare una regola di file XIB nel tuo progetto.

    b) si allontanano processo come "file Interface Builder", impostato utilizzando a "script personalizzato:" Ecco lo script personalizzato:

    /usr/bin/ibtool --output-format human-readable-text --compile "$TARGET_TEMP_DIR/$INPUT_FILE_BASE.nib" "$INPUT_FILE_DIR/$INPUT_FILE_NAME" 
    Hexdump=`hexdump -v -e '1 1 "0x%02x, "' "$TARGET_TEMP_DIR/${INPUT_FILE_BASE}.nib"` 
    Datalength=`stat -f "%z" ${TARGET_TEMP_DIR}/${INPUT_FILE_BASE}.nib` 
    sed -e "s/HEX_DUMP/$Hexdump/g" -e "s/NIB_NAME/${INPUT_FILE_BASE}/g" -e "s/HEX_LENGTH/$Datalength/g" "${SRCROOT}/NibTest/CompiledNibTemplate.m" > "$DERIVED_FILE_DIR/$INPUT_FILE_BASE.nib.m" 
    

    Questo trasformerà i file XIB in file .m che saranno compilati automaticamente nel tuo progetto. Il modello è CompiledNibTemplate.m, che assomiglia a questo:

    #import <Cocoa/Cocoa.h> 
    
    @implementation NSNib (NIB_NAME) 
    
    +(instancetype)NIB_NAME 
    { 
        NSData * data = [ NSData dataWithBytesNoCopy:(void*)(const unsigned char[]){ HEX_DUMP } length:(NSUInteger){ HEX_LENGTH } freeWhenDone:NO ] ; 
        NSNib * result = [ [ NSNib alloc ] initWithNibData:data bundle:nil ] ; 
        return result ; 
    } 
    
    @end 
    
  2. Sulla base del precedente esempio, se il vostro XIB è stato chiamato "StaticLibraryWindowController.xib", NSNib avranno ora un nuovo metodo di classe StaticLibraryWindowController.) Invocazione di [ NSNib StaticLibraryWindowController ] restituirà un oggetto NSNib. Puoi chiamare lo -instantiateWithOwner:topLevelObjects: come qualsiasi altro pennino)

+0

Stavo per andare fuori di testa - e leggere per sporcizia - il post stupido (zoppo/errato) della risposta premiata .. con link e storie sul tuo repository .. e poi ho visto la tua risposta. Buono per te ... Inoltre, su questo argomento c'è anche qualcosa di simile, che consente di incorporare dati in qualsiasi binario, pacchetto, lib ecc.] (Https://github.com/Daij-Djan/DDMountainNotifier /blob/master/MountainNotifier/DDEmbeddedDataReader.h) –

+0

Inoltre, ho sentito che alcune restrizioni sul caricamento dinamico del codice sono state revocate in iOS 8 ... quindi questo potrebbe non essere più applicabile – nielsbot

+0

@alexgray che è davvero bello, grazie. – nielsbot

Problemi correlati