从设置加载UIView变换和中心给出不同的位置

sbk*_*bkp 5 iphone transform center uiview uigesturerecognizer

我正在使用平移,捏合和旋转UIGestureRecognizers,以允许用户将某些UI元素准确放置在他们想要的位置.使用此处的代码http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more(或类似的代码来自http://mobile.tutsplus.com/ tutorials/iphone/uigesturerecognizer /)都给了我用户根据需要放置这些UI元素所需的内容.

当用户退出"UI布局"模式时,我保存UIView的变换和中心,如下所示:

NSString *transformString = NSStringFromCGAffineTransform(self.transform);
[[NSUserDefaults standardUserDefaults] setObject:transformString forKey:@"UItransform", suffix]];

NSString *centerString = NSStringFromCGPoint(self.center);
[[NSUserDefaults standardUserDefaults] setObject:centerString forKey:@"UIcenter"];
Run Code Online (Sandbox Code Playgroud)

当我重新加载应用程序时,我阅读了UIView的转换和中心,如下所示:

NSString *centerString = [[NSUserDefaults standardUserDefaults] objectForKey:@"UIcenter"];
if( centerString != nil )
    self.center = CGPointFromString(centerString);

NSString *transformString = [[NSUserDefaults standardUserDefaults] objectForKey:@"UItransform"];

if( transformString != nil )
    self.transform = CGAffineTransformFromString(transformString);
Run Code Online (Sandbox Code Playgroud)

并且UIView最终旋转并正确缩放,但是在错误的地方.此外,在再次进入"UI布局"模式时,我不能总是用各种手势抓取视图(好像所显示的视图不是手势识别器所理解的视图?)

我还有一个重置按钮,可以将UIView设置为transform标识,并将其设置center为从NIB加载时的状态.但是在加载改变的UIView中心并进行转换后,即使重置也不起作用.UIView的立场是错误的.

我的第一个想法是,由于那些手势代码示例改变了center,旋转必须围绕不同的中心发生(假设一些不可预测的移动,旋转和音阶序列).因为我不想保存整个编辑序列(虽然如果我想在布局模式中有一些撤消功能,这可能很方便),我改变了UIPanGestureRecognizer处理程序以使用转换来移动它.一旦我开始工作,我想只是保存变换会得到我当前的位置和方向,无论事情发生的顺序.但没有这样的运气.我仍然以这种方式得到一个古怪的位置.

所以我很茫然.如果UIView已被移动并旋转到新位置,我该如何以稍后加载它的方式保存该位置和方向并将UIView恢复到应该的位置?

如果我没有标记这个权利或者没有正确地解决它或者犯了一些其他的stackoverflow罪,请提前道歉.这是我第一次在这里发布.

编辑

到目前为止,我正在尝试这两个建议.我认为它们实际上是相同的(一个建议保存框架,另一个建议保存原点,我认为是frame.origin).

所以现在来自prefs代码的保存/加载包括以下内容.

保存:

NSString *originString = NSStringFromCGPoint(self.frame.origin);
[[NSUserDefaults standardUserDefaults] setObject:originString forKey:@"UIorigin"];
Run Code Online (Sandbox Code Playgroud)

加载(加载转换):

NSString *originString = [[NSUserDefaults standardUserDefaults] objectForKey:@"UIorigin"];
if( originString ) {
    CGPoint origin = CGPointFromString(originString);
    self.frame = CGRectMake(origin.x, origin.y, self.frame.size.width, self.frame.size.height);
}
Run Code Online (Sandbox Code Playgroud)

我得到相同的(或类似的 - 很难说)结果.事实上,我添加了一个按钮来重新加载prefs,一旦旋转视图,"重新加载"按钮将重复移动UIView一些偏移(好像帧或变换相对于它自己 - 我确定是一个线索,但我不确定它指向的是什么).

编辑#2

这让我想知道取决于视图frame.来自Apple http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html#//apple_ref/doc/uid/TP40009503-CH2-SW6(强调我的):

即使已将缩放或旋转因子添加到视图的变换中,center属性中的值也始终有效.对于frame属性中的值也是如此,如果视图的变换不等于identity变换,则该属性被视为无效.

编辑#3

好的,所以当我加载prefs时,一切看起来都很好.UI面板的boundsrect是{{0,0},{506,254}}.在VC的viewDidLoad方法结束时,一切似乎仍然没问题.但到实际显示的时候,bounds还有别的东西.例如:{{0,0},{488.321,435.981}}(看起来它在旋转和缩放后的超级视图中有多大).如果我将边界重置为它应该是什么,它会移回原位.

很容易将边界重置为他们应该以编程方式进行的操作,但我实际上不确定何时这样做!我想在viewDidLoad的末尾做这件事,但bounds在那一点上仍然是正确的.

编辑#4

我尝试在initWithCoder中捕获self.bounds(因为它来自NIB),然后在layoutSubviews中,将self.bounds重置为捕获的CGRect.这很有效.

但它似乎非常hacky和充满危险.这实际上不是正确的方法.(可以吗?)skram在下面的回答看起来很简单,但在应用重新加载时对我不起作用.

sbk*_*bkp 0

感谢所有贡献答案的人!它们的总和使我得出以下结论:

问题似乎是在bounds启动时从首选项加载转换后 CGRect 被重置,但在实时修改时更新首选项时却没有重置。

我认为有两种解决方案。一种方法是首先加载首选项 fromlayoutSubviews而不是 from viewDidLoad。调用bounds后似乎没有发生任何事情。layoutSubviews

然而,由于我的应用程序中的其他原因,从视图控制器的viewDidLoad. 所以我使用的解决方案是这样的:

// UserTransformableView.h
@interface UserTransformableView : UIView {
    CGRect defaultBounds;
}

// UserTransformableView.m
- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if( self ) {
        defaultBounds = self.bounds;
    }
    return self;
}

- (void)layoutSubviews {
    self.bounds = defaultBounds;
}
Run Code Online (Sandbox Code Playgroud)