- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这是我的第一个 iOS 项目,因此我在约束和自动布局方面遇到了困难。
这是我正在尝试做的。我想将 subview 添加到 UIScrollView。这是我以编程方式进行的,因为 subview 的数量不是静态的。当我只添加一个 subview (在代码或 XIB 中)或通过 XIB 添加多个 subview 时,我可以使自动布局和约束完美地工作。但是我无法让它在代码中使用动态数量的 subview 。
创建了多个 subview 实例,但由于约束不起作用,它们都在彼此之上。我希望他们在每场比赛中都排好队,这就是为什么我试图让约束发挥作用。 (目前我只是将 subview 的数量设置为 10,但这只是暂时的)
这是我的一些代码(从按下按钮开始):
-(IBAction) buttonTapped:(id)sender {
UIScrollView *matchScrollView = (UIScrollView *) [self.view viewWithTag:1];
NSMutableArray *matchViewsArray = [[NSMutableArray alloc] init];
for (int i = 0; i <= 9; i++) {
MatchView *newMatchView = [[NSBundle mainBundle] loadNibNamed:@"MatchView" owner:self options:nil].firstObject;
[matchViewsArray addObject:newMatchView];
}
for (int i = 0; i < [matchViewsArray count]; i++) {
MatchView *newMatchView = matchViewsArray[i];
//I kept some IBOutlets out of the code example here. They work fine with a single subview. or even multiple subviews as long as you don't mind they are all on top of each other due to constraints not working xD
[newMatchView setTranslatesAutoresizingMaskIntoConstraints:NO];
[matchScrollView addSubview:matchViewsArray[i]];
[matchScrollView addConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i]
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:matchScrollView
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:8.0]];
[matchScrollView addConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i]
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:matchScrollView
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:8.0]];
//If this is not the first object, then the top of the object contraints with the bottom of the previous object
if (i > 0) {
// I think the fault may lie here. Do i need to remove the previous constraint, or will it be overwritten? This did not work however, did i remove it wrong?
//Making sure it only tries to call removeconstraint: once and once only, as the constraint is only put on the else statement which only executes on the very first object. Attempt to fix the code
if (i == 1) {
[matchScrollView removeConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i - 1]
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:matchScrollView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:8.0]];
}
[matchViewsArray[i - 1] addConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i]
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:matchViewsArray[i - 1]
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:8.0]];
}
//The top of the first object constraints with the top of the matchScrollView
else {
[matchScrollView addConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i]
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:matchScrollView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:8.0]];
}
//If this is the last object, then the bottom of the object constraints with the bottom of matchScrollView
if ( i == [matchViewsArray count] - 1) {
//tried removing the constraint created by else statement first before adding a new constraint
[matchViewsArray[i] removeConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i - 1]
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:matchViewsArray[i]
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:8.0]];
[matchScrollView addConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i]
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationGreaterThanOrEqual
toItem:matchScrollView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:8.0]];
}
//else the bottom of the object contraints with the top of the next object
else {
[matchViewsArray[i + 1] addConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i]
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:matchViewsArray[i + 1]
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:8.0]];
}
[matchScrollView addConstraint:[NSLayoutConstraint constraintWithItem:matchViewsArray[i]
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:matchScrollView
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
}
我一直收到“以 NSException 类型的未捕获异常终止”。我尝试在添加新约束之前删除旧约束,但这没有帮助。除非我删除错误?
如果我删除所有的 if 和 else 语句,只创建一个 subview ,那么约束就可以完美地工作。如果我创建多个 subview ,那么应用程序不会崩溃,但所有 subview 都具有相同的约束并且彼此重叠。因此,通过添加 if 和 else 语句并使用 matchViewsArray[i - 1],我尝试为多个 subview 设置约束。
此外,即使这段代码有效,真的没有更简单的方法来代替循环中的所有这些 if 和 else 语句吗?
如前所述,这是我的第一个 iOS 项目,因此可能有更高效、更好的方法来实现我想要的行为。
如有任何帮助,我们将不胜感激。
最佳答案
不幸的是,我没有制作 iOS 应用程序的许可证,也无法按原样对其进行测试,但这个 OSX 代码片段可能会有所帮助:
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
NSView *contentView = [window contentView];
NSMutableArray *buttons = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) {
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
[button setTranslatesAutoresizingMaskIntoConstraints:NO];
[button setTitle:[NSString stringWithFormat:@"Button %d", (int)pow(10, i)]];
[button setBezelStyle:NSRoundedBezelStyle];
[button setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
[button sizeToFit];
[buttons addObject:button];
[contentView addSubview:button];
}
int count = (int)[buttons count];
// 1. one below other
// 2. all equal width
for (int i = 1; i < count; i++) {
NSView *view1 = buttons[i-1];
NSView *view2 = buttons[i];
NSDictionary *views = NSDictionaryOfVariableBindings(view1, view2);
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view1]-[view2]"
options:0
metrics:nil
views:views]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view1(==view2)]"
options:0
metrics:nil
views:views]];
}
// 3. first -> top
if (count > 0) {
NSView *view = [buttons firstObject];
NSDictionary *views = NSDictionaryOfVariableBindings(view);
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]"
options:0
metrics:nil
views:views]];
}
// 4. last -> bottom
if (count > 0) {
NSView *view = [buttons lastObject];
NSDictionary *views = NSDictionaryOfVariableBindings(view);
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view]-|"
options:0
metrics:nil
views:views]];
}
// 5. left <- all -> right
for (int i = 0; i < count; i++) {
NSView *view = buttons[i];
NSDictionary *views = NSDictionaryOfVariableBindings(view);
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-(>=20)-|"
options:0
metrics:nil
views:views]];
}
}
请注意,您不能在不使用“视觉格式语言”的情况下指定默认的 8/20 间距,因为 constraintsWithVisualFormat:...
会产生特殊的约束(好吧,里面有特殊的私有(private)标志)自动- 在特定情况下将 8 调整为 6/4/根据 Apple 的 HIG 调整大小。 (您可以尝试在 IB 中放置控件并发现默认值并不总是 8,但在运行时它突然是!)。
编辑:此外,您可以始终使用简单的#define 或子例程来隐藏 [[[content-constraint-with-contraint-visual-constraint-with-constraints-ponies]]]梯子。
edit2: 重构阶段:)
关于ios - 如何使约束(自动布局)以编程方式工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29661991/
我想做的是,如果鼠标位于“下一个”按钮上,它会以慢速向右滚动,如果鼠标没有位于“下一个”按钮上,它会停止滚动? 这是我的尝试http://jsfiddle.net/mdanz/nCCRy/14/ $(
StyleCop 是一个很棒的视觉工作室小插件。但它不会向您显示实时提示或提供任何自动修复。 随之而来的是 reSharper 和 StyleCop for reSharper,这是理想的解决方案,但
我为我的MatchQuery使用了模糊性选项,但是我想将模糊性值设置为auto。有什么办法吗? 另外,对于完成建议程序,您可以将其设置为支持unicode,对于我的MatchQuery,有什么方法可以
我想从表中获取一行[字符串名称,字符串密码,int 某些内容]并将其映射到一个 User 对象,该对象具有 3 个属性,如上面的 getter 和 setter有什么方法可以自动完成吗?我考虑过反射,
我有一个像这样的方法:void m1(string str) 并且有一个像这样的类: public class MyClass { public bool b1 { set; get; }
我正在尝试使用 $rootScope 从一个 Controller 向另一个 Controller $broadcast 一些数据。 如果我使用像 ng-click 这样的触发器来运行将广播的功能,它
我考虑了很多关于是要使用完全自动化的缓存还是手动缓存。 我们的自动方法是一种解决方案,它可以挖掘数据库、查询和格式化每个潜在和 future 的数据请求,并将其保存到适当的缓存存储(内存缓存或基于磁盘
我的 CSS 必须使用过渡来更改,直到现在我都使用 div:hover 来实现。 当您单击另一个 div 时需要激活过渡,而不是当您将鼠标悬停在必须移动/更改的 div 上时。 我该怎么做? 谢谢 永
在我的应用程序中,我需要一些动画,但如果它已经设置了动画,则不需要持续时间。但我的问题是它会自动添加持续时间。 在这里你可以看到 2 个函数,第二个没有持续时间但它确实有持续时间(可能从 1 秒开始)
两年前,我需要制作一个工具,通过 POST 自动将 txt/csv 文件上传到我的 Web 服务器,然后使用 cronjob 通过 PHP 对其进行解析。 这有两次在每天午夜自动发生。尽管这行得通,但
请阅读下面程序中的评论: #include void test(char c[]) { c=c+2; //why does this work ? c--; printf("%
也许是个幼稚的问题,但是...... 确认或拒绝: 自动和静态存储持续时间的对象/变量的内存的存在是在编译时确定的,程序运行时失败的可能性绝对为零,因为没有足够的内存用于自动对象。 自然地,当自动对象
有没有什么方法可以自动获得类中属性更改的通知,而不必在每个 setter 中都编写 OnPropertyChanged? (我有数百个属性,我想知道它们是否已更改)。 安东建议 dynamic pro
我们在使用 Azure DevOps 的项目中采用了 gitflow 流程。我有以下场景: 当功能分支合并到 Develop 时,我想在完成拉取请求的同时执行压缩合并策略 当 Release 分支定期
我的网站上有一个评论部分,我将 html 编码的评论保存在我的数据库中。所以我添加了这条评论- "testing" `quotes` \and backslashes\ and html 并将其保存在
是否存在“ checkin 前 TFS 自动 checkout ”这样的功能,以便在我说“ checkin ”之前我不会 checkout 任何文件,例如以防我只是临时更改文件 - 这一直发生。 换句
我有一个运行在 Linux/Apache/Tomcat 堆栈上的网站,它需要每隔几个月自动脱机以进行服务器维护,这将持续任意时间。有哪些选项可以让 Apache 建立和取消“服务器维护”页面? 我需要
我经常在工作中创建文档,在公司内部,由于我们使用的首字母缩写词和缩写词的数量,我们几乎拥有自己的语言。因此,我厌倦了在发布文档之前手动创建首字母缩写词和缩写表,并且快速的谷歌搜索发现了一个可以有效地为
我希望在用户或宏将计算模式从自动更改为手动或手动更改为自动时运行代码。是否有为此触发的事件? (属性是 Application.Calculation 在 Excel 互操作中。) 使用 Excel
这个问题在这里已经有了答案: Repeat command automatically in Linux (13 个回答) 6年前关闭。 我想创建一个脚本来获取另一个文件夹中的所有文件夹名称。并为这些
我是一名优秀的程序员,十分优秀!