ป้องกันไม่ให้การปิดดำเนินการจนกว่าอีกรายการหนึ่งจะเสร็จสมบูรณ์

นี่คือโค้ดสำหรับการปิดสองครั้งในการกดปุ่ม IBAction ที่แตกต่างกันสองครั้ง ผลลัพธ์ที่ต้องการคือการกดปุ่มเพื่อเปิด/ปิด LED จากนั้นจึงเข้าถึงเซ็นเซอร์วัดแสงและอ่านค่าแสงหลังจากเปลี่ยนสถานะ LED

สิ่งที่เกิดขึ้นคือสภาวะการแข่งขันที่ฟังก์ชัน getVariable ทำงานและส่งคืนก่อนที่ callFunction จะดำเนินการเปลี่ยนแปลง ผลลัพธ์ก็คือค่าที่แสดงใน getLightLabel.text จะเป็นค่าของเงื่อนไขก่อนหน้า ไม่ใช่เงื่อนไขปัจจุบัน

คำถามของฉันคือจะเขียนโค้ดด้านล่างใหม่ได้อย่างไรเพื่อให้ myPhoton!.getVariable ไม่ทำงานจนกว่า myPhoton!.callFunction จะส่งคืน (ทำงานเสร็จสิ้น)

ฉันได้ลองวาง getVariable ไว้ใน callFunction ทั้งก่อนและหลัง } ปิด if (ข้อผิดพลาด == ไม่มี) แต่ผลลัพธ์ก็เหมือนกับโค้ดที่แสดงที่นี่

@IBAction func lightOn(sender: AnyObject) {
    let funcArgs = [1]
    myPhoton!.callFunction("lightLed0", withArguments: funcArgs) { (resultCode : NSNumber!, error : NSError!) -> Void in
        if (error == nil) {
            self.lightStateLabel.text = "LED is on"
        }
    }
    myPhoton!.getVariable("Light", completion: { (result:AnyObject!, error:NSError!) -> Void in
        if let e = error {
            self.getLightLabel.text = "Failed reading light"
        }
        else {
            if let res = result as? Float {
                self.getLightLabel.text = "Light level is \(res) lumens"
            }
        }
    })



}


@IBAction func lightOff(sender: AnyObject) {
    let funcArgs = [0]
    myPhoton!.callFunction("lightLed0", withArguments: funcArgs) { (resultCode : NSNumber!, error : NSError!) -> Void in
        if (error == nil) {
            self.lightStateLabel.text = "LED is off"
        }
    }
    myPhoton!.getVariable("Light", completion: { (result:AnyObject!, error:NSError!) -> Void in
        if let e = error {
            self.getLightLabel.text = "Failed reading light"
        }
        else {
            if let res = result as? Float {
                self.getLightLabel.text = "Light level is \(res) lumens"
            }
        }
    })

}

นี่คือความคิดเห็นและโค้ด callFunction จากไฟล์ .h SDK นี้เขียนใน Objective C ฉันใช้ใน Swift พร้อมกับไฟล์ส่วนหัวที่เชื่อมโยง

/**
 *  Call a function on the device
 *
 *  @param functionName Function name
 *  @param args         Array of arguments to pass to the function on the device. Arguments will be converted to string maximum length 63 chars.
 *  @param completion   Completion block will be called when function was invoked on device. First argument of block is the integer return value of the function, second is NSError object in case of an error invoking the function
 */
-(void)callFunction:(NSString *)functionName withArguments:(NSArray *)args completion:(void (^)(NSNumber *, NSError *))completion;

/*
-(void)addEventHandler:(NSString *)eventName handler:(void(^)(void))handler;
-(void)removeEventHandler:(NSString *)eventName;
 */

นี่คือโค้ดไฟล์ .m

