Domanda

Sono consapevole che iOS ha API per integrare iCloud per le app. Posso integrare iCloud anche nelle app MAC? L'implementazione sarà diversa per le app MAC per integrare iCloud? Se sì, ci sono tutorial ecc. O siti Web di riferimento?

È stato utile?

Soluzione

Sì. iCloud è disponibile sul Mac.
Ma la documentazione di Apple per questo argomento non è ancora molto completa. Le uniche risorse ufficiali che ho potuto trovare dove il WWDC 2011 Video sessione 107 e alcune note in "Cosa c'è di nuovo in Mac OS X"

Quando Lion e iCloud erano ancora sotto la NDA, ho pubblicato i miei risultati in Devforums di Apple.
Questa è una versione modificata di questo post:

Sto usando una versione modificata del codice sessione 107 WWDC 2011. (trascritto dal video) Ho dovuto rimuovere l'istanziazione manuale di NSFileCoordinator per far funzionare il campione (l'altoparlante menziona che il coordinatore "potrebbe non essere necessario in futuro"):

- (IBAction)moveToOrFromCloud:(id)sender
{
     NSFileManager* fm = [NSFileManager defaultManager];
     NSURL* fileURL = [[self document] fileURL];
     BOOL shouldMakeUbiquitous = [sender tag] == 1;
     NSURL* destinationURL;
     if(shouldMakeUbiquitous)
     {
          NSURL* rootURL = [fm URLForUbiquityContainerIdentifier:@"app.example"];
          NSURL* directoryURL = [rootURL URLByAppendingPathComponent:@"Documents"];
          [fm createDirectoryAtURL:directoryURL withIntermediateDirectories:NO attributes:nil error:NULL];
          destinationURL = [directoryURL URLByAppendingPathComponent:[fileURL lastPathComponent]];
     }
     else
     {
          destinationURL = [[[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:[fileURL lastPathComponent]];
     }
     NSError* error;
     if(![fm setUbiquitous:shouldMakeUbiquitous itemAtURL:fileURL destinationURL:destinationURL error:&error])
     {
          [[self document] presentError:error modalForWindow:[[self document] windowForSheet] delegate:nil didPresentSelector:NULL contextInfo:NULL];
     }
     else
     {
          [[self document] setFileURL:destinationURL];
          [[self document] setFileModificationDate:nil];
     }
}

L'ibaction sopra è collegata a un nsmenuuiteem che controlla se il documento è già in iCloud o se deve essere caricato:

- (BOOL)validateMenuItem:(NSMenuItem*)item 
{
     SEL action = [item action];
     if (action == @selector(moveToOrFromCloud:))
     {
          BOOL isUbiquitous = [[NSFileManager defaultManager] isUbiquitousItemAtURL:[[self document] fileURL]];
          [item setTitle:isUbiquitous ? @"Remove from Cloud": "Move to Cloud"];
          [item setTag:isUbiquitous?0:1];
          return [self.document fileURL] != nil;
     }    
     return YES;
}

Elenco di controllo per le attività non codi necessarie per far funzionare l'archiviazione dei documenti iCloud:

  • Controlla se il supporto iCloud è attivato nell'utilità del certificato sviluppatore
  • Crea un ID contenitore di ubiquità nell'utilità del certificato sviluppatore
  • L'ID contenitore di ubiquità inizia con l'ID/ID individuale della squadra (consultare la scheda Account nel Centro membro)
  • Abilita i diritti in Xcode
  • Aggiungi il tuo ID contenitore di ubiquità al file di entitlements (come descritto qui "Richiesta di entitlements per l'archiviazione iCloud.")
  • Il mio ID plist bundle ha dovuto abbinare l'ID del contenitore dell'ubiquità (ad eccezione dell'ID della squadra)
  • Non sono stato in grado di aggiungere suffissi (ad esempio "app.example.osx", "app.example.ipad", ... come suggerito nel documento sopra)
  • Crea un profilo di provisioning
  • Assicurati che il profilo sia installato sulla macchina Dev e venga visualizzato nelle preferenze di Xcode & System
  • Abilita la registrazione del codice nelle impostazioni di build delle tue app

Altri suggerimenti

C'è un documento di Apple che è gravemente dettagliato in tutti gli aspetti http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/icloud/icloud.html

Un problema significativo con il codice pubblicato qui è che non ha il team nell'identificatore dato a URLFORUBIQUITYCONTAINERIDIFIESIFIER Anche se è menzionato nella lista di controllo, lasciandolo nullo di essere automaticamente riempito dai diritti sembra il miglior approccio.

Personalmente le uniche modifiche che dovevo fare per far entrare iCloud nella mia app erano:

  1. Controlla il pulsante "Usa iCloud" sul sito Web sviluppatore per il mio ID app
  2. Scarica la disposizione rigenerata per quell'ID app
  3. Controlla "Abilita entitlements" nel riepilogo Xcode

Questo è stato tutto, ecco un codice di esempio più chiaro (dovrebbe funzionare sia per iOS che per OSX):

NSURL *url = [self getiCloudURLFor:@"foo.bar" containerID:nil]; //leaving nil so it is auto filled from entitlements
if (url) {
    NSError *error;
    if (![[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:url error:&error]) {
        NSLog(@"Error downloading/syncing %@ (%@)",[url path],[error description]);                
    }else{
        NSLog(@"Started downloading/syncing %@",[url path]);              
    }         
}

NSArray *conflicts = [NSFileVersion unresolvedConflictVersionsOfItemAtURL:url];
for (NSFileVersion *conflict in conflicts) {
    NSLog(@"Conflicting %@ at %@ by %@ from %@",[url path],[conflict URL],[conflict localizedNameOfSavingComputer],[conflict modificationDate]);   
}

- (NSURL*)getiCloudURLFor:(NSString*)fileName containerID:(NSString*)containerID
{   
    NSFileManager *fm = [NSFileManager defaultManager];  

    NSURL *rootURL = [fm URLForUbiquityContainerIdentifier:containerID];
    if (rootURL) {
        NSURL *directoryURL = [rootURL URLByAppendingPathComponent:@"Documents"];
        if (![fm fileExistsAtPath:[directoryURL path]]) [fm createDirectoryAtURL:directoryURL withIntermediateDirectories:NO attributes:nil error:NULL];
        NSURL *cloudURL = [directoryURL URLByAppendingPathComponent:fileName];
        if (![fm isUbiquitousItemAtURL:cloudURL]) [self makeUbiquitousItemAtURL:cloudURL];//this only runs once per filename when it is first added to iCloud
        return cloudURL;
    }else{
        return [[[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:fileName]; //no cloud
    }     
    return nil;
}

- (void)makeUbiquitousItemAtURL:(NSURL*)cloudURL
{
    NSFileManager *fm = [NSFileManager defaultManager];

    NSURL *localURL = [[[fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] URLByAppendingPathComponent:[cloudURL lastPathComponent]]; 
    if (![fm fileExistsAtPath:[localURL path]]) [fm createFileAtPath:[localURL path] contents:nil attributes:nil];
    NSError *error;            
    if(![fm setUbiquitous:YES itemAtURL:localURL destinationURL:cloudURL error:&error])  {
        NSLog(@"Error making %@ ubiquituous at %@ (%@)",[localURL path],[cloudURL path],[error description]);
    }else{
        NSLog(@"Made %@ ubiquituous at %@",[localURL lastPathComponent],[cloudURL path]);               
    }      
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top