7

我的UIScrollView子视图出现了奇怪的行为,这个想法是以编程方式创建一个UIView带有自定义 nib 文件的实例,在我的情况下这是一个表单,用模型类中的数据填充该表单,并将其添加为我的UIScrollView. 问题是当我处理多个子视图时,UIScrollView只保留最新的子视图,所以如果我创建了三个子视图,滚动视图将只显示第三个(最新的)子视图。虽然页面控件设置为子视图的核心数量(三个)。

该项目太长了,所以我将尝试用相关代码简要解释我的问题:

- (void)viewDidLoad {

    NSArray *sorted = [appArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];//this array contains the data from model, I debugged that to make sure I got the exact data, no more no less :)


    //Loop all NSManaged objects, for example let's say I have 3 model objects, don't worry about how I get data etc, because I debugged all and maked sure all data objects number are exact, etc.
    for (App_Table *_appTable in sorted) {
    //This looped 3 times as expected, I debugged that also and maked sure on each iteration I got the data I expected to have
    //App_Table is a subclass of NSManagedObject, it's my model class and get its data from coredata file
    [self addMoreView];//Call this method will create a new subview and add it as subview to the UIScrollView, it will also update the page control, update the content size property, etc.

    AppTableView *_appTableView = (AppTableView *) [[self.scrollView subviews] lastObject];//Remember addMoreView method create a new instance of AppTableView and add it as subview for the UIScrollView property, then I get that subview to fill it with data here

    _appTableView.txtADDRESS.text = _appTable.address;//Fill in the form, no need to write all the form fields code because it's the same way.

    // Scroll To First Page...
    self.pageControl.currentPage = 0;
    [self.scrollView scrollRectToVisible:CGRectMake(0, 0, viewWidth, viewHeight) animated:YES];

    self.scrollView.contentSize = CGSizeMake(viewWidth*noOfItems, viewHeight);//Set the content size to the sum of subviews width, I also debugged that to check it's correct
    self.scrollView.delegate = self;

    [super viewDidLoad];
}

好的,所以当我有三个子视图时,滚动视图将加载三个子视图的宽度,如上面的行计算:

self.scrollView.contentSize = CGSizeMake(viewWidth*noOfItems, viewHeight);//Set the content size to the sum of subviews width, I also debugged that to check it's correct

我可以滚动到 3 次移动(这是子视图的数量)并且UIPageControl也设置为三个点,但只有一个子视图可见,只有我能看到的最新一个,其他两个子视图消失了,滚动视图计算了内容它们的大小,但它们不可见。有什么想法吗 ?谢谢。

编辑:

值得注意的是,我第一次编辑视图时,一切正常,当我处理 3 个子视图时,它们都是可见的,但是当我转到另一个视图并回到这个视图时,只有最后一个子视图是可见的。

此外,我正在开发一个带有拆分视图的 iPad 项目。

编辑: 这是为UIScrollView

 -(IBAction) addMoreView
    {

        NSArray *arr = [[NSBundle mainBundle] loadNibNamed:@"AppTableView" owner:self options:nil];

        AppTableView *aView = [arr objectAtIndex:0];
        [aView setFrame:CGRectMake(startX, 0, aView.bounds.size.width, aView.bounds.size.height)];
        [self.scrollView addSubview:aView];
        self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width+aView.frame.size.width
                                             , self.scrollView.contentSize.height);


        startX = startX + aView.frame.size.width;//Update the X position, first 0, then 600, 1200, and so on.
        [self.scrollView scrollRectToVisible:aView.frame animated:YES];
        NSLog(@"%f",self.scrollView.contentSize.width);
        NSLog(@"%f",self.scrollView.contentSize.height);

    }

假设我有 3 个子视图,上面的方法将被调用 3 次,因为它被放入for循环中。所以这是NSLogs上述方法的结果:

NSLog(@"%f",self.scrollView.contentSize.width);
NSLog(@"%f",self.scrollView.contentSize.height);

    First iteration:

    600.000000

    0.000000

    Second iteration:

    1200.000000

    0.000000

    Third iteration:

    1800.000000

    0.000000

编辑:

rob mayoff 建议的命令让我明白为什么会发生这种情况:

   |    |    |    | <AppTableView: 0x1eef4700; frame = (0 18; 600 430); autoresize = LM+RM+TM+BM; tag = 990; layer = <CALayer: 0x1eef4790>>

   |    |    |    | <AppTableView: 0x1ee3f380; frame = (0 18; 600 430); autoresize = LM+RM+TM+BM; tag = 991; layer = <CALayer: 0x1ee3f410>>

   |    |    |    | <AppTableView: 0x1ee56910; frame = (0 18; 600 430); autoresize = LM+RM+TM+BM; tag = 992; layer = <CALayer: 0x1ee3f410>>

