我正在寻找执行segue以使用卷曲动画由另一个视图控制器替换窗口的根视图控制器.这个想法是我在使用curl up动画SplashViewController转换(performSegueWithIdentifier:)到下一个之前显示了几秒钟LoginViewController.
我创建了一个UIStoryboardSegue名为的自定义类AnimatedSegue.以下是重写perform方法的代码:
- (void)perform
{
UIViewController *source = self.sourceViewController;
UIViewController *destination = self.destinationViewController;
UIWindow *window = source.view.window;
[UIView transitionFromView:source.view
toView:destination.view
duration:1.0
options:UIViewAnimationOptionTransitionCurlUp
completion:^(BOOL finished) {
[window setRootViewController:destination];
}];
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但在iOS 6中(显然不是在iOS 5中),该viewWillAppear:方法在destination视图控制器上被调用两次.它似乎是在过渡期间第一次被称为第二次被执行时[window setRootViewController:destination];
请注意,我不想使用导航控制器.在SplashViewController被释放(如预期),但一旦转换了.
关于如何解决我的问题的任何想法?
我正在使用Xcode 4.5和iOS 6.
我正在构建一个使用故事板的通用应用程序.我有一个视图控制器,在导航栏中有一个按钮.当点击按钮时,我使用segue将另一个视图控制器呈现为模态.模态视图控制器的导航栏中有"取消"和"保存"按钮.在故事板中,模态按钮项链接到新的Exit操作上的操作,该操作应该解开到父视图控制器,关闭模态,并调用操作处理程序.
这在iPhone上工作正常,但我在iPad上看到了问题.在iPad上,当模式以全屏显示时,一切正常.当我将模式更改为页面表或表单(这是我的情况下所需的行为)时,将调用操作处理程序,但模式视图控制器不会自动被解除.
有没有人见过这种行为?你有没有做过修复它的事情?
谢谢.
我有两个segue's导致相同viewController.有2个按钮viewController使用2个segue 连接到同一个按钮.在那viewController我需要检查点击了哪个按钮.所以实际上我需要检查使用/预制的segue.我如何在viewControllers类中检查这个?我知道有prepareForSegue方法,但是我不能将它用于我的目的,因为我需要把它放在prepareForSegue2个按钮所在的类中,我不希望它在那里,但我想在viewControllers课堂上因为我需要访问它并在该类中设置一些变量.
在我的应用程序中,我使用故事板和segues,我经常在执行segue之前将数据传递到目标视图控制器,如下所示:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:@selector(setMyData:)]) {
[segue.destinationViewController performSelector:@selector(setMyData:)
withObject:myData];
}
}
Run Code Online (Sandbox Code Playgroud)
除了在一个地方,它无处不在.选择器被调用,数据被设置,但是当segue完成并且目标控制器出现时,它没有我刚刚设置的数据.在源视图控制器和目标视图控制器中打印视图控制器的ID后,我发现segue.destinationViewController上面的代码中的视图控制器的实例与显示控制器的实例不同.这里发生了什么?
[更新1]
我查看了目标视图控制器的生命周期,它首先在segue执行期间加载,但是我在它上面设置了属性!这意味着,当我调用performSelector它时,视图控制器对象没有初始化!这就是我设置的数据不坚持的原因.我不明白为什么会这样,为什么同样的方法适用于我的应用程序的其他部分.
[更新2]setMyData按要求
发布代码.起初我根本没有这种方法,因为它locationToOpen是一个公共财产.我只添加它以确保它被调用并打印调试信息.
- (void)setMyData:(MyData *)myData
{
DLog(@"self: %@", (id)self);
_myData = myData;
}
Run Code Online (Sandbox Code Playgroud) 我有两个UITableViewControllers,我在它们之间使用故事板进行区分.
在prepareForSegue:sender:,第一个VC从Web服务获取NSArray,并使用下载的数据设置目标VC的模型.我把下载部分放入一个dispatch_queue_t所以它将异步运行而不是阻止UI线程.我想点击一个表格单元格,让UIActivityIndicatorView开始旋转,下载照片,下载照片时,停止微调器并继续使用segue.
在第一个UITableViewController我有一个prepareForSegue:sender:方法:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"SelectPlace"]) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[spinner startAnimating];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];
__block NSArray *photos = [[NSMutableArray alloc] init];
dispatch_queue_t downloadQueue = dispatch_queue_create("flickr download", NULL);
dispatch_async(downloadQueue, ^{
photos = [FlickrFetcher photosInPlace:[self.places objectAtIndex:indexPath.row] maxResults:50];
});
dispatch_release(downloadQueue);
[spinner stopAnimating];
[segue.destinationViewController setPhotos:photos withTitle:[[sender textLabel] text]];
}
}
Run Code Online (Sandbox Code Playgroud)
现在它立即执行segue而不显示微调器或等待下载完成.
如何在不阻塞主线程的情况下异步下载数据以准备目标视图,还能不立即进行segueing?
要从代码创建两个视图控制器之间的父/子关系,基本上只需执行以下操作:
[self addChildViewController:childViewController];
[self.view addSubview:childViewController.view];
Run Code Online (Sandbox Code Playgroud)
其中self是父视图控制器.
但是,如果我想完全从Interface Builder创建相同的关系呢?
或者换句话说:有没有办法使用Interface Builder重新创建方法addChildViewController的行为?
我没有找到很多关于这方面的文档,这是一篇关于该主题的未解决的帖子:https://devforums.apple.com/message/455758#455758
如果没有正确设置addChildViewController关系,任何旋转方法都不会转发到我的子视图控制器,这是我的问题所在.
这就是我在IB中所做的:
图片中的第一个"View"对象是我的父视图控制器的视图,而突出显示的"View"是子视图控制器的视图("Item View Controller").

