鉴于:
typealias Action = () -> ()
var action: Action = { }
func doStuff(stuff: String, completion: @escaping Action) {
print(stuff)
action = completion
completion()
}
func doStuffAgain() {
print("again")
action()
}
doStuff(stuff: "do stuff") {
print("swift 3!")
}
doStuffAgain()
Run Code Online (Sandbox Code Playgroud)
有没有办法制作类型的completion参数(和action)Action?并保持@escaping?
更改类型会出现以下错误:
error: @escaping attribute only applies to function types
删除@escaping属性,代码编译并运行,但似乎不正确,因为completion闭包正在逃避函数的范围.
当我在调查Javascript代码中的词法闭包问题时,我在Python中遇到了这个问题:
flist = []
for i in xrange(3):
def func(x): return x * i
flist.append(func)
for f in flist:
print f(2)
Run Code Online (Sandbox Code Playgroud)
请注意,此示例谨慎避免lambda.它打印"4 4 4",这是令人惊讶的.我期待"0 2 4".
这个等效的Perl代码是正确的:
my @flist = ();
foreach my $i (0 .. 2)
{
push(@flist, sub {$i * $_[0]});
}
foreach my $f (@flist)
{
print $f->(2), "\n";
}
Run Code Online (Sandbox Code Playgroud)
打印"0 2 4".
你能解释一下这个区别吗?
更新:
这个问题是不是与i是全球性的.这显示相同的行为:
flist = []
def outer():
for i in xrange(3):
def inner(x): return x * i …Run Code Online (Sandbox Code Playgroud) 我注意到assert在Swift中编写第一个值时输入为
@autoclosure() -> Bool
Run Code Online (Sandbox Code Playgroud)
用重载方法返回一个通用T值,通过它来测试存在LogicValue protocol.
但严格坚持手头的问题.它似乎想要一个@autoclosure返回一个Bool.
编写一个不带参数并返回Bool的实际闭包不起作用,它要我调用闭包使其编译,如下所示:
assert({() -> Bool in return false}(), "No user has been set", file: __FILE__, line: __LINE__)
Run Code Online (Sandbox Code Playgroud)
然而,简单地通过Bool工作:
assert(false, "No user has been set", file: __FILE__, line: __LINE__)
Run Code Online (Sandbox Code Playgroud)
那么发生了什么?什么是@autoclosure?
编辑: @auto_closure已重命名@autoclosure
如果我需要一个接一个地调用这个函数,
$('#art1').animate({'width':'1000px'},1000);
$('#art2').animate({'width':'1000px'},1000);
$('#art3').animate({'width':'1000px'},1000);
Run Code Online (Sandbox Code Playgroud)
我知道在jQuery中我可以做类似的事情:
$('#art1').animate({'width':'1000px'},1000,'linear',function(){
$('#art2').animate({'width':'1000px'},1000,'linear',function(){
$('#art3').animate({'width':'1000px'},1000);
});
});
Run Code Online (Sandbox Code Playgroud)
但是,我们假设我没有使用jQuery而且我想调用:
some_3secs_function(some_value);
some_5secs_function(some_value);
some_8secs_function(some_value);
Run Code Online (Sandbox Code Playgroud)
我应该如何调用这个函数来执行some_3secs_function,然后在该调用结束后,然后执行some_5secs_function并在该调用结束后再调用some_8secs_function?
更新:
这仍然无效:
(function(callback){
$('#art1').animate({'width':'1000px'},1000);
callback();
})((function(callback2){
$('#art2').animate({'width':'1000px'},1000);
callback2();
})(function(){
$('#art3').animate({'width':'1000px'},1000);
}));
Run Code Online (Sandbox Code Playgroud)
三个动画同时开始
我的错误在哪里
当我在C#编译器遇到一些非常奇怪的代码时,我正在回答关于闭包(合法地)延长对象生命周期的可能性的问题(如果重要的话,那就是4.0).
我能找到的最短的repro如下:
结果:编译器创建一个闭包对象,该对象引用创建lambda的对象,当它没有理由时 - 委托的"内部"目标是静态方法,并且lambda-creation-object的实例成员不需要在委托执行时被(并且没有)触摸.实际上,编译器的行为就像程序员this无缘无故地捕获的那样.
class Foo
{
private Action _field;
public void InstanceMethod()
{
var capturedVariable = Math.Pow(42, 1);
_field = () => StaticMethod(capturedVariable);
}
private static void StaticMethod(double arg) { }
}
Run Code Online (Sandbox Code Playgroud)
发布版本生成的代码(反编译为'simpler'C#)如下所示:
public void InstanceMethod()
{
<>c__DisplayClass1 CS$<>8__locals2 = new <>c__DisplayClass1();
CS$<>8__locals2.<>4__this = this; // What's this doing here?
CS$<>8__locals2.capturedVariable = Math.Pow(42.0, 1.0);
this._field = new Action(CS$<>8__locals2.<InstanceMethod>b__0);
}
[CompilerGenerated]
private sealed class …Run Code Online (Sandbox Code Playgroud) 在Objective-C中,您可以定义块的输入和输出,存储传递给方法的其中一个块,然后再使用该块:
// in .h
typedef void (^APLCalibrationProgressHandler)(float percentComplete);
typedef void (^APLCalibrationCompletionHandler)(NSInteger measuredPower, NSError *error);
// in .m
@property (strong) APLCalibrationProgressHandler progressHandler;
@property (strong) APLCalibrationCompletionHandler completionHandler;
- (id)initWithRegion:(CLBeaconRegion *)region completionHandler:(APLCalibrationCompletionHandler)handler
{
self = [super init];
if(self)
{
...
_completionHandler = [handler copy];
..
}
return self;
}
- (void)performCalibrationWithProgressHandler:(APLCalibrationProgressHandler)handler
{
...
self.progressHandler = [handler copy];
...
dispatch_async(dispatch_get_main_queue(), ^{
_completionHandler(0, error);
});
...
}
Run Code Online (Sandbox Code Playgroud)
所以我试图在Swift中做等效的事情:
var completionHandler:(Float)->Void={}
init() {
locationManager = CLLocationManager()
region = CLBeaconRegion()
timer = NSTimer()
}
convenience init(region: CLBeaconRegion, …Run Code Online (Sandbox Code Playgroud) 这是我正在尝试运行的简化版本:
for (var i = 0; i < results.length; i++) {
marker = results[i];
google.maps.event.addListener(marker, 'click', function() {
change_selection(i);
});
}
Run Code Online (Sandbox Code Playgroud)
但我发现每个监听器都使用results.length的值(for循环终止时的值).我如何添加监听器,使得每次使用i时我添加它的值,而不是对i的引用?
javascript closures listener pass-by-reference pass-by-value
许多Cocoa和CocoaTouch方法都有完成回调,实现为Objective-C中的块和Swift中的闭包.但是,在Playground中尝试这些时,永远不会调用完成.例如:
// Playground - noun: a place where people can play
import Cocoa
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in
// This block never gets called?
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
Run Code Online (Sandbox Code Playgroud)
我可以在我的Playground时间轴中看到控制台输出,但是println我的完成块永远不会被调用...
我正在尝试在Python 2.6中实现一个闭包,我需要访问一个非局部变量,但似乎这个关键字在python 2.x中不可用.如何在这些版本的python中访问闭包中的非局部变量?
我有一个协议:
enum DataFetchResult {
case success(data: Data)
case failure
}
protocol DataServiceType {
func fetchData(location: String, completion: (DataFetchResult) -> (Void))
func cachedData(location: String) -> Data?
}
Run Code Online (Sandbox Code Playgroud)
通过示例实现:
/// An implementation of DataServiceType protocol returning predefined results using arbitrary queue for asynchronyous mechanisms.
/// Dedicated to be used in various tests (Unit Tests).
class DataMockService: DataServiceType {
var result : DataFetchResult
var async : Bool = true
var queue : DispatchQueue = DispatchQueue.global(qos: .background)
var cachedData : Data? = nil
init(result …Run Code Online (Sandbox Code Playgroud) closures ×10
swift ×4
asynchronous ×2
callback ×2
javascript ×2
python ×2
swift3 ×2
c# ×1
function ×1
lambda ×1
late-binding ×1
listener ×1
memory-leaks ×1
optional ×1
python-2.x ×1
xcode8-beta6 ×1