在 Swift 中,如何停止所有进程,直到从 UICOLLECTIONVIEW 中的 parse.com 检索到数据 [英] In Swift, how to stop all the process until datas retrieved from parse.com in UICOLLECTIONVIEW

查看:18
本文介绍了在 Swift 中,如何停止所有进程,直到从 UICOLLECTIONVIEW 中的 parse.com 检索到数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 CollectionView 中,我显示来自 parse.com 的数据.成功找回.但无法在单元格中显示.我收到错误为数组出站.我发现了错误,解析以异步方式运行.但是,在解析结束之前,集合视图被加载.所以我无法在单元格中显示值.它正在抛出一个错误.如何停止所有过程,直到解析完全加载?请指导我.我的代码如下:

//VIEWCONTROLLER 有 collectionViewvar myList : NSArray = NSArray()让 obj_par = parse_retrive()obj_par.parse_DB()//要从PARSE中检索的数据story_collection_view.reloadData()//重新加载集合视图func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) ->UICollectionViewCell {println("第五个")if(collectionView == date_collection_view){::返回单元格}别的{var cell = collectionView.dequeueReusableCellWithReuseIdentifier("story_read", forIndexPath: indexPath) as story_reading_cellcell.story_title.text = myList.objectAtIndex(indexPath.row) as?字符串//错误:索引的数组出站返回单元格}}

//PARSE_RETRIVE 类