容器控制器还通过另外的IBOutlet保留其子实例:
@property (nonatomic, strong) IBOutlet ItemsViewController *itemsViewController;
Run Code Online (Sandbox Code Playgroud)
谢谢
更新1:如果我在容器控制器的viewDidLoad中手动设置父/子关系,则所有旋转方法都会正确转发给子项.
[self addChildViewController:self.itemsViewController];
Run Code Online (Sandbox Code Playgroud)
但我真的不知道这是否是正确的做法,因为我想用IB做所有事情.
更新2:感谢@micantox提示他使用对象库中的"容器视图",我已将我的xib文件转换为Storyboard,现在子视图控制器已添加到其父级,所以我没有必要使用addChildViewController从代码中手动添加它,并按预期转发旋转方法.
"容器视图"基本上实现了嵌入segue,仅支持iOS 6.
这是我的Storyboard更新的截图:

interface-builder uiviewcontroller uistoryboardsegue childviewcontroller container-view
在Xcode中创建故事板文件时,您必须选择是否适用于iPhone或iPad.这意味着应始终将iPhone和iPad UI放入单独的故事板中.这是真的?
我的应用程序有多个故事板.虽然Main.storyboard文件在iPhone和iPad之间存在很大差异,但其他故事板几乎完全相同.唯一的区别可能是推动iPhone与iPhone上的popover,可以通过编程方式处理.制作两个故事板似乎非常愚蠢和多余.
因此,如果制作一个"通用"故事板,是否应该在Xcode中选择iPhone或iPad?有关系吗?
在使用segue的导航中,从根控制器我们可以推送控制器A或B.
从A我们可以推C,它可以推B,以后可以放松到A重启过程.
从B我们可以推A,它可以推C,后来可以放松到B重启过程.
在B中,我们有一个按钮,上面写着"转到A",它必须根据场景放松或推动控制器A.

如果我能在预先形成push segue之前放松,我怎么能轻易地知道?
现在我使用navigationController数组来检查前一个控制器是否为C来推或放.我想知道使用segues的这种循环的通用解决方案,例如:
如果B可以放松到A 然后放松其他推A
所以,问题是,如何检查B可以在不访问navigationController数组的情况下放松到A?
我有一个UICollectionView当用户按下单元格时,我UINavigationController使用故事板以模态方式呈现另一个视图控制器.
- (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:@"editBookIPad"
sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender
{
// Did not include code for other segues, but I check which is the current one properly
UINavigationController *dest = segue.destinationViewController; // This is nil!
dest.modalPresentationStyle = UIModalPresentationFormSheet;
DetailsViewController *detailsVC = (id)[dest topViewController];
detailsVC.stack = self.stack;
detailsVC.editingMode = 1;
detailsVC.bookToEdit = [self.fetchedResultsController objectAtIndexPath:sender];
[self.collectionView deselectItemAtIndexPath:sender
animated:YES];
}
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是segue.desinationViewController返回nil(如代码片段中的注释所示).
只是为了调试,我改为UINavigationController另一个视图控制器,我没有问题.我不知道是否从modal更改为push作为过渡样式会有所帮助,因为它不可能推动a UINavigationController(发生崩溃事件就是这样).
我清理了项目和构建文件夹,然后重新启动了我的计算机(以及Xcode).
这是运行应用程序时的样子:

在寻找类似的问题时,我发现了这一点.大多数其他问题是关于在目标视图控制器上设置的属性为nil(例如 …
我做了一个习惯UIStoryboardSegue,但当它解开时,它似乎导致我UINavigationBar变黑,然后回到它的正确颜色.请参阅下面的GIF.
我的自定义segue只是让新的ViewController从顶部下来,然后返回到顶部.
这是UIStoryboardSegue代码:
import UIKit
class SlideDownSegue: UIStoryboardSegue {
var duration: Double = 0.5
override func perform() {
let screenHeight = UIScreen.main.bounds.size.height
let toVC = self.destination
let fromVC = self.source
toVC.view.transform = CGAffineTransform(translationX: 0, y: -screenHeight)
UIApplication.shared.keyWindow?.insertSubview(toVC.view, aboveSubview: fromVC.view)
UIView.animate(withDuration: duration, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
toVC.view.transform = CGAffineTransform.identity
}, completion: {
success in
fromVC.present(toVC, animated: false, completion: nil)
})
}
}
class UnwindSlideDownSegue: UIStoryboardSegue {
override func perform() {
let screenHeight = …Run Code Online (Sandbox Code Playgroud) ios ×7
uistoryboard ×3
ios5 ×2
ios6 ×2
objective-c ×2
segue ×2
asynchronous ×1
ios11 ×1
ipad ×1
iphone ×1
storyboard ×1
swift4 ×1
xcode ×1
xcode9 ×1