-(void)callFunction:(NSString *)functionName withArguments:(NSArray *)args completion:(void (^)(NSNumber *, NSError *))completion
{
    // TODO: check function name exists in list
    NSURL *url = [self.baseURL URLByAppendingPathComponent:[NSString stringWithFormat:@"v1/devices/%@/%@", self.id, functionName]];
    NSMutableDictionary *params = [NSMutableDictionary new]; //[self defaultParams];
    // TODO: check response of calling a non existant function

    if (args) {
        NSMutableArray *argsStr = [[NSMutableArray alloc] initWithCapacity:args.count];
        for (id arg in args)
        {
            [argsStr addObject:[arg description]];
        }
        NSString *argsValue = [argsStr componentsJoinedByString:@","];
        if (argsValue.length > MAX_SPARK_FUNCTION_ARG_LENGTH)
        {
            // TODO: arrange user error/codes in a list
            NSError *err = [self makeErrorWithDescription:[NSString stringWithFormat:@"Maximum argument length cannot exceed %d",MAX_SPARK_FUNCTION_ARG_LENGTH] code:1000];
            if (completion)
                completion(nil,err);
            return;
        }

        params[@"args"] = argsValue;
    }

    [self setAuthHeaderWithAccessToken];

    [self.manager POST:[url description] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
        if (completion)
        {
            NSDictionary *responseDict = responseObject;
            if ([responseDict[@"connected"] boolValue]==NO)
            {
                NSError *err = [self makeErrorWithDescription:@"Device is not connected" code:1001];
                completion(nil,err);
            }
            else
            {
                // check
                NSNumber *result = responseDict[@"return_value"];
                completion(result,nil);
            }
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error)
    {
        if (completion)
            completion(nil,error);
    }];

}

person Bendrix    schedule 18.06.2015    source แหล่งที่มา
comment
คุณแน่ใจหรือว่าปัญหาของคุณไม่ใช่รหัสเอง ใน callFunctions ทั้งสอง ดูเหมือนว่าคุณจะรวมโค้ดเพื่อกำหนดฟังก์ชันและเรียกใช้ฟังก์ชันหนึ่ง - คุณกำลังเรียก myPhoton!.callFunction(...) แต่คุณมีโค้ดอยู่ในวงเล็บ {...} หลังจากที่คุณผ่าน ข้อโต้แย้งทั้งหมดของคุณ   -  person dunnmifflsys    schedule 18.06.2015
comment
@dunmifflsys นี่คือสิ่งที่คุณสามารถทำได้โดยการปิดเป็นพารามิเตอร์สุดท้ายในการเรียกใช้ฟังก์ชัน foo(block: {closure}) สามารถเขียนได้ foo {closure} สิ่งที่ฉันขาดหายไปในโพสต์ต้นฉบับคือคำจำกัดความของ callFunction และ getVariable   -  person Laurent    schedule 18.06.2015
comment
เราจะเห็นคำจำกัดความ callFunction(_:withArguments:) ของคุณได้ไหม   -  person fqdn    schedule 18.06.2015
comment
ดูการเปลี่ยนแปลงที่เป็นปัญหา ฉันเพิ่มโค้ดไฟล์ .h และ .m จาก Objective C SDK ฉันใช้ไฟล์ส่วนหัวเชื่อมโยงใน Swift เพื่อเข้าถึงฟังก์ชัน หากเป็นไปได้ที่จะจำกัดโซลูชันไว้เฉพาะ Swift ก็จะเป็นที่ต้องการ   -  person Bendrix    schedule 18.06.2015


คำตอบ (1)


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

ในแอปพลิเคชันนี้ ปัญหาที่ฉันพบไม่สามารถแก้ไขได้บนฝั่ง IOS/Swift ของสแต็ก Cloud API และ uP ที่ฝังไว้ไม่ได้เชื่อมโยงกันอย่างแน่นหนา ดังนั้นคลาวด์จึงกลับสู่ IOS โดยดำเนินการให้เสร็จสิ้นก่อนที่โค้ดฟังก์ชันทั้งหมดจะทำงานบน Particle uP

วิธีแก้ปัญหาโดยรวมนี้จริงๆ แล้วอยู่ที่การปรับเปลี่ยน Cloud API หรือเพิ่มโค้ดเพิ่มเติมให้กับเฟิร์มแวร์ uP เพื่อเชื่อมโยงกระบวนการกับแอป IOS อย่างแน่นหนาด้วยการสื่อสารเพิ่มเติม

person Bendrix    schedule 13.07.2015