iOS 8 CoreData iCloud同步一致性问题

时间:2015-06-21 16:39:17

标签: swift core-data icloud

我有一个使用xCode 6.3.2在Swift中编写的通用应用程序。目前非常简单,当我按下按钮时,会生成随机数,然后使用CoreData进行存储。在我实施iCloud之前,这非常有效。启用iCloud后,存储新的随机数并不会传播到其他设备上。它大部分时间都有,但并非总是如此。

我正在使用iPad Air,iPhone 6 Plus和iPhone 4s进行测试

我使用以下三个通知观察员:

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "persistentStoreDidChange", name: NSPersistentStoreCoordinatorStoresDidChangeNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "persistentStoreWillChange:", name: NSPersistentStoreCoordinatorStoresWillChangeNotification, object: managedContext.persistentStoreCoordinator)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "receiveiCloudChanges:", name: NSPersistentStoreDidImportUbiquitousContentChangesNotification, object: managedContext.persistentStoreCoordinator)

这是第三个函数:

func receiveiCloudChanges(notification: NSNotification)
{
    println("iCloud changes have occured")
    dispatch_async(dispatch_get_main_queue())
        {
            self.activityIndicator.startAnimating()
            self.updateLabel.text = "iCloud changes have occured"

            self.managedContext.performBlockAndWait
                { () -> Void in
                    self.managedContext.mergeChangesFromContextDidSaveNotification(notification)
                }
            self.reloadTextViewAndTableView()
            self.activityIndicator.stopAnimating()
        }
}

我没有尝试更新UI,直到managedContext完成合并,我正在主线程上执行所有操作。我真的不知道为什么一台设备上的更改只在90-95%的时间内显示在第二个或第三个设备上。

作为我的试验和错误的一部分,当我从我的测试设备中删除应用程序并重新安装时,有时会显示iCloud操作正在等待的消息,但是我等待多久并不重要设备不同步他们保持这种方式。即使它们不同步,如果我添加另外一个或两个仍然会传播到其他设备,但随后我将丢失更多的数据。它似乎在90%的时间内起作用。

我使用以下内容更新UI:

func reloadTextViewAndTableView()
{
    let allPeopleFetch = NSFetchRequest(entityName: "Person")
    var error : NSError?
    let result = managedContext.executeFetchRequest(allPeopleFetch, error: &error) as! [Person]?

    //Now reload the  textView by grabbing every person in the DB and appending it to the textView
    textView.text = ""
    allPeople = managedContext.executeFetchRequest(allPeopleFetch, error: &error) as! [Person]
    for dude in allPeople
    {
        textView.text = textView.text.stringByAppendingString(dude.name)
    }
    tableView.reloadData()
    println("allPeople.count = \(allPeople.count)")
}

我真的站在这里。我只是不确定为什么它"通常"工程...

1 个答案:

答案 0 :(得分:0)

所以我仍然不确定CoreData有时或为什么有时会失去同步,如上所述。我发现,如果我一个接一个地输入一个新的数字很快就会发生。

作为一种解决方法,我在UI中添加了一个按钮,允许用户通过使用以下选项重建NSPersistentStore来强制重新同步iCloud。

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;


public class HTML2PDF { 
class Watermark extends PdfPageEventHelper{
        //font for watermarking text
        Font font = new Font(FontFamily.HELVETICA, 52, Font.ITALIC, new GrayColor(.75f));
        public void onEndPage(PdfWriter writer, Document document){
            ColumnText.showTextAligned(writer.getDirectContentUnder(), 
                    Element.ALIGN_CENTER, 
                    new Phrase("Watermarking Text", font), 
                    297.5f, 421,-45);//-45 specifies the angle of Watermarking Text
        }
    }

    public void convertHTML2PDF(){
        //Create objects of Document and specify the Page size of a PDF
        Document document = new Document(PageSize.A4);
        try{
            PdfWriter pdfWriter;
            //get the instance of class PdfWriter with the document objects and output path
            pdfWriter = PdfWriter.getInstance(document, new FileOutputStream("/opt/remedy/html2any-cmd-linux/bin/test.pdf"));
            //setting the Watermarking in the PageEvent of PdfWriter
            pdfWriter.setPageEvent(new Watermark());
            document.open();

            String htmlContent = "";
            BufferedReader in = new BufferedReader(new FileReader("/opt/remedy/html2any-cmd-linux/bin/WO00000001004641434460592596_1.html"));
            String temp;
            //read the html files content and stores it in a String variable
            while((temp = in.readLine())!=null){
                htmlContent += temp;
            }
            in.close();
            XMLWorkerHelper xmlWorker = XMLWorkerHelper.getInstance();
            // converts the html into a PDF
            xmlWorker.parseXHtml(pdfWriter, document, new StringReader(htmlContent));
            document.close();

        } 
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    //main method
    public static void main(String[] args){
        new HTML2PDF().convertHTML2PDF();
    }

}

我宁愿商店一直与所有其他设备保持同步,但至少这样用户永远不会丢失数据。如果他们发现他们错过了他们知道他们在其他设备上输入的记录,那么他们所要做的就是点击重新同步按钮。