我很惭愧地发布这个,但我变得绝望了。
在谈到 AutoLayout 时,我是一个菜鸟。这主要是因为我的应用程序中有将近 60 个不同的屏幕。为什么要改变有效的方法?不管怎样,我不使用 XIBs/NIBs/Storyboards,因为任何时候我需要对应用程序范围的 UI 进行更改,我都必须修复一堆东西。相反,我有自己的一组 UIViewController 子类。其中之一只有一个 UITableView,很像 UITableViewController。我可以在睡梦中制作 UITableViews。
我有一个新屏幕,需要在 TableView 的标题中添加几个按钮。我正在尝试更好地使用 AutoLayout,所以我会尽可能地使用它。没有进一步的叙述,这里有一个非常简短的独立示例。
#import "AppDelegate.h"
@interface TestViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) NSArray *rows;
@end
@implementation TestViewController
- (void) loadView {
UITableView *tv = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] bounds] style:UITableViewStyleGrouped];
[tv setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
[tv setDelegate:self];
[tv setDataSource:self];
[self setView:tv];
UIView *tableHeader = [[UIView alloc] init];
[tableHeader setTranslatesAutoresizingMaskIntoConstraints:NO];
[tv setTableHeaderView:tableHeader];
UIButton *selectProfileButton = [UIButton buttonWithType:UIButtonTypeCustom];
[selectProfileButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[selectProfileButton setShowsTouchWhenHighlighted:YES];
[selectProfileButton setTitle:@"Select Profile..." forState:UIControlStateNormal];
[tableHeader addSubview:selectProfileButton];
UIButton *editProfileButton = [UIButton buttonWithType:UIButtonTypeCustom];
[editProfileButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[editProfileButton setImage:[UIImage imageNamed:@"EditAccessoryIcon"] forState:UIControlStateNormal];
[tableHeader addSubview:editProfileButton];
UIEdgeInsets padding = UIEdgeInsetsMake(5, 10, 5, 5);
// select button in NW corner
[tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
toItem:tableHeader attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top]];
[tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
toItem:tableHeader attribute:NSLayoutAttributeLeft multiplier:1.0 constant:padding.left]];
[tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
toItem:tableHeader attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-padding.bottom]];
// edit button in NE corner
[tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:editProfileButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
toItem:tableHeader attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top]];
[tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:editProfileButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
toItem:tableHeader attribute:NSLayoutAttributeRight multiplier:1.0 constant:-padding.right]];
[tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:editProfileButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
toItem:tableHeader attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-padding.bottom]];
// spacing between buttons
[tableHeader addConstraint:[NSLayoutConstraint constraintWithItem:selectProfileButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
toItem:editProfileButton attribute:NSLayoutAttributeLeft multiplier:1.0 constant:-10.0]];
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [[self rows] count]; }
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
[[cell textLabel] setText:[[self rows] objectAtIndex:[indexPath row]]];
return cell;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
TestViewController *test = [[TestViewController alloc] init];
[test setRows:@[@"1", @"2", @"3"]];
[[self window] setRootViewController:test];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
@end
不幸的是,在运行时我得到了这个:
2014-07-11 13:18:48.502 TestTableHeader[9478:60b] *** Assertion failure in -[UITableView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2935.137/UIView.m:8794
2014-07-11 13:18:48.505 TestTableHeader[9478:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'
*** First throw call stack:
(
0 CoreFoundation 0x017ed1e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0156c8e5 objc_exception_throw + 44
2 CoreFoundation 0x017ed048 +[NSException raise:format:arguments:] + 136
3 Foundation 0x0114c4de -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
4 UIKit 0x0029ba38 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 567
5 libobjc.A.dylib 0x0157e82b -[NSObject performSelector:withObject:] + 70
6 QuartzCore 0x03c5845a -[CALayer layoutSublayers] + 148
7 QuartzCore 0x03c4c244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
8 QuartzCore 0x03c583a5 -[CALayer layoutIfNeeded] + 160
9 UIKit 0x0035dae3 -[UIViewController window:setupWithInterfaceOrientation:] + 304
10 UIKit 0x00273aa7 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 5212
11 UIKit 0x00272646 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 82
12 UIKit 0x00272518 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 117
13 UIKit 0x002725a0 -[UIWindow _setRotatableViewOrientation:duration:force:] + 67
14 UIKit 0x0027163a __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 120
15 UIKit 0x0027159c -[UIWindow _updateToInterfaceOrientation:duration:force:] + 400
16 UIKit 0x002722f3 -[UIWindow setAutorotates:forceUpdateInterfaceOrientation:] + 870
17 UIKit 0x002758e6 -[UIWindow setDelegate:] + 449
18 UIKit 0x0034fb77 -[UIViewController _tryBecomeRootViewControllerInWindow:] + 180
19 UIKit 0x0026b474 -[UIWindow addRootViewControllerViewIfPossible] + 591
20 UIKit 0x0026b5ef -[UIWindow _setHidden:forced:] + 312
21 UIKit 0x0026b86b -[UIWindow _orderFrontWithoutMakingKey] + 49
22 UIKit 0x002763c8 -[UIWindow makeKeyAndVisible] + 65
23 TestTableHeader 0x00002dfa -[AppDelegate application:didFinishLaunchingWithOptions:] + 890
24 UIKit 0x0022614f -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 309
25 UIKit 0x00226aa1 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1810
26 UIKit 0x0022b667 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824
27 UIKit 0x0023ff92 -[UIApplication handleEvent:withNewEvent:] + 3517
28 UIKit 0x00240555 -[UIApplication sendEvent:] + 85
29 UIKit 0x0022d250 _UIApplicationHandleEvent + 683
30 GraphicsServices 0x037e2f02 _PurpleEventCallback + 776
31 GraphicsServices 0x037e2a0d PurpleEventCallback + 46
32 CoreFoundation 0x01768ca5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
33 CoreFoundation 0x017689db __CFRunLoopDoSource1 + 523
34 CoreFoundation 0x0179368c __CFRunLoopRun + 2156
35 CoreFoundation 0x017929d3 CFRunLoopRunSpecific + 467
36 CoreFoundation 0x017927eb CFRunLoopRunInMode + 123
37 UIKit 0x0022ad9c -[UIApplication _run] + 840
38 UIKit 0x0022cf9b UIApplicationMain + 1225
39 TestTableHeader 0x00002fed main + 141
40 libdyld.dylib 0x01e34701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
根据我的阅读,这意味着我缺少一个约束。 UIButtons 有一个固有的大小,所以我只需要设置它们的位置。容器 UIView 将由 UITableView 调整大小,因此无需执行任何操作。 (我什至尝试设置咯咯笑的高度——我没有咯咯笑。)
我哪里搞砸了?
谢谢!
更新了示例代码和堆栈以提供简短的独立示例。
最佳答案
我遇到了同样的问题。我认为这不是由于缺少约束造成的。这是因为 UITableView 显然没有正确处理带有自动布局的页眉/页脚。对我有用的解决方法是使用 systemLayoutSizeFittingSize: 方法设置框架:
//initialize tableHeader, add subviews and constraints
CGSize size = [tableHeader systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
tableHeader.frame = (CGRect){.origin = CGPointZero, .size = size};
self.tableView.tableHeaderView = tableHeader;
请注意,我没有将translatesAutoresizingMaskIntoConstraints设置为NO。
此外,您似乎还没有添加所有需要的约束。您只定位按钮,但您的 tableHeader 不知道如何计算其自己的宽度和高度。您可能需要使 selectProfileButton(或其他按钮)的底部等于 tableHeader 的底部,并在按钮之间添加一个(最小)水平间距。
另外,据我所知,UITableView 会将 tableHeader 的宽度扩展到它自己的宽度,而不管任何约束。
关于ios - 如何使用 AutoLayout 使 UITableView header 的这个简单布局正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24686899/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru