2016-04-07 43 views
0

我将this Objective-C开源项目转换为Swift。它有一堆可选的代表。可选委托方法的respondsToSelector

@protocol BEMAnalogClockDelegate <NSObject> 

@optional 

- (void)currentTimeOnClock:(BEMAnalogClockView *)clock Hours:(NSString *)hours Minutes:(NSString *)minutes Seconds:(NSString *)seconds; 
- (NSString *)dateFormatterForClock:(BEMAnalogClockView *)clock; 
- (NSString *)timeForClock:(BEMAnalogClockView *)clock; 
- (UIColor *)analogClock:(BEMAnalogClockView *)clock graduationColorForIndex:(NSInteger)index; 
- (CGFloat)analogClock:(BEMAnalogClockView *)clock graduationAlphaForIndex:(NSInteger)index; 
- (CGFloat)analogClock:(BEMAnalogClockView *)clock graduationWidthForIndex:(NSInteger)index; 
- (CGFloat)analogClock:(BEMAnalogClockView *)clock graduationLengthForIndex:(NSInteger)index; 
- (CGFloat)analogClock:(BEMAnalogClockView *)clock graduationOffsetForIndex:(NSInteger)index; 

我将它们转换为Swift像这样。

@objc protocol BEMAnalogClockDelegate { 
    optional func currentTimeOnClock(clock: BEMAnalogClockView, hours: String, minutes: String, seconds: String) 
    optional func dateFormatterForClock(clock: BEMAnalogClockView) -> String 
    optional func timeForClock(clock: BEMAnalogClockView) -> String 
    optional func analogClock(clock: BEMAnalogClockView, graduationColorForIndex index: Int) -> UIColor 
    optional func analogClock(clock: BEMAnalogClockView, graduationAlphaForIndex index: Int) -> CGFloat 
    optional func analogClock(clock: BEMAnalogClockView, graduationWidthForIndex index: Int) -> CGFloat 
    optional func analogClock(clock: BEMAnalogClockView, graduationLengthForIndex index: Int) -> CGFloat 
    optional func analogClock(clock: BEMAnalogClockView, graduationOffsetForIndex index: Int) -> CGFloat 
    optional func clockDidBeginLoading(clock: BEMAnalogClockView) 
    optional func clockDidFinishLoading(clock: BEMAnalogClockView) 
} 

在Objective-C的项目,要求这些可选的方法之前,它会检查使用respondsToSelector这样其可用性。

if ([self.delegate respondsToSelector:@selector(analogClock:graduationColorForIndex:)]) { 
    self.graduationColor = [self.delegate analogClock:self graduationColorForIndex:i]; 
} else self.graduationColor = [UIColor whiteColor]; 

if ([self.delegate respondsToSelector:@selector(analogClock:graduationAlphaForIndex:)]) { 
    self.graduationAlpha = [self.delegate analogClock:self graduationAlphaForIndex:i]; 
} else self.graduationAlpha = 1.0; 

我直接通过使BEMAnalogClockDelegate符合NSObjectProtocol,并呼吁他们像这样转换这斯威夫特。

if delegate.respondsToSelector(#selector(BEMAnalogClockDelegate.analogClock(_:graduationColorForIndex:))) { 
    graduationColor = delegate.analogClock!(self, graduationColorForIndex: i) 
} else { 
    graduationColor = UIColor.whiteColor() 
} 

if delegate.respondsToSelector(#selector(BEMAnalogClockDelegate.analogClock(_:graduationAlphaForIndex:))) { 
    graduationAlpha = delegate.analogClock!(self, graduationAlphaForIndex: i) 
} else { 
    graduationAlpha = 1 
} 

但是,这会导致项目运行时出现EXC_BREAKPOINT崩溃。

我搜索了一个解决方案,并遇到了this文章,其中建议使用guard let为此。

但是我的问题是如何指定else部件中的逻辑?例如,在上面的第一个if else块中,它检查if块中的方法,如果失败,它将的值设置为else块中的UIColor.whiteColor()

如果我使用guard let方法,该怎么办?还是有更好的方法来做到这一点?

+0

这个答案可能会有所帮助:http://stackoverflow.com/a/36475215/2976878 – Hamish

回答

2

Swift也支持方法的选项。

你可以这样做,而不是:

graduationColor = delegate.analogClock?(self, graduationColorForIndex: i) ?? UIColor.whiteColor()

还是很长的路要走:

if let graduationColor = delegate.analogClock?(self, graduationColorForIndex: i) { 
    self.graduationColor = graduationColor 
} else { 
    self.graduationColor = UIColor.whiteColor() 
}