ข้อมูลเบื้องต้นเกี่ยวกับ iCloud และตัวอย่างโค้ด [ปิด]


86

ในฐานะผู้เริ่มต้นฉันกำลังดิ้นรนกับ iCloud มีตัวอย่างอยู่บ้าง แต่โดยปกติแล้วจะมีรายละเอียดค่อนข้างมาก (ในฟอรัมนักพัฒนาจะมีหนึ่งสำหรับ iCloud และ CoreData ซึ่งมีขนาดใหญ่มาก) เอกสารแอปเปิ้ลจะ OK แต่ฉันยังคงไม่สามารถมองเห็นภาพใหญ่ ดังนั้นโปรดอดทนกับฉันคำถามเหล่านี้บางคำถามค่อนข้างพื้นฐาน แต่อาจตอบได้ง่าย

บริบท:ฉันมีแอพ iCloud ที่ใช้งานง่ายมาก (โค้ดตัวอย่างเต็มด้านล่าง) มี UITextView เพียงรายการเดียวที่แสดงต่อผู้ใช้และข้อมูลของเขา / เธอจะถูกบันทึกไว้ในไฟล์ที่เรียกว่า text.txt

ใส่คำอธิบายภาพที่นี่

ไฟล์ txt จะถูกพุชไปยังระบบคลาวด์และพร้อมใช้งานสำหรับทุกอุปกรณ์ ทำงานได้อย่างสมบูรณ์ แต่:

ปัญหาหลัก: แล้วผู้ใช้ที่ไม่ใช้ iCloud ล่ะ?

เมื่อฉันเปิดแอพ (ดูรหัสด้านล่าง) ฉันตรวจสอบว่าผู้ใช้เปิดใช้งาน iCloud หรือไม่ หากเปิดใช้งาน iCloud ทุกอย่างก็เรียบร้อยดี แอปไปข้างหน้าและค้นหา text.txt ในระบบคลาวด์ หากพบก็จะโหลดและแสดงให้ผู้ใช้เห็น หากไม่พบ text.txt ในระบบคลาวด์ระบบจะสร้าง text.txt ใหม่และจะแสดงให้ผู้ใช้เห็น

หากผู้ใช้ไม่ได้เปิดใช้งาน iCloud จะไม่มีอะไรเกิดขึ้น ฉันจะทำให้เป็นไปได้อย่างไรที่ผู้ใช้ที่ไม่ใช่ iCloud จะยังสามารถใช้งานแอพข้อความของฉันได้ หรือว่าฉันเฉยๆ? ฉันจะต้องเขียนฟังก์ชันแยกต่างหากสำหรับผู้ใช้ที่ไม่ใช่ iCloud หรือไม่? ได้แก่ ฟังก์ชันที่ฉันเพียงแค่โหลด text.txt จากโฟลเดอร์เอกสาร?

Apple เขียนว่า :

รักษาไฟล์ใน iCloud แบบเดียวกับที่คุณใช้กับไฟล์อื่น ๆ ทั้งหมดในแซนด์บ็อกซ์ของแอพ

อย่างไรก็ตามในกรณีของฉันไม่มีแซนด์บ็อกซ์ของแอป 'ปกติ' อีกต่อไป มันอยู่ในระบบคลาวด์ หรือฉันมักจะโหลด text.txt จากดิสก์ก่อนจากนั้นตรวจสอบกับ iCloud ว่ามีอะไรที่ทันสมัยกว่านี้หรือไม่?

ปัญหาที่เกี่ยวข้อง: โครงสร้างไฟล์ - แซนด์บ็อกซ์กับคลาวด์

บางทีปัญหาหลักของฉันอาจเป็นความเข้าใจผิดพื้นฐานว่า iCloud ควรจะทำงานอย่างไร เมื่อฉันสร้างอินสแตนซ์ใหม่ของ UIDocument ฉันจะต้องเขียนทับสองวิธี ขั้นแรก- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outErrorให้รับไฟล์จากระบบคลาวด์จากนั้นจึง-(id)contentsForType:(NSString *)typeName error:(NSError **)outErrorจะรับไฟล์เข้าสู่ระบบคลาวด์

ฉันต้องรวมฟังก์ชันแยกต่างหากซึ่งจะบันทึกสำเนา text.txt ในเครื่องลงในแซนด์บ็อกซ์ของฉันด้วยหรือไม่ สิ่งนี้จะใช้ได้กับผู้ใช้ที่ไม่ใช่ iCloud หรือไม่ ตามที่ฉันเข้าใจ iCloud มันจะบันทึกสำเนา text.txt ในเครื่องโดยอัตโนมัติ ดังนั้นฉันจึงไม่จำเป็นต้องบันทึกอะไรลงในแซนด์บ็อกซ์ 'เก่า' ของแอพของฉัน (เช่นที่เคยเป็นในยุคก่อน iCloud) ตอนนี้แซนด์บ็อกซ์ของฉันว่างเปล่าทั้งหมด แต่ฉันไม่รู้ว่าถูกต้องหรือไม่ ฉันควรเก็บ text.txt อีกสำเนาไว้ที่นั่นหรือไม่ สิ่งนี้รู้สึกเหมือนทำให้โครงสร้างข้อมูลของฉันยุ่งเหยิง ... เนื่องจากมี text.txt หนึ่งรายการในคลาวด์หนึ่งรายการในแซนด์บ็อกซ์ iCloud บนอุปกรณ์ของฉัน (ซึ่งจะใช้งานได้แม้ว่าฉันจะออฟไลน์) และอีกอันที่สามในแซนด์บ็อกซ์เก่าที่ดีของ แอพของฉัน ...


รหัสของฉัน: โค้ดตัวอย่างง่ายๆของ iCloud

นี่เป็นไปตามตัวอย่างที่ฉันพบในฟอรัมนักพัฒนาและในวิดีโอเซสชัน WWDC ฉันถอดมันลงจนเหลือน้อยที่สุด ฉันไม่แน่ใจว่าโครงสร้าง MVC ของฉันดีหรือไม่ โมเดลอยู่ใน AppDelegate ซึ่งไม่เหมาะ ข้อเสนอแนะใด ๆ ที่จะทำให้ดีขึ้นยินดีต้อนรับ


แก้ไข: ฉันพยายามแยกคำถามหลักและโพสต์ไว้ [ที่นี่] 4


ภาพรวม:

ภาพรวม

บิตที่สำคัญที่สุดที่โหลด text.txt จากคลาวด์:

//  AppDelegate.h
//  iCloudText

#import <UIKit/UIKit.h>

@class ViewController;
@class MyTextDocument;

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
    NSMetadataQuery *_query;
}

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *viewController;
@property (strong, nonatomic) MyTextDocument *document;

@end

//  AppDelegate.m
//  iCloudText

#import "AppDelegate.h"
#import "MyTextDocument.h"
#import "ViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;
@synthesize document = _document;

- (void)dealloc
{
    [_window release];
    [_viewController release];
    [super dealloc];
}

- (void)loadData:(NSMetadataQuery *)query {

    // (4) iCloud: the heart of the load mechanism: if texts was found, open it and put it into _document; if not create it an then put it into _document

    if ([query resultCount] == 1) {
        // found the file in iCloud
        NSMetadataItem *item = [query resultAtIndex:0];
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:url];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc openWithCompletionHandler:^(BOOL success) {
            if (success) {
                NSLog(@"AppDelegate: existing document opened from iCloud");
            } else {
                NSLog(@"AppDelegate: existing document failed to open from iCloud");
            }
        }];
    } else {
        // Nothing in iCloud: create a container for file and give it URL
        NSLog(@"AppDelegate: ocument not found in iCloud.");

        NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
        NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:@"Documents"] URLByAppendingPathComponent:@"text.txt"];

        MyTextDocument *doc = [[MyTextDocument alloc] initWithFileURL:ubiquitousPackage];
        //_document = doc;
        doc.delegate = self.viewController;
        self.viewController.document = doc;

        [doc saveToURL:[doc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            NSLog(@"AppDelegate: new document save to iCloud");
            [doc openWithCompletionHandler:^(BOOL success) {
                NSLog(@"AppDelegate: new document opened from iCloud");
            }];
        }];
    }
}

