Berikut adalah kode untuk dua penutupan dalam dua penekanan tombol IBAction yang berbeda. Hasil yang diinginkan adalah menekan tombol untuk menghidupkan/mematikan LED, kemudian mengakses sensor cahaya dan membaca nilai cahaya setelah perubahan status LED.
Apa yang terjadi adalah kondisi balapan di mana fungsi getVariable berjalan dan kembali sebelum callFunction mengimplementasikan perubahan. Hasilnya adalah nilai yang ditampilkan di getLightLabel.text adalah nilai dari kondisi sebelumnya, bukan kondisi saat ini.
Pertanyaan saya adalah bagaimana cara menulis ulang kode di bawah ini sehingga myPhoton!.getVariable tidak dijalankan sampai myPhoton!.callFunction telah kembali (menyelesaikan tugasnya).
Saya telah mencoba menempatkan getVariable di dalam callFunction, sebelum dan sesudah } menutup if (kesalahan == nihil), tetapi hasilnya sama dengan kode yang ditampilkan di sini.
@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"
}
}
})
}
Berikut adalah komentar dan kode callFunction dari file .h. SDK ini ditulis dalam Objective C. Saya menggunakannya di Swift dengan file header penghubung.
/**
* 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;
*/
Ini kode file .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);
}];
}