我很难理解为什么我在使用Swift的iOS项目中遇到此编译器错误.如果我创建以下类:
class InitTest {
let a: Int
let b: Int
let c: Int
init () {
self.a = 3
self.b = 4
self.c = self.runCalculation()
}
func runCalculation () -> Int {
return self.a * self.b
}
}
Run Code Online (Sandbox Code Playgroud)
我在行上写了一个编译错误,self.c = self.runCalculation()说"在初始化之前使用了变量'self.c'".
起初我以为这是因为编译器无法验证该runCalculation()方法无法访问self.c,但后来我尝试将init方法稍微混合起来:
init () {
self.a = 3
self.c = self.runCalculation()
self.b = 4
}
Run Code Online (Sandbox Code Playgroud)
这次错误是"初始化之前使用的变量'self.b'"(在同一self.runCalculation()行).这表明编译器是能够检查其性能的方法访问,所以据我可以看到应该有最初的情况下,没有问题的.
当然这是一个简单的例子,我可以轻松地重构以避免调用计算方法,但在一个真实的项目中,可能会有几个计算,每个计算都可能非常复杂.我希望能够分离逻辑以保持可读性.
幸运的是,有一个简单的解决方法:
init () {
self.a = 3
self.b = 4
self.c = 0 …Run Code Online (Sandbox Code Playgroud) 我正在尝试在Instruments中配置Swift应用程序并且遇到困难,因为没有显示libswiftCore.dylib和l ibswiftFoundation.dylib库的调试符号.鼠标悬停文本建议使用File -> Symbols手动选择的dSYM文件,但我不知道在那里它们被存储,或者即使他们存在.我编写的代码中的符号看起来很好.
我建立了一个测试项目并在仪器中对其进行了剖析以证明:

如何识别显示的功能libswiftCore.dylib?
我遇到了通过UIViewController的touchesBegan/Moved/Ended方法处理多个触摸的问题.我也在cocos2d应用程序中看到相同的行为(使用ccTouchesBegan/Moved/Ended),所以我认为这个问题可以应用于iOS中的所有触摸处理.我已经把我正在使用的代码放在下面,然后是我看到的结果.
所有方法都在UIViewController子类上实现.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touches Began");
[self logTouchesFor: event];
[super touchesEnded: touches withEvent: event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touches Moved");
[self logTouchesFor: event];
[super touchesEnded: touches withEvent: event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touches Ended");
[self logTouchesFor: event];
[super touchesEnded: touches withEvent: event];
}
-(void)logTouchesFor:(UIEvent *)event
{
int count = 1;
for (UITouch *touch in event.allTouches)
{
CGPoint location = [touch locationInView: self.view];
NSLog(@"%d: (%.0f, %.0f)", count, location.x, location.y);
count++;
} …Run Code Online (Sandbox Code Playgroud) 我正在使用UIDynamics实现一些动画,以在视图之间启用一些基于物理的转换.我想以编程方式暂停和继续这些动画以响应用户的触摸.到目前为止,我发现这样做的唯一方法是从动态动画师中删除行为,然后像这样重新添加它们:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.dynamicAnimator removeBehaviour: self.behaviour1];
[self.dynamicAnimator removeBehaviour: self.behaviour2];
// etc
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
self.behaviour1 = [[UIGravityBehavior alloc] initWithItems: @[self.item]];
self.behaviour1.gravityDirection = self.gravityVector;
[self.dynamicAnimator addBehaviour: self.behaviour1];
self.behaviour2 = [[UICollisionBehavior alloc] initWithItems: @[self.item]];
[self.behaviour2 addBoundaryWithIdentifier: @"Boundary" forPath: self.boundary];
[self.dynamicAnimator addBehaviour: self.behaviour2];
// etc
}
Run Code Online (Sandbox Code Playgroud)
(旁白:我也使用[self.dynamicAnimator updateItemUsingCurrentState: item]而不是重新创建行为,但我仍然需要从动态动画师中删除它们并再次重新添加它们,以便在用户触摸屏幕时暂停.)
我希望能够做的是self.dynamicAnimator.running = NO暂停,然后self.dynamicAnimator.running = YES继续.这将更加简洁,涉及更少的代码(我目前有五种行为可以做到这一点),并有助于避免过程中的潜在错误.不幸的是,该dynamicAnimator.running财产是只读的,所以这是不可能的.
有没有办法暂停和继续UIDynamicAnimator一两行,我错过了?
我知道可以为有区别的联合添加方法和属性,但是你可以添加一个必须在创建联合的实例时设置的不可变字段,就像记录中的字段一样吗?
我想我想要做的是组合一个union类型和一个记录类型,如下所示:
type union =
| OptionOne of int
| OptionTwo of string
{
AFieldUsedForBothCases : string
}
Run Code Online (Sandbox Code Playgroud)
这不是有效的声明.
我知道这可以通过创建记录类型来解决:
type record =
{
AFieldUsedForBothCases : string
TheDiscriminatedUnion : union
}
Run Code Online (Sandbox Code Playgroud)
但是如果可能的话,我想做第一个例子.