- (void)queryDidFinishGathering:(NSNotification *)notification {

    // (3) if Query is finished, this will send the result (i.e. either it found our text.dat or it didn't) to the next function

    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];

    [self loadData:query];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
    _query = nil; // we're done with it
}

-(void)loadDocument {

    // (2) iCloud query: Looks if there exists a file called text.txt in the cloud

    NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
    _query = query;
    //SCOPE
    [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
    //PREDICATE
    NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, @"text.txt"];
    [query setPredicate:pred];
    //FINISHED?
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
    [query startQuery];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"AppDelegate: app did finish launching");
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil] autorelease];
    } else {
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil] autorelease];
    }

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    // (1) iCloud: init

    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if (ubiq) {
        NSLog(@"AppDelegate: iCloud access!");
        [self loadDocument];
    } else {
        NSLog(@"AppDelegate: No iCloud access (either you are using simulator or, if you are on your phone, you should check settings");
    }


    return YES;
}

@end

เอกสาร UID

//  MyTextDocument.h
//  iCloudText

#import <Foundation/Foundation.h>
#import "ViewController.h"

@interface MyTextDocument : UIDocument {

    NSString *documentText;
    id delegate;

}

@property (nonatomic, retain) NSString *documentText;
@property (nonatomic, assign) id delegate;

@end

//  MyTextDocument.m
//  iCloudText

#import "MyTextDocument.h"
#import "ViewController.h"

@implementation MyTextDocument

@synthesize documentText = _text;
@synthesize delegate = _delegate;

// ** READING **

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError
{
    NSLog(@"UIDocument: loadFromContents: state = %d, typeName=%@", self.documentState, typeName);

    if ([contents length] > 0) {
        self.documentText = [[NSString alloc] initWithBytes:[contents bytes] length:[contents length] encoding:NSUTF8StringEncoding];
    }
    else {
        self.documentText = @"";
    }

    NSLog(@"UIDocument: Loaded the following text from the cloud: %@", self.documentText);


    // update textView in delegate...
    if ([_delegate respondsToSelector:@selector(noteDocumentContentsUpdated:)]) {
        [_delegate noteDocumentContentsUpdated:self];
    }

    return YES;

}

// ** WRITING **

-(id)contentsForType:(NSString *)typeName error:(NSError **)outError
{
    if ([self.documentText length] == 0) {
        self.documentText = @"New Note";
    }

    NSLog(@"UIDocument: Will save the following text in the cloud: %@", self.documentText);

    return [NSData dataWithBytes:[self.documentText UTF8String] length:[self.documentText length]];
}
@end

VIEWCONTROLLER

//
//  ViewController.h
//  iCloudText

#import <UIKit/UIKit.h>

@class MyTextDocument;

@interface ViewController : UIViewController <UITextViewDelegate> {

    IBOutlet UITextView *textView;

}

@property (nonatomic, retain) UITextView *textView;
@property (strong, nonatomic) MyTextDocument *document;

-(void)noteDocumentContentsUpdated:(MyTextDocument *)noteDocument;

@end

//  ViewController.m
//  iCloudText

#import "ViewController.h"
#import "MyTextDocument.h"

@implementation ViewController

@synthesize textView = _textView;
@synthesize document = _document;

-(IBAction)dismissKeyboard:(id)sender {

    [_textView resignFirstResponder];

}

