理解convertRect:toView:,convertRect:FromView:,convertPoint:toView:和convertPoint:fromView:methods

Lor*_*o B 127 layout uiview ios

我试图了解这些方法的功能.你能给我一个简单的用例来理解他们的语义吗?

从文档中,例如,convertPoint:fromView:方法描述如下:

将点从给定视图的坐标系转换为接收器的坐标系.

什么是坐标系是什么意思?接收器怎么样?

例如,使用convertPoint:fromView是否有意义:如下所示?

CGPoint p = [view1 convertPoint:view1.center fromView:view1];
Run Code Online (Sandbox Code Playgroud)

使用NSLog实用程序,我已经验证了p值与view1的中心重合.

先感谢您.

编辑:对于那些感兴趣的人,我创建了一个简单的代码片段来理解这些方法.

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 150, 200)];
view1.backgroundColor = [UIColor redColor];

NSLog(@"view1 frame: %@", NSStringFromCGRect(view1.frame));        
NSLog(@"view1 center: %@", NSStringFromCGPoint(view1.center));   

CGPoint originInWindowCoordinates = [self.window convertPoint:view1.bounds.origin fromView:view1];        
NSLog(@"convertPoint:fromView: %@", NSStringFromCGPoint(originInWindowCoordinates));

CGPoint originInView1Coordinates = [self.window convertPoint:view1.frame.origin toView:view1];        
NSLog(@"convertPoint:toView: %@", NSStringFromCGPoint(originInView1Coordinates));
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,self.window都是接收者.但是有区别.在第一种情况下,convertPoint参数以view1坐标表示.输出如下:

convertPoint:fromView:{100,100}

而在第二个中,convertPoint以superview(self.window)坐标表示.输出如下:

convertPoint:toView:{0,0}

jrt*_*ton 180

每个视图都有自己的坐标系 - 原点为0,0,宽度和高度.这bounds在视图的矩形中描述.该frame视图的,但是,将有它的起源在它的父的边界矩形内的点.

视图层次结构的最外层视图的原点是0,0,它对应于iOS中屏幕的左上角.

如果在该视图中添加20,30的子视图,则子视图中的0,0点对应于超视图中的20,30点.这种转换就是那些方法正在做的.

上面的例子没有意义(没有双关语意),因为它将一个点从视图转换为自身,所以什么都不会发生.您更常见的是查看某个视图与其超级视图相关的位置 - 测试视图是否正在移出屏幕,例如:

CGPoint originInSuperview = [superview convertPoint:CGPointZero fromView:subview];
Run Code Online (Sandbox Code Playgroud)

"接收器"是接收消息的对象的标准目标-c术语(方法也称为消息),因此在我的示例中接收器是superview.

  • 感谢您的回复,jrturton.非常有用的解释.`convertPoint`和`convertRect`在返回类型上有所不同.`CGPoint`或`CGRect`.但是`from`和`to`怎么样?我可以使用经验法则吗?谢谢. (3认同)
  • 如果superview不是子视图的直接父视图,它仍然可以工作吗? (3认同)
  • @VanDuTran是的,只要它们在同一个窗口中(iOS应用程序中的大多数视图都是) (3认同)

phi*_*phi 36

我总觉得这让人很困惑所以我做了一个游乐场,你可以在视觉上探索这个convert功能的作用.这是在Swift 3和Xcode 8.1b中完成的:

import UIKit
import PlaygroundSupport

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Main view
        view.backgroundColor = .black
        view.frame = CGRect(x: 0, y: 0, width: 500, height: 500)

        // Red view
        let redView = UIView(frame: CGRect(x: 20, y: 20, width: 460, height: 460))
        redView.backgroundColor = .red
        view.addSubview(redView)

        // Blue view
        let blueView = UIView(frame: CGRect(x: 20, y: 20, width: 420, height: 420))
        blueView.backgroundColor = .blue
        redView.addSubview(blueView)

        // Orange view
        let orangeView = UIView(frame: CGRect(x: 20, y: 20, width: 380, height: 380))
        orangeView.backgroundColor = .orange
        blueView.addSubview(orangeView)

        // Yellow view
        let yellowView = UIView(frame: CGRect(x: 20, y: 20, width: 340, height: 100))
        yellowView.backgroundColor = .yellow
        orangeView.addSubview(yellowView)


        // Let's try to convert now
        var resultFrame = CGRect.zero
        let randomRect: CGRect = CGRect(x: 0, y: 0, width: 100, height: 50)

        /*
        func convert(CGRect, from: UIView?)
        Converts a rectangle from the coordinate system of another view to that of the receiver.
        */

        // The following line converts a rectangle (randomRect) from the coordinate system of yellowView to that of self.view:
        resultFrame = view.convert(randomRect, from: yellowView)

        // Try also one of the following to get a feeling of how it works:
        // resultFrame = view.convert(randomRect, from: orangeView)
        // resultFrame = view.convert(randomRect, from: redView)
        // resultFrame = view.convert(randomRect, from: nil)

        /*
        func convert(CGRect, to: UIView?)
        Converts a rectangle from the receiver’s coordinate system to that of another view.
        */

        // The following line converts a rectangle (randomRect) from the coordinate system of yellowView to that of self.view
        resultFrame = yellowView.convert(randomRect, to: view)
        // Same as what we did above, using "from:"
        // resultFrame = view.convert(randomRect, from: yellowView)

        // Also try:
        // resultFrame = orangeView.convert(randomRect, to: view)
        // resultFrame = redView.convert(randomRect, to: view)
        // resultFrame = orangeView.convert(randomRect, to: nil)


        // Add an overlay with the calculated frame to self.view
        let overlay = UIView(frame: resultFrame)
        overlay.backgroundColor = UIColor(white: 1.0, alpha: 0.9)
        overlay.layer.borderColor = UIColor.black.cgColor
        overlay.layer.borderWidth = 1.0
        view.addSubview(overlay)
    }
}

var ctrl = MyViewController()
PlaygroundPage.current.liveView = ctrl.view
Run Code Online (Sandbox Code Playgroud)

请记住显示助手编辑器()以查看视图,它应如下所示:

在此输入图像描述

随意在这里或在这个要点中贡献更多的例子.


hor*_*oe7 30

这是一个简单的英语解释.

当您想将子视图的矩形(aView是子视图[aView superview])转换为另一个视图的坐标空间(self)时.

// So here I want to take some subview and put it in my view's coordinate space
_originalFrame = [[aView superview] convertRect: aView.frame toView: self];
Run Code Online (Sandbox Code Playgroud)

  • 事实并非如此.它不会移动视图,它只是根据另一个视图为您提供视图的坐标.在你的情况下,它将根据他们在自己的位置为你提供aView的坐标. (3认同)

Sau*_*and 14

iOS中的每个视图都有一个坐标系.坐标系就像一个图形,它有x轴(水平线)和y轴(垂直线).线相互作用的点称为原点.点由(x,y)表示.例如,(2,1)表示该点是2个像素,1个像素向下.

您可以在此处阅读有关坐标系的更多信息 - http://en.wikipedia.org/wiki/Coordinate_system

但是你需要知道的是,在iOS中,每个视图都有它的OWN坐标系,左上角是原点.X轴继续向右增加,y轴继续向下增加.

对于转换点问题,请参考此示例.

有一个名为V1的视图,宽100像素,高100像素.现在在其中,还有另一个视图,称为V2,位于(10,10,50,50),这意味着(10,10)是V1坐标系中V2的左上角应该位于的点,并且( 50,50)是V2的宽度和高度.现在,请注意INSIDE V2的坐标系,比如说(20,20).现在,V1的坐标系内有什么意义呢?这就是方法的用途(当然你可以自己计算,但它们可以为你节省额外的工作).为了记录,V1中的点将是(30,30).

希望这可以帮助.


tob*_*jim 8

谢谢大家发布问题和答案:它帮助我解决了这个问题.

我的视图控制器有它的正常视图.

在该视图中,有许多分组视图,只是为其子视图提供与自动布局约束的干净交互.

在其中一个分组视图中,我有一个Add按钮,它显示一个popover视图控制器,用户可以在其中输入一些信息.

view
--groupingView
----addButton
Run Code Online (Sandbox Code Playgroud)

在设备旋转期间,视图控制器通过UIPopoverViewControllerDelegate调用提醒popoverController:willRepositionPopoverToRect:inView:

- (void)popoverController:(UIPopoverController *)popoverController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView *__autoreleasing *)view
{
    *rect = [self.addButton convertRect:self.addbutton.bounds toView:*view];
}
Run Code Online (Sandbox Code Playgroud)

上面前两个答案给出的解释的基本部分是我需要转换的矩形是添加按钮的边界,而不是它的框架.

我没有尝试使用更复杂的视图层次结构,但我怀疑通过使用方法调用(inView :)中提供的视图,我们可以解决多层叶视图中的各种丑陋问题.

  • "我需要转换为添加按钮的边界,而不是它的框架." - 基本上从很多丑陋的框架代码中拯救了我,使其成功.感谢您抽出宝贵时间指出这一点 (3认同)