func parse_DB() {println("第二个 10")par_query.findObjectsInBackgroundWithBlock({(NSArray objects, NSError error) in如果(错误!= nil){NSLog("错误" + error.localizedDescription)}别的 {println("第二个 13")let sql_store_obj1 = sql_to_store()//第三类self.parse_obj_arr = NSArray(数组:对象)var j : Int = self.parse_obj_arr.countfor (var i : Int = 0; i < j; i++) {self.par_object = self.parse_obj_arr.objectAtIndex(i) 作为 PFObjectself.sto = self.par_object["story_title"] as String//STORY TITLE FROM PARSEself.sto_con = self.par_object["story_content"] as String//STORY CONTENT FROM PARSEself.sto_tit.append(self.sto)//存储在数组VARself.sto_cont.append(self.sto_con)//存储在数组VAR中}//结束sql_store_obj1.sto_title_arr = self.sto_titsql_store_obj1.sto_content_arr = self.sto_contsql_store_obj1.parse_to_sql()}//其他结束})//解析查询结束println("第二")}

//第三类

func parse_to_sql() {让 appDel : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate让上下文:NSManagedObjectContext = appDel.managedObjectContext!let ent = NSEntityDescription.entityForName("Sad", inManagedObjectContext: context)var newStory = story_sad_managed(entity: ent!, insertIntoManagedObjectContext: context)newStory.story_title = sto_title_arrnewStory.story_content = sto_content_arr让请求 = NSFetchRequest(实体名称:故事")request.predicate = NSPredicate(格式:"story_title = %@", sto_title_arr)结果 = context.executeFetchRequest(request, error: nil)!让 sto_page_obj = story_page()sto_page_obj.myList = result//第一类数组}

解决方案

注意:所有代码都在 Objective-C 中,但此特定代码的翻译应该是微不足道的.如果有人想编辑我的帖子以包含 Swift 代码,请随意,但请将 Objective-C 留在帖子中.

我所做的(对于UICollectionViewUITableView)是创建一个属性,通常称为isLoading,如下所示:

@property (assign, nonatomic) BOOL isLoading;

我通常这样初始化它:

- (void)viewDidLoad {[超级viewDidLoad];//这也可以在 viewWillAppear/viewDidAppear 中完成//根据您的需要/愿望self.isLoading = NO;[自加载数据];}- (void)loadData {如果(self.isLoading == YES){//以防万一loadData"在一个待处理时进行呼叫...返回;}//防止此方法再次触发,直到//数据加载完成;防止 UICollectionView//试图显示丢失的数据self.isLoading = YES;//做任何你需要做的事...//清理并准备 UICollectionViewself.isLoading = NO;[self.collectionView reloadData];}

现在,真正的秘密当然是,您必须在 UICollectionViewDataSource 方法中实现逻辑,以根据 self.isLoading 有条件地显示数据,如下所示:

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {如果(self.isLoading == YES){//你可能想要返回 0 或 1,//取决于你是否有加载"//占位符单元格.假设你这样做:返回 1;} 别的 {//在这里返回正确的数字}}

通常,这就是我需要让我的屏幕延迟加载 UICollectionView 直到 Parse 查询正确返回.

当我有多个查询将同时运行时,所有查询都应该在我认为数据加载完成之前返回,然后我为每个查询创建一个 BOOL 属性,并根据需要设置标志,我通过 checkIfDone 方法收集所有查询返回.像这样:

@property (assign, nonatomic) BOOL data1Loaded;@property (assign, nonatomic) BOOL data2Loaded;@property (assign, nonatomic) BOOL data3Loaded;@property (assign, nonatomic) BOOL data4Loaded;- (void)loadData {如果(self.isLoading == YES){返回;}self.isLoading = YES;self.data1Loaded = NO;self.data2Loaded = NO;self.data3Loaded = NO;self.data4Loaded = NO;//调用每个单独的数据加载方法...[自加载数据1];[自加载数据2];[自加载数据3];[自加载数据4];//请注意,我没有在此处执行任何 reloadData 调用...}- (void)loadData1 {PFQuery *query =//一些查询创建...[查询 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {如果(错误!= nil){//处理出错"} 别的 {//处理得到好的数据"}//无论哪种方式,#1 都完成了,所以:self.data1Loaded = YES;//此模式检查完成和//只有当所有的时候才运行完成代码//4(在这种情况下)项目/查询已返回[自我检查如果完成];}];}- (void)checkIfDone {if (self.data1Loaded == YES &&self.data2Loaded == YES &&self.data3Loaded == YES &&self.data4Loaded == YES){//清理并准备 UICollectionViewself.isLoading = NO;[self.collectionView reloadData];}}

<块引用>

警告: 这假设对 loadData 的任何后续调用都将在后台发生,并且对 [collectionView 的任何后续调用reloadData] 只会在您的查询调用结束时发生.如果在此期间还有其他任何事情可能会调用 reloadData,您将需要更高级的逻辑来确保正确加载正确的数据.


<块引用>

旁注:在执行此类操作时,不要忘记向用户显示工作正在进行中的指示.我喜欢使用开源的MBProgressHUD.它可以在 此处在 GitHub 上获得.我发现完全按照您所说的去做是非常宝贵的.

In CollectionView I am displaying datas from parse.com. Successfully retrieved. But unable to display in the cell. I am receiving error as Array outbound. I found out the mistake, parse is running as asynchronous. But, before parse end, collection view gets loaded. So I unable to display values in the cell. It is throwing an error. How to stop all the process until parse get loaded completely? Kindly guide me. MY CODING IS BELOW:

//VIEWCONTROLLER having collectionView

var myList : NSArray = NSArray()

let obj_par = parse_retrive()
obj_par.parse_DB() //DATAS GOING TO RETRIVE FROM PARSE

story_collection_view.reloadData() //RELOADING COLLECTIONVIEW

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        println("fifth")

        if(collectionView == date_collection_view)
        {
         :
         :
            return cell
        }

        else

        {
            var cell = collectionView.dequeueReusableCellWithReuseIdentifier("story_read", forIndexPath: indexPath) as story_reading_cell

  cell.story_title.text = myList.objectAtIndex(indexPath.row) as? String //ERROR: ARRAY OUTBOUND OF INDEX

            return cell
        }

    }

//PARSE_RETRIVE CLASS

func parse_DB() {

        println("SECOND 10")

        par_query.findObjectsInBackgroundWithBlock({(NSArray objects, NSError error) in

            if (error != nil) {
                NSLog("error " + error.localizedDescription)
            }
            else {
                println("SECOND 13")
                let sql_store_obj1 = sql_to_store() //THIRD CLASS
                self.parse_obj_arr = NSArray(array: objects)
                var j : Int = self.parse_obj_arr.count
                for (var i : Int = 0; i < j; i++) {
                    self.par_object = self.parse_obj_arr.objectAtIndex(i) as PFObject
                    self.sto = self.par_object["story_title"] as String        //STORY TITLE FROM PARSE
                    self.sto_con = self.par_object["story_content"] as String  //STORY CONTENT FROM PARSE

                    self.sto_tit.append(self.sto)        //STORING IN ARRAY VAR
                    self.sto_cont.append(self.sto_con)   //STORING IN ARRAY VAR

                } //FOR ENDING

                sql_store_obj1.sto_title_arr = self.sto_tit
                sql_store_obj1.sto_content_arr = self.sto_cont
                sql_store_obj1.parse_to_sql()

            }//ELSE ENDING

        }) //PARSE QUERY ENDING

        println("SECOND")

    } 

//THIRD CLASS

func parse_to_sql() {

        let appDel : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let context : NSManagedObjectContext = appDel.managedObjectContext!
        let ent = NSEntityDescription.entityForName("Sad", inManagedObjectContext: context)
        var newStory = story_sad_managed(entity: ent!, insertIntoManagedObjectContext: context)

        newStory.story_title = sto_title_arr
        newStory.story_content = sto_content_arr

        let request = NSFetchRequest(entityName: "STORY")
        request.predicate = NSPredicate(format: "story_title = %@", sto_title_arr)
        result  = context.executeFetchRequest(request, error: nil)!

        let sto_page_obj = story_page()
        sto_page_obj.myList = result //1st CLASS ARRAY 

    }

解决方案

NOTE: All code is in Objective-C, but the translation for this particular code should be trivial. If someone wants to edit my post to include the Swift code, please feel free, but please leave the Objective-C in the post.

What I do (for UICollectionView or UITableView) is create a property, normally called isLoading like this:

@property (assign, nonatomic) BOOL isLoading;

I normally initialize it like this:

- (void)viewDidLoad {
    [super viewDidLoad];
    // This could also be done in viewWillAppear/viewDidAppear
    // based on your needs/desires
    self.isLoading = NO;
    [self loadData];
}

- (void)loadData {
    if (self.isLoading == YES) {
        // Just in case a "loadData" call is made while one is pending...
        return;
    }
    // Prevent this method from firing again until 
    // data loading is done; prevent UICollectionView
    // from attempting to display missing data
    self.isLoading = YES;
    
    // Do whatever you need to do...
    
    // Clean up and prepare for UICollectionView
    self.isLoading = NO;
    [self.collectionView reloadData];
}

Now, the real secret is, of course, that you have to implement logic in your UICollectionViewDataSource methods to display data conditionally based upon self.isLoading, like this:

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    if (self.isLoading == YES) {
        // You might want to return 0 or 1, 
        // depending on whether you have a "loading"
        // placeholder cell. Assume you do:
        return 1;        
    } else {
        // Return whatever is the correct number here
    
    }
}

Generally, that's all I need to get my screen to delay loading the UICollectionView until the Parse query has returned correctly.

When I have multiple queries that will run concurrently, all of which should return before I consider data loading to be complete, then I create a BOOL property for each of them, setting the flags as appropriate, and I funnel all query returns through a checkIfDone method. Something like this:

@property (assign, nonatomic) BOOL data1Loaded;
@property (assign, nonatomic) BOOL data2Loaded;
@property (assign, nonatomic) BOOL data3Loaded;
@property (assign, nonatomic) BOOL data4Loaded;

- (void)loadData {
    if (self.isLoading == YES) {
        return;
    }
    self.isLoading   = YES;
    self.data1Loaded = NO;
    self.data2Loaded = NO;
    self.data3Loaded = NO;
    self.data4Loaded = NO;

    // Call each of the separate data loading methods...
    [self loadData1];
    [self loadData2];
    [self loadData3];
    [self loadData4];

    // Notice that I don't do any reloadData calls here...

}

- (void)loadData1 {
    PFQuery *query = // Some query creation...
    [query findObjectsInBackgroundWithBlock:
        ^(NSArray *objects, NSError *error) {
            if (error != nil) { 
                // Handle "got error"

            } else {
                // Handle "got good data"

            }
            // Either way, #1 is done, so:
            self.data1Loaded = YES;
            // This pattern checks for completion and
            // runs the completion code only when all
            // 4 (in this case) items/queries have returned
            [self checkIfDone];
        }
     ];
}

- (void)checkIfDone {
    if (self.data1Loaded == YES && 
        self.data2Loaded == YES && 
        self.data3Loaded == YES && 
        self.data4Loaded == YES) 
    {
        // Clean up and prepare for UICollectionView
        self.isLoading = NO;
        [self.collectionView reloadData];
    }
}

Caveat: This assumes that any subsequent calls to loadData will occur in the background and that any subsequent calls to [collectionView reloadData] will only take place at the end of your query calls. If anything else might call reloadData in the meantime, you will need more advanced logic to ensure that the correct data is loaded correctly.


Side Note: When doing something like this, don't forget to show the user an indication that work is progressing. I like to use the open source MBProgressHUD. It's available here on GitHub. I have found it invaluable for doing exactly what you're talking about doing.

这篇关于在 Swift 中,如何停止所有进程,直到从 UICOLLECTIONVIEW 中的 parse.com 检索到数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