-(void)noteDocumentContentsUpdated:(MyTextDocument *)noteDocument
{
    NSLog(@"VC: noteDocumentsUpdated");
    _textView.text = noteDocument.documentText;
}

-(void)textViewDidChange:(UITextView *)theTextView {

     NSLog(@"VC: textViewDidChange");
    _document.documentText = theTextView.text;
    [_document updateChangeCount:UIDocumentChangeDone];

}

4
ฉันขอแนะนำให้แยกคำถามออกเป็นสองสามคำถาม ฉันเห็นคำถามที่แตกต่างกันสองสามข้อฝังอยู่ที่นี่และเป็นการยากที่จะเลือกมันออกมาในผนังข้อความที่คุณมีที่นี่ ฉันจะเปลี่ยนคำถามนี้กลับไปเป็นเพียงแค่ถามว่าจะทำอย่างไรสำหรับคนที่ไม่ได้เปิดใช้งาน iCloud และแยกส่วนอื่น ๆ (เฉพาะส่วนที่เกี่ยวข้องของโค้ดตัวอย่างของคุณ) ออกเป็นคำถามแยก เป็นคำถามที่ดี แต่ฉันคิดว่าควรแยกออก
Brad Larson

@BradLarson ขอบคุณสำหรับความคิดเห็นของคุณ ขออภัยหากคำถามสับสนเล็กน้อย แต่ฉันคิดว่าคำถามหลัก (ตามที่ฉันพยายามระบุ) คือปัญหาแซนด์บ็อกซ์ของแอปกับปัญหาแซนด์บ็อกซ์ของ iCloud ฉันให้รหัสเต็ม (ซึ่งเป็นตัวอย่างรหัส iCloud ที่สั้นที่สุด btw) ตามที่ฉันคิดว่าบริบททั้งหมดมีความสำคัญที่จะต้องรู้ว่าเกิดอะไรขึ้น ... แต่ฉันอาจจะเปิดคำถามอื่นและเชื่อมโยงกลับไปที่คำถามนี้เพื่อ รับภาพใหญ่ขึ้น
n.evermind

@BradLarson ตกลงฉันเปิดคำถามใหม่ที่นี่: stackoverflow.com/questions/7798555/…
n.evermind

สำหรับผู้ที่ยังคงพยายามจัดการ Core Data และ iCloud ลองใช้ลิงค์นี้ossh.com.au/design-and-technology/software-development/…
Duncan Groenewald

ไม่ควรปิดนี่เป็นหนึ่งในโพสต์ที่สร้างสรรค์กว่าที่ฉันเคยเห็นใน iCloud ..
Andrew Smith

คำตอบ:


22

ฉันเพิ่งอ่านเอกสารอีกครั้งและดูเหมือนว่าแนวทางทั่วไปของฉันไม่ถูกต้อง ฉันควรสร้างไฟล์ในแซนด์บ็อกซ์ก่อนแล้วจึงย้ายไปที่คลาวด์ กล่าวอีกนัยหนึ่งดูเหมือนว่า Apple จะแนะนำว่าฉันควรมีไฟล์เดียวกันสามเวอร์ชันตลอดเวลา: หนึ่งไฟล์ในไดเร็กทอรีของแอพของฉันหนึ่งในไดเร็กทอรีปีศาจ iCloud ของอุปกรณ์ของฉัน (ซึ่งสามารถเข้าถึงได้หากออฟไลน์) และอีกหนึ่งไฟล์ใน เมฆ:

