我决定放弃我的 UIImageView,而是使用 UIPageViewController,以便用户可以在同一页面上的图像之间滑动。
我现在拥有的是一个普通的 UIViewController,因为我添加了一个 containerView,其中嵌入了一个 UIPageViewController。
因此 UIPageViewController 充当 View Controller 的 subview 。
我有一个“详细信息”页面,其中包含有关产品 X 的一些信息。我不希望只显示一张图片,而是希望图片“可滑动”,以便用户可以看到不同的图片。但我不希望 PageControllerView 充当全尺寸 View ,图像应该始终在 View Controller 内可见。
我现在的问题是我卡住了。我不知道如何连接两个 Controller 。因此,如果有人有使用 swift 的嵌入式 segues/ subview 的示例应用程序/教程,请分享。
由于下面的回答,我制定了一个解决方案:
在我的 Storyboard中,我有 3 个 VC。带有 UIPageControllerView 的嵌入式容器 View 的 VC1,然后我添加了第三个 VC“内容 View Controller ”来显示 UIPageControllerView 的图像。
ViewController.swift
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource {
var pageViewController: UIPageViewController!
var pageTitles: NSArray!
var pageImages: NSArray!
override func viewDidLoad()
{
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func restartAction(sender: AnyObject)
{
var startVC = self.viewControllerAtIndex(0) as ContentViewController
var viewControllers = NSArray(object: startVC)
self.pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil)
}
func viewControllerAtIndex(index: Int) -> ContentViewController
{
if ((self.pageTitles.count == 0) || (index >= self.pageTitles.count)) {
return ContentViewController()
}
var vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
vc.imageFile = self.pageImages[index] as! String
vc.titleText = self.pageTitles[index] as! String
vc.pageIndex = index
return vc
}
// MARK: - Page View Controller Data Source
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
{
var vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == 0 || index == NSNotFound)
{
return nil
}
index--
return self.viewControllerAtIndex(index)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
var vc = viewController as! ContentViewController
var index = vc.pageIndex as Int
if (index == NSNotFound)
{
return nil
}
index++
if (index == self.pageTitles.count)
{
return nil
}
return self.viewControllerAtIndex(index)
}
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
return self.pageTitles.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
return 0
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PageViewControllerFitta" {
self.pageTitles = NSArray(objects: "Explore", "Today Widget")
self.pageImages = NSArray(objects: "page1", "page2")
let toView = segue.destinationViewController as! UIPageViewController
toView.dataSource = self
var startVC = self.viewControllerAtIndex(0) as ContentViewController
var viewControllers = NSArray(object: startVC)
toView.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil)
toView.view.frame = CGRectMake(0, 30, self.view.frame.width, self.view.frame.size.height - 60)
self.addChildViewController(toView)
self.view.addSubview(toView.view)
toView.didMoveToParentViewController(self)
}
}
}
ContentViewController.Swift
import UIKit
class ContentViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
var pageIndex: Int!
var imageFile: String!
override func viewDidLoad()
{
super.viewDidLoad()
self.imageView.image = UIImage(named: self.imageFile)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
最佳答案
嵌入实际上是一种在实例化包含 Controller 后立即发生的转场,所以实现这一点的方法是在包含 Controller 上实现 prepareForSegue,并捕获对你的 Controller 的引用该方法中的子 Controller 。这是一个改编 self 目前正在从事的项目的示例,它可能无法编译,但应该可以让您了解如何继续 - 如果您需要更多信息,请告诉我。
为了让它工作,你必须给 segue 属性一个 identifier。假设您正在使用 Storyboard,这只是 segue 本身的一个属性(位于连接父 UIViewController 和子 UIViewController 的箭头上的小圆形过渡图标)。
class ViewController: UIViewController { // <-- this is the container
var myEmbeddedViewController: MyCustomUIViewController?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segue.identifier {
case .Some("the-identifier-i-used-for-the-segue"):
myEmbeddedViewController = segue.destinationViewController as? MyCustomUIViewController
default:
break
}
}
// ... other UIViewController stuff...
}
这是另一个涉及一些细节和文档的答案,尽管它是在 Objective-C 而不是 Swift 中提供的:iOS Nested View Controllers view inside UIViewController's view?
既然您已经引用了您的 UIPageControllerView,它需要一种方法来回答一些用于显示目的的问题:有多少页,我们打开到什么页,我要显示什么页当用户滑动到下一页和上一页时。它使用常见的 UIKit/Cocoa 习惯用法 dataSource(很多 View Controller 都有这个属性)来做到这一点。
在您链接到的示例代码中,viewDidLoad 方法包含行 self.pageViewController.dataSource = self。这是可行的,因为作者已经声明他的 ViewController 除了扩展 UIViewController 之外,还符合 UIPageViewControllerDataSource 协议(protocol)。然后他实现了所需的方法:
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController?
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
(dataSource 不必是您的 ViewController,您可以创建一个单独的类或结构。不过,对于简单的示例,它可能没问题。)
您面临的具体挑战是根据您应用的要求实现这些方法,以便嵌入式 UIPageViewController 可以根据您设置的 dataSource 确定要显示的内容.
假设您希望它显示一个仅包含图像和标签的 ProductImageViewController。从理论上讲,您可以为每个产品创建 Storyboard,但除非您拥有少量永不更改的产品,否则这不会真正奏效。更有可能的是,您希望根据您的产品列表在代码中创建新实例。
在示例代码中,作者只是设置了一个标签和图像的静态数组,然后 pageViewController 方法只是根据当前位置和滑动方向从数组中抓取适当的一个.您想要设置一个数据源来了解您的产品列表,您可能从一些动态来源(如 CoreData、CloudKit 或其他一些网络服务)获得该列表。
作为一个让您自己熟悉的简单实验,尝试修改该演示的变量 self.pageTitles 和 self.pageImages 并查看这如何改变嵌入式 Controller 的行为。尝试修改该代码,而不是使用两个数组,一个文本和一个图像文件名,而是使用一个包含您定义的结构或类的数组,它包含标签文本和文件名。一旦它起作用,改变它而不是硬编码标签/图像列表,你从你的产品目录加载它。那是什么在起作用,你已经完成了,发货:)
关于ios - Swift ios 不确定如何连接或使用嵌入式 UIPageViewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30849085/
我正在学习如何使用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等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t