具有异步请求的递归函数

时间:2015-09-15 10:13:14

标签: swift asynchronous recursion completionhandler

我有一个带有异步请求的递归函数。如果请求成功,我想保存在数组中,但我不知道如何。 具体来说,它是一个上传文件的功能,如果该功能获得一个文件夹,也应该上传该文件夹中的文件。

我想过用completionHandler来实现这个,关于这个:

func uploadFiles(pathToFile: NSURL) ->[Bool]{
    var suc: [Bool] = [Bool]()
    self.uploadFileRec(pathToFile, suc: &suc){
        (result: [Bool]) in
        println(result)
    }
    return suc
}

func uploadFilesRec(pathToFile: NSURL, inout suc: [Bool], completionHandler: (result: [Bool]) -> Void){
    var isDir: ObjCBool = ObjCBool(true)
    var manager: NSFileManager = NSFileManager.defaultManager()
    manager.fileExistsAtPath(pathToFile.path!, isDirectory: &isDir)
    if(isDir){
        var error: NSError? = nil
        let contents = manager.contentsOfDirectoryAtPath(pathToFile.path!, error: &error) as! [String]
        for fileName in contents {
            if(fileName != ".DS_Store"){
                var pathString = pathToFile.path! + "/" + fileName
                var updatePathtoFile = NSURL(fileURLWithPath: pathString)
                self.uploadFilesRec(updatePathtoFile!, suc: &suc, completionHandler: completionHandler)
                completionHandler(result: suc)
            }
        }

    }
    else{
        asyncFileUpload(...){
            ...
            suc.append(/*successful or not*/)
        }
    }
}

但问题是println不仅会调用一次,而且会调用uploadFileRec调用内部调用次数。因此,如果我将调用另一个函数而不是println,该函数也会被调用多次。 所以我认为使用completionHandler的想法是错误的。我怎么能意识到这一点?

2 个答案:

答案 0 :(得分:1)

好的,我回答我自己的问题。

complitionHandler的想法确实是错误的。就像我在问题中所说的那样,complitionHandler被调用多次,因为调用了递归函数。如果您想在我的应用程序收集回复或类似内容,如果某些文件的上传成功,您必须使用调度组。主要想法是在此组中添加所有请求,并等待所有请求完成。

在实践中,它意味着创建组:

let group = dispatch_group_create()

在调用递归函数之前输入组,然后每次函数调用自身:

dispatch_group_enter(self.group)

请求完成后离开组,并在您输入组的时间内离开:

dispatch_group_leave(self.group)

等到所有工作完成后:

dispatch_group_notify(group, dispatch_get_main_queue()) {
        //Do work here
    }

答案 1 :(得分:0)

  1. private void startBeaconRangeFinderService() { beaconManager.setRangeNotifier(new RangeNotifier() { @Override public void didRangeBeaconsInRegion(Collection<Beacon> beacons, org.altbeacon.beacon.Region region) { try { if (beacons.size() > 0) { for (Beacon b : beacons) { processYourBeaconInThisMethod(b); } } } catch (Exception ex) { Log.e(TAG_BEACON_ACTIVITY, "Error was thrown: " + ex.getMessage()); } } }); try { beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null)); } catch (RemoteException e) { Log.e(TAG_BEACON_ACTIVITY, "Error was thrown: " + e.getMessage()); } } 因此,您默认将所有文件视为dirs,当var isDir: ObjCBool = ObjCBool(true)失败时,您会收到深度递归,因为 isDirectory 标记保持为TRUE:

      

    如果路径不存在,则返回时该值未定义

    来自Apple Doc ...

  2. manager.fileExistsAtPath - 不确定最终会得到正确的路径。所以,你得到了递归。检查 pathString

  3. manager.fileExistsAtPath 结果被忽略,因此,您正在进行盲目上传...
  4. 解决问题并继续......