แอพใช้เทคโนโลยีเดียวกันในการจัดการไฟล์และไดเร็กทอรีใน iCloud ที่ใช้กับไฟล์และไดเร็กทอรีในเครื่อง ไฟล์และไดเร็กทอรีใน iCloud ยังคงเป็นเพียงไฟล์และไดเร็กทอรี คุณสามารถเปิดสร้างย้ายคัดลอกอ่านและเขียนลบหรือดำเนินการอื่น ๆ ที่คุณอาจต้องการทำ ความแตกต่างเพียงอย่างเดียวระหว่างไฟล์และไดเร็กทอรีในเครื่องและไฟล์และไดเร็กทอรี iCloud คือ URL ที่คุณใช้ในการเข้าถึง แทนที่จะเป็น URL ที่สัมพันธ์กับแซนด์บ็อกซ์ของแอปของคุณ URL สำหรับไฟล์และไดเรกทอรี iCloud จะสัมพันธ์กับไดเรกทอรีคอนเทนเนอร์ iCloud ที่เกี่ยวข้อง

ในการย้ายไฟล์หรือไดเรกทอรีไปยัง iCloud:

สร้างไฟล์หรือไดเรกทอรีในเครื่องในแซนด์บ็อกซ์ของแอป ขณะใช้งานไฟล์หรือไดเร็กทอรีต้องได้รับการจัดการโดยผู้นำเสนอไฟล์เช่นอ็อบเจ็กต์ UIDocument

ใช้เมธอด URLForUbiquityContainerIdentifier: เพื่อดึง URL สำหรับไดเร็กทอรีคอนเทนเนอร์ iCloud ที่คุณต้องการจัดเก็บรายการ ใช้ URL ไดเร็กทอรีคอนเทนเนอร์เพื่อสร้าง URL ใหม่ที่ระบุตำแหน่งของรายการใน iCloud เรียกใช้ setUbiquitous: itemAtURL: destinationURL: error: method ของ NSFileManager เพื่อย้ายรายการไปยัง iCloud อย่าเรียกวิธีนี้จากเธรดหลักของแอปของคุณ การทำเช่นนั้นอาจบล็อกเธรดหลักของคุณเป็นระยะเวลานานหรือทำให้เกิดการหยุดชะงักกับหนึ่งในผู้นำเสนอไฟล์ของแอปของคุณเอง เมื่อคุณย้ายไฟล์หรือไดเร็กทอรีไปที่ iCloud ระบบจะคัดลอกรายการนั้นออกจากแซนด์บ็อกซ์ของแอพของคุณและลงในไดเร็กทอรีส่วนตัวเพื่อให้สามารถตรวจสอบได้โดย iCloud daemon แม้ว่าไฟล์จะไม่อยู่ในแซนด์บ็อกซ์ของคุณแล้ว แต่แอปของคุณก็ยังสามารถเข้าถึงไฟล์ได้อย่างเต็มที่ แม้ว่าสำเนาของไฟล์จะยังคงอยู่ในอุปกรณ์ปัจจุบัน แต่ไฟล์จะถูกส่งไปยัง iCloud เพื่อให้สามารถแจกจ่ายไปยังอุปกรณ์อื่นได้ iCloud daemon จัดการงานทั้งหมดเพื่อให้แน่ใจว่าสำเนาในเครื่องเหมือนกัน ดังนั้นจากมุมมองของแอพของคุณไฟล์ก็อยู่ใน iCloud

การเปลี่ยนแปลงทั้งหมดที่คุณทำกับไฟล์หรือไดเร็กทอรีใน iCloud ต้องทำโดยใช้ออบเจ็กต์ตัวประสานไฟล์ การเปลี่ยนแปลงเหล่านี้รวมถึงการย้ายการลบการคัดลอกหรือการเปลี่ยนชื่อรายการ ผู้ประสานงานไฟล์ตรวจสอบให้แน่ใจว่า iCloud daemon ไม่เปลี่ยนไฟล์หรือไดเร็กทอรีในเวลาเดียวกันและตรวจสอบให้แน่ใจว่าผู้สนใจรายอื่นได้รับแจ้งการเปลี่ยนแปลงที่คุณทำ

อย่างไรก็ตามหากคุณเจาะลึกลงไปในเอกสารเกี่ยวกับ setUbiquitous คุณจะพบ:

ใช้วิธีนี้เพื่อย้ายไฟล์จากตำแหน่งปัจจุบันไปยัง iCloud สำหรับไฟล์ที่อยู่ในกระบะทรายของโปรแกรมประยุกต์นี้เกี่ยวข้องกับร่างกายลบไฟล์จากไดเรกทอรี Sandbox ที่ (ระบบจะขยายสิทธิ์แซนด์บ็อกซ์ของแอปพลิเคชันของคุณเพื่อให้เข้าถึงไฟล์ที่ย้ายไปยัง iCloud) คุณยังสามารถใช้วิธีนี้เพื่อย้ายไฟล์ออกจาก iCloud และกลับเข้าสู่ไดเร็กทอรีภายใน

ดังนั้นสิ่งนี้จึงดูเหมือนหมายความว่าไฟล์ / ไดเร็กทอรีถูกลบออกจากแซนด์บ็อกซ์ในเครื่องและย้ายไปยังคลาวด์


1
ลิงค์ url เสีย ...
ngb

5

ฉันใช้ตัวอย่างของคุณมาตลอดและฉันชอบที่ช่วยให้ฉันเข้าใจพื้นฐานของ iCloud ตอนนี้ฉันกำลังทะเลาะกับคำถามของคุณเกี่ยวกับแอพของฉันเองซึ่งต้องรองรับผู้ใช้ที่มีอยู่ของแอพที่มีเนื้อหาที่เก็บไว้ในเครื่องซึ่งอาจใช้ iCloud หรือไม่ก็ได้สร้างเคสเหล่านี้เท่าที่ฉันจะบอกได้:

กรณี:

  1. ผู้ใช้ใหม่
    • มี icloud - สร้างเอกสารใน icloud
    • ไม่มี icloud - สร้างเอกสารในเครื่อง
  2. ผู้ใช้ที่มีอยู่
    • มี icloud
      • เพิ่งเพิ่ม - ย้ายเอกสารในเครื่องไปที่ icloud
      • ไม่เพียงแค่เพิ่ม - เปิด / บันทึกเอกสารไปที่ icloud
    • ไม่มี icloud
      • เพิ่งลบออก - ย้ายเอกสาร icloud เดิมไปยังท้องถิ่น
      • ไม่เพียงแค่ลบ - เปิด / บันทึกเอกสารลงในเครื่อง

หากมีคนลบ iCloud - การโทรไปยัง URL ที่แพร่หลายจะไม่ส่งคืนศูนย์หรือไม่? หากเป็นเช่นนั้นฉันจะย้ายเอกสารกลับไปยังที่จัดเก็บในตัวเครื่องได้อย่างไร ตอนนี้ฉันจะสร้างคำนำหน้าผู้ใช้ แต่ดูเหมือนจะเป็นวิธีแก้ปัญหาเล็กน้อย

ฉันรู้สึกว่าตัวเองขาดอะไรบางอย่างที่เห็นได้ชัดที่นี่ดังนั้นหากใครสามารถเห็นได้โปรดส่งเสียงเข้า


ฉันควรเพิ่มว่าฉันสงสัยว่ามีคลาสที่จัดการกรณีเหล่านี้หรือไม่ดังนั้นฉันจึงใช้มันและไม่ต้องกังวลว่าจะบันทึกไว้ที่ไหน
earnshavian

ลองดูที่developer.apple.com/library/ios/#documentation/DataManagement/…ซึ่งจะให้โค้ดตัวอย่างเพื่อพิจารณาว่าควรใส่บางสิ่งลงในแซนด์บ็อกซ์ในเครื่องหรือระบบคลาวด์
n.evermind

