如何使用异步函数之外的值?

时间:2018-05-13 05:34:33

标签: swift function asynchronous

原始功能看起来像这样:

CImpl

但是由于同步功能在Swift中的工作方式,每月费用值不会更新。所以然后我尝试更改我的代码,以便将尽可能多的代码放入异步函数本身,它看起来像这样:

//! 2018.05.13 13:31:34 CST
//! Find the max-area bounding-rect of approxed-poly-contours

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int findMaxRect(){
    /// Read, cvtColor, threshold
    Mat img, gray, threshed;
    img = imread("car.jpg");
    cvtColor(img, gray, COLOR_BGR2GRAY);
    threshold(gray, threshed, 100, 255, THRESH_OTSU|THRESH_BINARY);

    /// Find contours
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(threshed, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

    ///  Find the max boundingRect of approxed-contours
    double max_area = -1;
    Rect max_rect;
    int idx = -1;
    vector<Point2f> contour_poly;

    for (int i = 0; i < contours.size(); i++){
        /// Approx the contour
        Mat contour = Mat(contours[i]);
        double arclen = arcLength(contour, true);
        approxPolyDP(contour, contour_poly, 0.03*arclen, true);

        /// Get the bounding box
        Rect rect =  boundingRect(Mat(contour_poly));

        /// Update the max_area_box
        double area = rect.width*rect.height;
        if(area>max_area){
            max_area = area;
            max_rect = rect;
        }
    }

    cout << max_rect<<endl;

    /// Draw the max rect
    Mat drawing = img.clone();
    rectangle(drawing, max_rect.tl(), max_rect.br(), Scalar(0,255,0), 1,8,0);
    /// Crop
    Mat dst = img(max_rect);
    /// Display
    imshow("drawing", drawing);
    imshow("dst", dst);
    waitKey(0);
    return 0;
}

int main(int argc, char** argv){
    //test_contours();
    findMaxRect() ;
}

但问题是现在“sum”的值为0,因为我在此异步函数之外使用了一个变量。我已经看到在多个问题上提出了这个问题,但我无法在任何地方找到答案。这个问题的解决方案是什么

2 个答案:

答案 0 :(得分:1)

在获取数据时使用完成处理程序作为触发器更新UI。

具有完成处理程序的设置功能:

func retrieveMonthlySpent(month:String, year:String, completion: ((Double) -> Void)? = nil) {
FirebaseFunctions().retrieve(from: .expense, username: self.username as! String, returning: Expenses.self) { (expenses) in
    self.monthlyExpenses = expenses
    var sum = 0.0
    for expense in self.monthlyExpenses {
        if expense.modificationDate.convertToMonth() == month && expense.expense && expense.modificationDate.convertToYear() == year {
            sum += expense.convertedAmount
        }
    }
    completion(sum)
  }
}

在viewController中使用它,例如:

func retrieveMonthlySpent(month:"05", year:"1996") { result in
      self.sumLabel.text = result
}
很容易就像Thanos抓住他的手指一样:)

答案 1 :(得分:0)

如果要调用异步API,则必须使用完成处理程序:

func retrieveMonthlySpent(month:String, year:String, success: @escaping (Double) -> Void) {
    FirebaseFunctions().retrieve(from: .expense, username: self.username as! String, returning: Expenses.self) { (expenses) in
        self.monthlyExpenses = expenses
        var sum:Double = 0
        for expense in self.monthlyExpenses{
            if expense.modificationDate.convertToMonth() == month && expense.expense && expense.modificationDate.convertToYear() == year{
                sum += expense.convertedAmount
            }
        }
        success(sum)
    }
}

您可以使用当前控制器中的此方法:

self.retrieveMonthlySpent(month: "", year: "") { (sum) in
            print(sum)
        }

或者从其他ViewController,您可以这样使用:

Xviewcontroller().retrieveMonthlySpent(month: "", year: "") { (sum) in
            total = sum
        }

为了更好的代码重用性,您需要将此方法放在superviewcontroller或任何公共类中。