所有三个子视图都绘制在同一个框架中,因此它们彼此上方,但是当我在运行时使用断点进行调试时,它们x正在发生变化,第一次是 0,然后是 600,然后是 1200,这让我认为它绘制正确。如何解决这个问题,尤其是 x 值正在正确递增,那么问题是什么,为什么他们仍然在相同的 x 坐标上绘图?

4

7 回答 7

2

首先,您应该将[super viewDidLoad]调用放在- (void)viewDidLoad方法的顶部,而不是底部。

鉴于您实际看到的内容和期望看到的内容还不够清楚,将您的问题的最小工作示例作为可下载项目提供将有助于我们为您提供帮助。如果您只是尝试在不与托管对象交互但使用一些静态提供的数据的单独视图控制器中重现它,其他人将能够自己重现并调试它。或者你也可以在这个过程中自己弄清楚。

于 2013-05-01T09:01:47.767 回答
1

我回来的有点晚,但最后我找到了解决我的问题的方法,所以认为分享它以节省别人的时间是件好事。

就我而言,滚动视图是 nib 文件中的自定义视图。因此,通过在左侧和顶部激活其 Autosizing 蒙版,该错误得到了修复。

在此处输入图像描述

于 2013-08-21T21:43:47.090 回答
0

当然,您没有为 3 个项目正确设置内容大小:

self.scrollView.contentSize.width+aView.frame.size.width

应该

self.scrollView.contentSize.width+ ( aView.frame.size.width * NUMBER_OF_SUBVIEWS)

我想当您在滚动视图上水平滚动时,内容大小只允许一个子视图有足够的空间,对吗?

于 2013-04-25T09:03:20.580 回答
0

这段代码-addMoreView就是问题所在:

AppTableView *aView = [arr objectAtIndex:0];
[aView setFrame:CGRectMake(startX, 0, aView.bounds.size.width, aView.bounds.size.height)];
[self.scrollView addSubview:aView];

如果startX从未更改,则您将在同一位置添加所有这些视图。

于 2013-04-23T21:47:42.247 回答
0

尝试将 aView 设置autoresizingMaskUIViewAutoresizingNoneaddMoreView 方法内部。

于 2013-05-18T01:45:08.397 回答
0

使用了一个静态变量,该变量在加载时重新初始化为 0,然后它增加子视图的宽度以开始在新的 X 位置上绘图。

于 2013-05-01T18:24:02.157 回答
0

我在姐妹帖子中创建了一个使用您的代码的项目,并且它工作得很好。我在自动调整大小的掩码上添加了几个测试,如下所示。我建议您将其与您正在做的事情进行比较。当子视图或滚动视图上的掩码未设置为绑定到顶部/左侧时,会发生奇怪的事情。

我修改后的代码:

NSArray *colors = @[ [UIColor redColor], [UIColor greenColor], [UIColor blueColor] ];

UIViewAutoresizing mask;
mask = [self.scrollView autoresizingMask];
//assert(!self.scrollView.autoresizesSubviews); // has no affect here

if((mask & (UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin)) != mask) NSLog(@"scrollView MASK WRONG");

for (int i=0; i<3; ++i) {

    NSArray *arr = [[NSBundle mainBundle] loadNibNamed:@"AppTableView" owner:self options:nil];

    NSLog(@"scrollView frame: %@", NSStringFromCGRect(self.scrollView.frame));
    if((mask & (UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin)) != mask) NSLog(@"aView MASK WRONG");

    AppTableView *aView = [arr objectAtIndex:0];
    assert([aView isKindOfClass:[AppTableView class]]);
    NSLog(@"orig aView frame: %@", NSStringFromCGRect(aView.frame));
    UIViewAutoresizing mask = [aView autoresizingMask];
    if((mask & (UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin)) != mask) NSLog(@"aView MASK WRONG");


    aView.frame = CGRectMake(startX, 0, aView.bounds.size.width, aView.bounds.size.height);
    NSLog(@"changed aView frame: %@", NSStringFromCGRect(aView.frame));
    aView.backgroundColor = colors[i];

    [self.scrollView addSubview:aView];
    self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width+aView.frame.size.width
                                             ,self.scrollView.contentSize.height);
    startX = startX + aView.frame.size.width;

   //AppTableView *_appTableView = (AppTableView *) [[self.scrollView subviews] lastObject];

    //_appTableView.txtADDRESS.text = _appTable.address;//Fill in the form, no need to write all the form fields code because it's the same way.
}
NSLog(@"scrollView frame: %@", NSStringFromCGRect(self.scrollView.frame));
NSLog(@"scrollView contentOffset: %@", NSStringFromCGPoint(self.scrollView.contentOffset));
于 2013-05-18T16:34:53.580 回答