objective-c - 两个例程,一个在 Objective-C 中,另一个在 Swift 中,相同的代码产生本质不同的结果

标签 objective-c swift translation

iOS 10.2 swift 3.0

试图将此 Objective-C 中的代码转换为 Swift 3.0,并且不太了解核心图形库。

@interface SPGripViewBorderView : UIView
@end

@implementation SPGripViewBorderView

- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
    // Clear background to ensure the content view shows through.
    self.backgroundColor = [UIColor clearColor];
}
return self;
}

- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);

// (1) Draw the bounding box.
CGContextSetLineWidth(context, 1.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextAddRect(context, CGRectInset(self.bounds, kSPUserResizableViewInteractiveBorderSize/2, kSPUserResizableViewInteractiveBorderSize/2));
CGContextStrokePath(context);

// (2) Calculate the bounding boxes for each of the anchor points.
CGRect upperLeft = CGRectMake(0.0, 0.0, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);
CGRect upperRight = CGRectMake(self.bounds.size.width - kSPUserResizableViewInteractiveBorderSize, 0.0, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);
CGRect lowerRight = CGRectMake(self.bounds.size.width - kSPUserResizableViewInteractiveBorderSize, self.bounds.size.height - kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);
CGRect lowerLeft = CGRectMake(0.0, self.bounds.size.height - kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);
CGRect upperMiddle = CGRectMake((self.bounds.size.width - kSPUserResizableViewInteractiveBorderSize)/2, 0.0, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);
CGRect lowerMiddle = CGRectMake((self.bounds.size.width - kSPUserResizableViewInteractiveBorderSize)/2, self.bounds.size.height - kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);
CGRect middleLeft = CGRectMake(0.0, (self.bounds.size.height - kSPUserResizableViewInteractiveBorderSize)/2, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);
CGRect middleRight = CGRectMake(self.bounds.size.width - kSPUserResizableViewInteractiveBorderSize, (self.bounds.size.height - kSPUserResizableViewInteractiveBorderSize)/2, kSPUserResizableViewInteractiveBorderSize, kSPUserResizableViewInteractiveBorderSize);

// (3) Create the gradient to paint the anchor points.
CGFloat colors [] = { 
    0.4, 0.8, 1.0, 1.0, 
    0.0, 0.0, 1.0, 1.0
};
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2);
CGColorSpaceRelease(baseSpace), baseSpace = NULL;

// (4) Set up the stroke for drawing the border of each of the anchor points.
CGContextSetLineWidth(context, 1);
CGContextSetShadow(context, CGSizeMake(0.5, 0.5), 1);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);

// (5) Fill each anchor point using the gradient, then stroke the border.
CGRect allPoints[8] = { upperLeft, upperRight, lowerRight, lowerLeft, upperMiddle, lowerMiddle, middleLeft, middleRight };
for (NSInteger i = 0; i < 8; i++) {
    CGRect currPoint = allPoints[i];
    CGContextSaveGState(context);
    CGContextAddEllipseInRect(context, currPoint);
    CGContextClip(context);
    CGPoint startPoint = CGPointMake(CGRectGetMidX(currPoint), CGRectGetMinY(currPoint));
    CGPoint endPoint = CGPointMake(CGRectGetMidX(currPoint), CGRectGetMaxY(currPoint));
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
    CGContextRestoreGState(context);
    CGContextStrokeEllipseInRect(context, CGRectInset(currPoint, 1, 1));
}
CGGradientRelease(gradient), gradient = NULL;
CGContextRestoreGState(context);
}

@end

我将其重新编码为...

导入 UIKit

class GripViewBorderView: UIView {

