如何使用 UIPageViewController 加载单独的 XIB?

2024-01-06

我正在深入研究 UIPageViewControllers 的新世界,那里有很多教程,但是它们似乎都创建了一个视图,然后仅使用具有不同内容的新实例。

我真的很希望能够创建多个 XIB,然后将它们与 UIPageViewController 链接在一起,但它太新了,我无法理解它的工作方式。


好吧,这是一个很长的答案,您应该能够复制和粘贴。 (此代码改编自 Erica Sadun (https://github.com/erica/iOS-5-Cookbook))

首先,创建一个 UIPageViewController 类型的新类。称之为 BookController。现在将以下代码粘贴到您的 .h 文件中。

// Used for storing the most recent book page used
#define DEFAULTS_BOOKPAGE   @"BookControllerMostRecentPage"

@protocol BookControllerDelegate <NSObject>
- (id) viewControllerForPage: (int) pageNumber;
@optional
- (void) bookControllerDidTurnToPage: (NSNumber *) pageNumber;
@end

@interface BookController : UIPageViewController <UIPageViewControllerDelegate, UIPageViewControllerDataSource>
+ (id) bookWithDelegate: (id) theDelegate;
+ (id) rotatableViewController;
- (void) moveToPage: (uint) requestedPage;
- (int) currentPage;

@property (assign) id <BookControllerDelegate> bookDelegate;
@property (nonatomic, assign) uint pageNumber;

在你的 .m 文件中:

#define IS_IPHONE   ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
#define SAFE_ADD(_Array_, _Object_) {if (_Object_ && [_Array_ isKindOfClass:[NSMutableArray class]]) [pageControllers addObject:_Object_];}
#define SAFE_PERFORM_WITH_ARG(THE_OBJECT, THE_SELECTOR, THE_ARG) (([THE_OBJECT respondsToSelector:THE_SELECTOR]) ? [THE_OBJECT performSelector:THE_SELECTOR withObject:THE_ARG] : nil)


#pragma Utility Class - VC that Rotates
@interface RotatableVC : UIViewController 
@end
@implementation RotatableVC
- (void) loadView 
{
    [super loadView]; 
    self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    self.view.backgroundColor = [UIColor whiteColor];
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
{
    return YES;
}
@end


#pragma Book Controller
@implementation BookController
@synthesize bookDelegate, pageNumber;

#pragma mark Debug / Utility
- (int) currentPage
{
    int pageCheck = ((UIViewController *)[self.viewControllers objectAtIndex:0]).view.tag;
    return pageCheck;
}

#pragma mark Page Handling

// Update if you'd rather use some other decision style
- (BOOL) useSideBySide: (UIInterfaceOrientation) orientation
{
    BOOL isLandscape = UIInterfaceOrientationIsLandscape(orientation);
    return isLandscape;
}

// Store the new page and update the delegate
- (void) updatePageTo: (uint) newPageNumber
{   
    pageNumber = newPageNumber;

    [[NSUserDefaults standardUserDefaults] setInteger:pageNumber forKey:DEFAULTS_BOOKPAGE];
    [[NSUserDefaults standardUserDefaults] synchronize];

    SAFE_PERFORM_WITH_ARG(bookDelegate, @selector(bookControllerDidTurnToPage:), [NSNumber numberWithInt:pageNumber]);

}

// Request controller from delegate
- (UIViewController *) controllerAtPage: (int) aPageNumber
{
    if (bookDelegate && 
        [bookDelegate respondsToSelector:@selector(viewControllerForPage:)])
    {
        UIViewController *controller = [bookDelegate viewControllerForPage:aPageNumber];
        controller.view.tag = aPageNumber;
        return controller;
    }
    return nil;
}

// Update interface to the given page
- (void) fetchControllersForPage: (uint) requestedPage orientation: (UIInterfaceOrientation) orientation
{
    BOOL sideBySide = [self useSideBySide:orientation];
    int numberOfPagesNeeded = sideBySide ? 2 : 1;
    int currentCount = self.viewControllers.count;

    uint leftPage = requestedPage;
    if (sideBySide && (leftPage % 2)) leftPage--;

    // Only check against current page when count is appropriate
    if (currentCount && (currentCount == numberOfPagesNeeded))
    {
        if (pageNumber == requestedPage) return;
        if (pageNumber == leftPage) return;
    }

    // Decide the prevailing direction by checking the new page against the old
    UIPageViewControllerNavigationDirection direction = (requestedPage > pageNumber) ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse;
    [self updatePageTo:requestedPage];

    // Update the controllers
    NSMutableArray *pageControllers = [NSMutableArray array];
    SAFE_ADD(pageControllers, [self controllerAtPage:leftPage]);    
    if (sideBySide)
        SAFE_ADD(pageControllers, [self controllerAtPage:leftPage + 1]);

    [self setViewControllers:pageControllers direction: direction animated:YES completion:nil];
}

// Entry point for external move request
- (void) moveToPage: (uint) requestedPage
{
    [self fetchControllersForPage:requestedPage orientation:(UIInterfaceOrientation)[UIDevice currentDevice].orientation];
}

#pragma mark Data Source

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    [self updatePageTo:pageNumber + 1];
    return [self controllerAtPage:(viewController.view.tag + 1)];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    [self updatePageTo:pageNumber - 1];
    return [self controllerAtPage:(viewController.view.tag - 1)];
}

#pragma mark Delegate

- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
    NSUInteger indexOfCurrentViewController = 0;
    if (self.viewControllers.count)
        indexOfCurrentViewController = ((UIViewController *)[self.viewControllers objectAtIndex:0]).view.tag;
    [self fetchControllersForPage:indexOfCurrentViewController orientation:orientation];

    BOOL sideBySide = [self useSideBySide:orientation];
    self.doubleSided = sideBySide;

    UIPageViewControllerSpineLocation spineLocation = sideBySide ? UIPageViewControllerSpineLocationMid : UIPageViewControllerSpineLocationMin;
    return spineLocation;
}

-(void)dealloc{
    self.bookDelegate = nil;
}

#pragma mark Class utility routines
// Return a UIViewController that knows how to rotate
+ (id) rotatableViewController
{
    UIViewController *vc = [[RotatableVC alloc] init];
    return vc;
}

// Return a new book
+ (id) bookWithDelegate: (id) theDelegate
{
    BookController *bc = [[BookController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

    bc.dataSource = bc;
    bc.delegate = bc;
    bc.bookDelegate = theDelegate;

    return bc;
}

该类现在可用于控制您在任何项目中创建的任何书籍,以及单个项目中的多本书。对于每本书,使用 @interface 创建一个委托 UIPageViewController:

@interface NameOfBookController : UIPageViewController <BookControllerDelegate>

在此委托的 .m 文件中,包括:

// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
    [super loadView];
    CGRect appRect = [[UIScreen mainScreen] applicationFrame];
    self.view = [[UIView alloc] initWithFrame: appRect];
    self.view.backgroundColor = [UIColor whiteColor];
    self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

    // Establish the page view controller
    bookController = [BookController bookWithDelegate:self];
    bookController.view.frame = (CGRect){.size = appRect.size};
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    // Add the child controller, and set it to the first page
    [self.view addSubview:bookController.view];
    [self addChildViewController:bookController];
    [bookController didMoveToParentViewController:self];
}

然后加:

- (id) viewControllerForPage: (int) pageNumber
{    

    // Establish a new controller

    UIViewController *controller;


    switch (pageNumber) {
        case 0:
            view1 = [[FirstViewController alloc] init];
            view1.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
            controller = view1;
//rinse and repeat with each new view controller
            break;
        case 1:
            //etc.
            break;
        default:
            return nil;
            break;
    }
    return controller;
}

根据记录,此代码不是内存安全的。如果使用 ARC,请添加 @autoreleasePool{};如果没有,请不要忘记您的保留/释放周期。

我希望这有帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 UIPageViewController 加载单独的 XIB? 的相关文章

  • UIBezierPath containsPoint:无法正常工作?(更新:超级视图中的触摸位置如何处理?)

    所以我有 2 个视图可以绘制贝塞尔路径然后返回路径 然后我需要检查路径是否包含我在以下帮助下执行此操作的点 path containsPoint currentObject position 它适用于其中一种观点 但不适用于另一种观点 一个
  • iOS 初学者:带有 3 个按钮的 UIAlertView 窗口 > 检查按下了什么按钮

    我有一个教程中的工作代码 但不完全理解它 情况 在我的 iPhone 应用程序中按下按钮后 将出现一个包含三个按钮的 AlertView 现在我想检查用户按下了什么按钮 教程中的代码 IBAction infoButtonPressed i
  • Xcode 产品在发布模式下呈红色

    我想分发我的应用程序 我放置了代码签名和所有内容 我的最后一步是将构建设置为发布 我去编辑方案并将构建配置发布 然后我的产品由于某种原因变成了红色 我无法在 Finder 中打开它 因此无法发送它 如果我将其改回构建模式 它就不是红色的 我
  • 转发 UIAlertView 的可变参数

    我正在尝试设置一个非常简单的UIAlertView带有文本编辑 确定和取消按钮 我想根据文本编辑的内容禁用确定按钮 为了能够保留委托 以便他不会在警报视图之前消失 从而在用户对警报视图执行某些操作时立即导致崩溃 我对其进行了子类化 现在 我
  • Objective-C 相当于 Java 枚举或“静态最终”对象

    我试图找到一个与 Java 枚举类型或 public static final 对象等效的 Objective C 例如 public enum MyEnum private String str private int val FOO f
  • App Store Connect 上传错误“您尚未获得云管理分发证书的访问权限”

    使用 Xcode 将 iOS 应用程序上传到 App Store Connect 自动管理签名 并收到此错误 查找和生成签名资产时发生以下错误 与苹果通讯失败 您尚未获得云管理分发证书的访问权限 请联系您团队的帐户持有人或管理员以授予您访问
  • iPhone 应用程序中的 iOS 7 状态栏恢复为 iOS 6 默认样式?

    在 iOS 7 中UIStatusBar它的设计方式是与视图合并 如下所示 GUI designed by Tina Tav ar http dribbble com shots 1183911 Side menu and status b
  • 新的自动引用计数机制如何工作?

    有人可以简单地向我解释一下 ARC 的工作原理吗 我知道它与垃圾收集不同 但我只是想知道它到底是如何工作的 另外 如果 ARC 的作用与 GC 的作用相同且不影响性能 那么 Java 为什么要使用 GC 为什么它不使用 ARC 呢 每个接触
  • NSTextview:如何获取插入点的字形矩形?自定义文本视图?

    我似乎找不到任何有关如何获取插入点的矩形的文档 我试图在文本插入点 插入点正下方显示一个视图 如自动完成 我正在考虑制作一个自定义文本视图 但如果我可以避免它 那对我的情况来说将是理想的 谢谢 NSRect rectForActiveRan
  • 如何在 iOS 中以编程方式在 UITableViewCells 中添加图像

    我需要添加不同的图像UITableViewCells以编程方式 我怎样才能做到这一点 我正在尝试一些代码 但图像不显示在UITableViewCells 这是我下面的代码 void viewDidLoad arrImages NSMutab
  • 管理 iOS 中的布局

    我是新来的iOS开发方面 我对 JAVA Swing 和 Windows 应用程序有扎实的背景 我想学习如何进行布局iOS 我猜iOS没有 布局管理器 就像 Java Swing 中的那样 发展的唯一出路UI是否指定每个控制器的尺寸和位置
  • 具有自定义视图的相机

    我的应用程序使用相机 我想在相机预览上添加叠加层 例如 我想在使用相机时使用相框 还想添加一个用于相机操作的自定义栏 请帮助我做同样的事情 您可能正在尝试使用 UIImagePickerController 但我知道这个可以解决你的问题 您
  • 如何使用 UIScrollView?

    我该如何使用UIScrollView 请给我一个带有一张滚动图像的简单示例 这将使您深入了解UIScrollView控制 学习 UIScrollView 的基础知识 https stackoverflow com questions 159
  • 我应该在哪里保存想要长期保留的数据和文件,以及如何防止 iCloud 备份它们

    我有任意类型的文件 包括核心数据存储库 我需要保留这些文件 并且不要让 iOS 删除它们 通常 我不希望 iCloud 备份这些文件 我应该把它们保存在哪里 iOS5 0 及更早版本 5 0 1 和 5 1 及更高版本中保存文件的本地更改主
  • 使用 in 子句按数组顺序对 NSPredicate 进行排序

    我有一个NSPredicate会在一个内搜索 idNSArray的 ID 就像是 id in array 有没有办法获得按相同数组顺序排序的提取结果集 我现在的代码是 NSArray findIn NSArray identifiers i
  • initWithFrame 与 initWithStyle

    我想从已弃用的 TableView 中更新initWithFrame reuseIdentifier 我的表格视图使用自定义单元格 到处都说要使用initWithStyle 并且它不会以任何方式改变行为或细胞initWithFrame CG
  • Objective-c:如何检测视图上的双击?

    我正在开发一个应用程序 其中视图上有多个控件 但我想在用户双击视图时启用它们 您可以以双击为例 但在设备中我想在双击时捕获事件 您需要添加一个UITapGestureRecognizer到您想要点击的视图 像这样 void viewDidL
  • “UITableViewCell 附件复选标记”是图像吗?

    我需要定义一个自定义UITableViewCell哪里的UITableViewCellAccessoryCheckmark位于 a 的左侧UILabel 我应该将其定义为图像还是有更聪明的方法 非常感谢 卡洛斯 这只是一个关于苹果文档 ht
  • 不同形状的图像拼贴

    我对照片编辑应用程序开发完全陌生 我如何开发这样的网格样式 以便我可以添加从相机胶卷中选取的多个图像来创建拼贴画 我浏览了下面的链接 但没有找到实现这一目标的方法 任何建议或链接都 会有帮助 LINK1 https stackoverflo
  • 文本字段创建操作而不是出口

    我正在开发我的第一个应用程序 具有多个视图屏幕 并且在第一个视图上一切都运行良好 我添加了几个文本字段 并能够将它们作为插座连接到控制器 并从中获取值 管理它并吐出它回到标签 我尝试将第二个视图上的文本字段控制拖动到第二个控制器视图 当我这

随机推荐

  • listStatus 端点包括响应中的收件人状态

    有没有办法在 listStatus 端点的响应正文中包含收件人状态 这是我提出的卷曲请求 curl X PUT https na2 docusign net restapi v2 accounts XXXXX envelopes statu
  • Javascript 相当于 Java 的 UUID 类

    在java中 你可以做类似的事情 UUID id UUID fromString eb66c416 4739 465b 9af3 9dc33ed8eef9 long msb id getMostSignificantBits long ls
  • 把jdbc操作放在actor中好不好?

    我正在构建一个传统的 Web 应用程序 通过 JDBC 执行数据库 CRUD 操作 我想知道将 jdbc 操作放入当前请求处理线程之外的参与者中是否合适 我做了一些搜索 但没有找到演示此功能的教程或示例应用程序 那么有哪些缺点和优点呢 这种
  • 如何在 PHP 中重命名子数组键? [复制]

    这个问题在这里已经有答案了 当我对名为 tags 多维数组 的变量进行 var dump 时 我得到以下信息 Array 0 gt Array name gt tabbing url gt tabbing 1 gt Array name g
  • 如何让查询生成器将其原始 SQL 查询输出为字符串?

    给出以下代码 DB table users gt get 我想获取上面的数据库查询生成器将生成的原始 SQL 查询字符串 在这个例子中 它将是SELECT FROM users 我该怎么做呢 Answer recommended by PH
  • 以编程方式更改 Android EditText 的色调颜色

    我正在尝试改变一个的着色颜色EditText在运行时以编程方式查看 基本上我想改变你通常应用的内容 attr colorControlNormal就像在默认背景可绘制 https github com android platform fr
  • nth-child:如何选择两个一组的元素

    假设我有一个这样的表 div class fc slats table tbody tr td class fc widget content fc major 16 td td class fc widget content fc min
  • play 和 postgres 未找到关系错误(虽然表确实存在)

    我有一个名为 ETL TABLES 的表 它驻留在公共模式上 在 我的 application conf 我有以下行 hibernate default schema public 这应该意味着 postgres 的 search path
  • Android - 等待齐射响应以继续

    我构建了一个应用程序 它在地图中加载标记 我为 volley JSON 文件获取标记 但我需要首先加载 volley 然后继续执行代码 因为另一种方式显示错误纬度空 这个参数加载得不快 另一个方法先执行并显示 null 我的负载标记齐射代码
  • React/TypeScript:具体为组件输入 props.children

    假设我们有一个组件Foo呈现props children和另一个组件Bar 两个模块都导出一个 props 接口 有没有办法强制执行Foo的孩子可以是only类型的Bar 理想情况下 我们可以在构建时使用 TypeScript 来完成此任务
  • 在 CakePHP 3 中连接多个数据库

    我想将一些数据历史记录和日志存储在其他数据库表中 就未来的记录而言 这可能是非常大的数据库 还应该支持跨数据库 SQL 连接 所以请帮我解决这个问题 提前致谢 您可以按照以下步骤在同一个 cakephp 应用程序中使用多个数据源 在 Con
  • .NET 中的标准输入和输出

    如何从标准输入读取并写入标准输出 System Diagnostics Process StandardInput 的 MSDN 参考没有帮助 因为它单独启动进程 然后重定向标准输入 输出 但是如果该进程已经在运行并调用我的应用程序来为其提
  • 需要一个 CouchDB 技巧来按日期排序并按组过滤

    我有包含 日期 和 组 字段的文档 这是我的观点 byDateGroup map function doc if doc date doc group emit doc date doc group null 与此等效的查询是什么 sele
  • Java 中的独立 Socket.IO 服务器

    我正在寻找一个用 Java 编写的简单 Socket IO 服务器 我熟悉this one http code google com p socketio java 但它依赖于 servlet 而我没有在我的应用程序中使用它 我正在寻找类似
  • Spark python中基于条件过滤RDD并提取匹配数据

    我有这样的数据 cl id cn id cn value 10004 77173296 390 0 10004 77173299 376 0 10004 77173300 0 0 20005 77173296 0 0 20005 77173
  • 媒体源扩展 (MSE) 与 WebRTC 的比较

    媒体源扩展和 WebRTC 之间的根本区别是什么 我可以暂时表达一下我自己的理解吗 WebRTC 包含一个 RTCPeerConnection 它处理从媒体流获取流并将它们传递到协议以流式传输到应用程序的连接对等点 WebRTC 似乎在底层
  • 替换 pandas 数据框中很少出现的值

    我有一个中等大 约 60 000 行 x 15 列 的 csv 文件 我正在使用 pandas 处理它 每行代表一个人并包含个人数据 我想匿名呈现数据 我想要这样做的一种方法是替换特定列中罕见的值 我最初尝试这样做 def clean da
  • Selenium:如何等到光标发生变化?

    使用 CSS JS 可以更改用户看到的鼠标指针光标 例如 您可以设置cursor wait将光标更改为微调器 我想做的是进行 Selenium 测试 等待光标更改为 从wait 但是 我找不到任何 预期条件 EC 方法来观察光标的 CSS
  • Convert.DateTime 引发错误:字符串未被识别为“06-13-2012”的有效日期时间

    我正在将一个日期插入我的数据库 该值来自 s theDate Convert ToDateTime 06 13 2012 我收到错误 字符串未被识别为有效的日期时间 我该如何解决这个问题 尝试这个 DateTime ParseExact 0
  • 如何使用 UIPageViewController 加载单独的 XIB?

    我正在深入研究 UIPageViewControllers 的新世界 那里有很多教程 但是它们似乎都创建了一个视图 然后仅使用具有不同内容的新实例 我真的很希望能够创建多个 XIB 然后将它们与 UIPageViewController 链