ขอบคุณสำหรับสิ่งนั้น ฉันเห็นเอกสารนั้น แต่ก่อนหน้านี้ในภารกิจ iCloud ของฉันดังนั้นฉันจึงลืมรหัสที่เสนอ ฉันจะพยายามปรับตัวอย่างของคุณให้รองรับท้องถิ่นและระยะไกล ฉันยังไม่ชัดเจนว่าเราจัดการกับผู้ใช้ที่ปิดใช้งาน iCloud อย่างไรเนื่องจากเราสูญเสีย URL ที่แพร่หลาย แต่ฉันจะมีรอยแตกและแชร์การอัปเดต
earnshavian

1
ดังนั้นในทางหนึ่งมันค่อนข้างโง่ที่เราต้องใช้ URL สำหรับคลาวด์และ PATH สำหรับแซนด์บ็อกซ์ในเครื่อง คงจะดีไม่น้อยหาก iCloud สามารถจัดการทุกอย่างให้เราได้ ... แต่วิธีนี้โดยพื้นฐานแล้วเราต้องใช้วิธีการสองแบบสำหรับทุกไฟล์ที่เราเปิด
n.evermind

ฉันเพิ่งอ่านโพสต์ของคุณอีกครั้ง ตอนนี้ฉันกำลังบันทึกค่ากำหนดของผู้ใช้ (เช่นผู้ใช้ต้องการ / ไม่ต้องการใช้ iCloud) ใน NSUserDefaults นี่คือสิ่งที่ Apple แนะนำเช่นกัน ฉันตรวจสอบอยู่เสมอว่าสามารถเข้าถึง iCloud ได้หรือไม่ หากไม่สามารถเข้าถึงได้ฉันจะบอกให้ผู้ใช้เปิดใช้งาน - แต่ถ้าพวกเขาไม่ได้บอกแอปอย่างชัดเจนว่าไม่ต้องการใช้ มิฉะนั้นจะน่ารำคาญสำหรับผู้ที่ไม่ต้องการใช้ iCloud เมื่อฉันพิจารณาแล้วว่าเปิดใช้งาน iCloud หรือไม่ฉันจะทำตามเส้นทาง URL ที่แพร่หลายและใช้ UIDocument หรือเพียงแค่เปิดไฟล์จากแซนด์บ็อกซ์เหมือนในสมัยก่อน
n.evermind

4

หากคุณต้องการให้ผู้ใช้สามารถแชร์ข้อความระหว่างอุปกรณ์ที่เป็นรุ่นก่อน iOS 5.0 ได้คุณจะต้องทำสิ่งที่ทุกคนต้องทำก่อน iCloud และย้ายข้อมูลไปยังเซิร์ฟเวอร์ของคุณเอง

สิ่งที่คุณต้องการจริงๆคือเซิร์ฟเวอร์ที่ให้แอปของคุณบันทึกไฟล์ข้อความและเชื่อมโยงกับบัญชีผู้ใช้

คุณจะต้องให้ผู้ใช้สร้างบัญชีและคุณจะต้องจัดการกระบวนการด้วยตัวเองในการย้ายข้อมูลใหม่บนอุปกรณ์หนึ่งไปยัง 'คลาวด์' ของคุณเอง

ผู้ใช้จะลงทะเบียนด้วยบัญชีเดียวกันบนอุปกรณ์อื่น ๆ และคุณจะต้องดูแลตรวจจับเมื่ออุปกรณ์อื่นย้ายข้อมูลไปยังคลาวด์ของคุณเองและอัปเดตอุปกรณ์ปัจจุบันด้วยข้อมูลใหม่

เห็นได้ชัดว่าสำหรับอุปกรณ์ iOS 5.0 คุณอาจต้องการตรวจจับไฟล์ที่เปลี่ยนแปลงสำหรับอุปกรณ์ก่อน iOS 5.0 ในระบบคลาวด์ของคุณเองและยังสามารถพูดคุยกับ iCloud ได้


ขอบคุณ. กล่าวอีกนัยหนึ่งคือถ้าฉันไม่ต้องการรองรับอุปกรณ์ก่อน iOS 5 ฉันก็แค่ไปกับ UIDocument และลืมเนื้อหาของไดเรกทอรี doc ในแซนด์บ็อกซ์ของแอปของฉัน
n.evermind