    let kUserResizableViewInteractiveBorderSize:CGFloat = 10.0

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }


    override func draw(_ rect:CGRect) {
        let context = UIGraphicsGetCurrentContext();
        context!.saveGState();

        // (1) Draw the bounding box.
        context!.setLineWidth(1.0);
        context!.setStrokeColor(UIColor.blue.cgColor)
        //CGContextAddRect(context!, CGRectInset(self.bounds, (kSPUserResizableViewInteractiveBorderSize / 2.0), (kSPUserResizableViewInteractiveBorderSize / 2.0)));
        context!.addRect(self.bounds.insetBy(dx: (kUserResizableViewInteractiveBorderSize / 2.0), dy: (kUserResizableViewInteractiveBorderSize / 2.0)))
        context!.strokePath();

        // (2) Calculate the bounding boxes for each of the anchor points.
        let upperLeft = CGRect(x: 0.0, y: 0.0, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize)
        let upperRight = CGRect(x: self.bounds.size.width - kUserResizableViewInteractiveBorderSize, y: 0.0, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize);
        let lowerRight = CGRect(x: self.bounds.size.width - kUserResizableViewInteractiveBorderSize, y: self.bounds.size.height - kUserResizableViewInteractiveBorderSize, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize);
        let lowerLeft = CGRect(x: 0.0, y: self.bounds.size.height - kUserResizableViewInteractiveBorderSize, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize);
        let upperMiddle = CGRect(x: (self.bounds.size.width - kUserResizableViewInteractiveBorderSize)/2, y: 0.0, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize);
        let lowerMiddle = CGRect(x: (self.bounds.size.width - kUserResizableViewInteractiveBorderSize)/2, y: self.bounds.size.height - kUserResizableViewInteractiveBorderSize, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize);
        let middleLeft = CGRect(x: 0.0, y: (self.bounds.size.height - kUserResizableViewInteractiveBorderSize)/2, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize);
        let middleRight = CGRect(x: self.bounds.size.width - kUserResizableViewInteractiveBorderSize, y: (self.bounds.size.height - kUserResizableViewInteractiveBorderSize)/2, width: kUserResizableViewInteractiveBorderSize, height: kUserResizableViewInteractiveBorderSize);

        // (3) Create the gradient to paint the anchor points.
        let baseSpace = CGColorSpaceCreateDeviceRGB()
        //let gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 2)
        let colors = [UIColor.red.cgColor,
                     UIColor.yellow.cgColor]

        let gradient = CGGradient(colorsSpace: baseSpace, colors: colors as CFArray, locations: nil)

        // (4) Set up the stroke for drawing the border of each of the anchor points.
        context!.setLineWidth(1)
        context!.setShadow(offset: CGSize(width: 0.5, height: 0.5), blur: 1)
        context!.setStrokeColor(UIColor.white.cgColor)

        // (5) Fill each anchor point using the gradient, then stroke the border.
        let allPoints:[CGRect] = [ upperLeft, upperRight, lowerRight, lowerLeft, upperMiddle, lowerMiddle, middleLeft, middleRight ];
        for i in 0 ... 7 {
            let currPoint = allPoints[i]
            context!.saveGState()
            context!.addEllipse(in: currPoint)
            context!.clip()
            let startPoint = CGPoint(x: currPoint.midX, y: currPoint.minY);
            let endPoint = CGPoint(x: currPoint.midX, y: currPoint.maxY);
            context!.drawLinearGradient(gradient!, start: startPoint, end: endPoint, options: .init(rawValue: 0))
            context!.saveGState()
            context!.strokeEllipse(in: currPoint.insetBy(dx: 1, dy: 1))
        }
        context!.restoreGState()
    }


}

但是我错过了一些东西,因为 OOC 在左边,而我的新 Swift 在右边。由于我无法想象在我的版本中只绘制了一个点,OOC 版本 [正确] 绘制了 8 个点。

enter image description here

最佳答案

您在 for 循环的末尾编写了 context!.saveGState() 来代替 CGContextRestoreGState(context)。当然,它应该是 context!.restoreGState()。简单的错字!

此外,请删除所有分号,并使用 guard let context = UIGraphicsGetCurrentContext() else { return } 来摆脱所有那些强制展开!

关于objective-c - 两个例程,一个在 Objective-C 中,另一个在 Swift 中,相同的代码产生本质不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42089219/

相关文章:

objective-c - NSLog(...) 不正确的格式说明符会影响其他变量吗?

iphone - 来自 iOS 5 中后台地理围栏的通知?

ios - 我可以使用 ARKit 和 ARSK View 更改 anchor 或移动图像吗?

java - 动画:如何使动画在我访问另一个 Activity 并返回后重复播放?

objective-c - GCD dispatch_async 和 NSURLConnection

objective-c - 像从 cmd+tab 一样获取 ProcessList

ios - 检查http响应格式

swift - 如何在 swift playground 中使用 carthage 导入的框架

ios - 用于简化 Objective C 中的 Singleton 方法调用的宏,以执行类似 NSLocalizedString 的操作

trans twig 过滤器中的 Symfony2 HTML