แม้ว่าเท่าที่ฉันบอกได้คุณจะยังคงมีเอกสารในแซนด์บ็อกซ์ซึ่ง UIDocument จะช่วยเป็นสื่อกลางกับ iCloud ให้กับคุณ แต่คุณจะได้รับแจ้งเมื่อคุณสามารถเข้าถึงได้ ... ฉันยังคงได้รับ จับสิ่งนี้ด้วยตัวเอง!
Jonathan Watmough

3

ดูเหมือนว่าคุณจะไม่ประสบปัญหา iCloud / notICloud เท่ากับปัญหา iOS5 / notIOS5

หากเป้าหมายการปรับใช้ของคุณคือ iOS5 ให้ใช้โครงสร้าง UIDocument เสมอ หากเป็นที่แพร่หลาย NSMetaDataQuery ของคุณจะพบในระบบคลาวด์ หากไม่พบจะพบในอุปกรณ์

ในทางกลับกันหากคุณต้องการให้การเข้าถึงแอปของคุณก่อน 5.0 คุณจะต้องตรวจสอบตามเงื่อนไขเพื่อดูว่า iOS ที่ใช้งานอยู่คือ 5.0 หรือสูงกว่าหรือไม่ ถ้าเป็นเช่นนั้นให้ใช้ UIDocument; ถ้าไม่เช่นนั้นอ่าน / เขียนข้อมูลด้วยวิธีเก่า

วิธีการของฉันคือการเขียนวิธี saveData แบบมีเงื่อนไขที่ตรวจสอบ iOS5 หากมีอยู่ฉันจะอัปเดตจำนวนการเปลี่ยนแปลง (หรือใช้ตัวจัดการการเลิกทำ) ในกรณีของคุณ textViewDidChange จะเรียกเมธอดนี้ ถ้าไม่เช่นนั้นจะบันทึกลงในดิสก์ด้วยวิธีเก่า ในการโหลดสิ่งที่ตรงกันข้ามจะเกิดขึ้น


1

คุณสับสนกับ "จัดการไฟล์ใน iCloud แบบเดียวกับที่คุณจัดการกับไฟล์อื่น ๆ ทั้งหมดในแซนด์บ็อกซ์ของแอป" สิ่งนี้ถือเป็นจริงสำหรับบางสิ่งเช่น Keynote และ Numbers ที่คุณเก็บไฟล์ไว้เป็นจำนวนมากและหากคุณมี iCloud พวกเขาจะเริ่มการซิงค์อย่างน่าอัศจรรย์

อย่างไรก็ตามคุณกำลังสร้างบางสิ่งที่ขึ้นอยู่กับฟังก์ชันที่คล้ายกับ iCloud คุณไม่สามารถยึดมั่นในคำพูดนั้นได้เนื่องจากแอปของคุณขึ้นอยู่กับ iCloud เพื่อให้ทุกอย่างทำงานได้ตามที่ตั้งใจไว้ คุณจะต้องปิดแอปของคุณและพูดเพียงว่า "โปรดตั้งค่า iCloud เพื่อให้สิ่งนี้ใช้งานได้" หรือทำซ้ำฟังก์ชันที่คล้ายกับ iCloud (ของคุณเองหรือของคนอื่น) ที่คุณสามารถใช้ได้ตลอดเวลา


ขอบคุณ. ดังนั้นฉันเดาว่าฉันต้องเลือกว่าฉันจะทำแอพ iCloud เท่านั้นหรือไฮบริดบางประเภทสำหรับคนที่เปลี่ยนฟังก์ชัน iCloud เนื่องจาก iCloud มีความซับซ้อนมากฉันจึงมักจะใช้เฉพาะแอป iCloud เท่านั้น ขอบคุณ.
n.evermind
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.