Cocoa Touch 中的协调控制器设计模式

2024-01-05

我正在创建一个带有大量自定义视图的 iOS 应用程序,因此,使用默认的 Cocoa 视图不是一个选项。然后,我决定和协调/中介控制器设计模式(在 Apress - Pro Objective-C Design Patterns for iOS 中学习)。

从委托中,我创建一个 rootViewController 指向我的协调控制器中的视图:

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
coordinatingController = [C6CoordinatingController sharedInstance];
self.window.rootViewController = coordinatingController.activeVC;
[self.window makeKeyAndVisible];
return YES;

然后,在协调控制器中,我有单例创建方法:

+ (C6CoordinatingController *) sharedInstance{
if (sharedCoordinator == nil){
    C6Log(@"New Shared Coordinator");
    sharedCoordinator = [[super allocWithZone:NULL] init];
    [sharedCoordinator initialize];
}
else {
    C6Log(@"Return Singleton Shared Coordinator");
}
return sharedCoordinator;
}



+ (id) allocWithZone:(NSZone *)zone{
return [self sharedInstance];
}



- (void) initialize{
C6Log(@"");
[self checkDevice];

_mainVC = [C6MainViewController initWithDevice:device];
_activeVC = _mainVC;
[self checkLanguage];
[self chooseFirstView];
}

我还有一个选择器来选择第一个视图(我目前只有两个):

-(void) chooseFirstView{
// If a language was not setted, go to language settings view
if (!language) {
    C6Log(@"Going to Language Settings");
    C6LanguageSettingsViewController *languageVC = [C6LanguageSettingsViewController initWithDevice:device];
    [_mainVC.view addSubview:languageVC.view];
}
else {
    C6Log(@"Going to User Settings", language);
    C6AccountSettingsViewController *accountVC = [C6AccountSettingsViewController initWithDevice:device];
    [_mainVC.view addSubview:accountVC.view];
}
}

然后,我有一个 IBAction 供我的视图使用:

- (IBAction) requestViewChangeByObject:(id)object {
int buttonTag = [object tag]; // dividend
int viewTag = buttonTag / divisor; // quotient
int actionTag = buttonTag - (divisor * viewTag); // remainder
C6Log(@"viewTag: %d | actionTag %d", viewTag, actionTag);
switch (viewTag) {
    case LanguageTags:
        C6Log(@"LanguageTags");
        break;
    case AccountTags:
        C6Log(@"AccountTags");
        break;
    default:
        break;
}

在 NIB 中,我创建了一个对象(协调控制器),我可以从那里调用 IBAction。它工作得很好,我可以改变我的观点(它仍然需要实现)…………

但是……我也想更改语言,但是,因为这不是导航问题,所以我想从 C6LanguageSettingsViewController 而不是从 C6CoodinatingController 进行更改。

因此,我在 C6LanguageSettingsViewController 中创建了另一个 IBAction:

- (IBAction)chooseLang:(id)sender{
UIImage *bt;
[self resetImagesToNormalState];
C6Log(@""); 
C6Log(@"%@", [sender tag]);
C6Log(@"%@", sender);
.
.
.

当我将按钮连接到此 IBAction(通过文件所有者或通过 LanguageSettingsViewController 对象)时,应用程序会中断,有时它不会显示错误,有时会出现错误无法识别的选择器发送到实例 OR EXC_BAD_ACCESS(代码=1,地址=0x…………)在 UIApplicationMain.

我相信问题是 NIB 找不到文件的所有者......但我不知道如何解决它。


好吧……这似乎很荒谬,但我正在回答自己:P

我设法让它工作(终于!),我发现我正在以一种糟糕的方式管理视图控制器,所以,我改变了协调控制器中的一些代码:

首先,我没有一个带有 NIB 和其他东西的“真正的”mainViewController……

旧初始化

- (void) initialize{
    C6Log(@"");
    [self checkDevice];
    _mainVC = [C6MainViewController initWithDevice:device];
    _activeVC = _mainVC;
    [self checkLanguage];
    [self chooseFirstView];
}

新初始化

- (void) initialize{
    C6Log(@"");
    [self checkDevice];
    [self checkLanguage];
    [self chooseFirstView];
}

检查设备验证它是 iPhone 还是 iPad,这样我就可以选择正确的 NIB。

检查语言检查 [NSUserDefaults standardUserDefaults] 的语言

最后,我调用chooseFirstView:

老选择第一个查看

-(void) chooseFirstView{
    // If a language was not setted, go to language settings view
    if (!language) {
        C6Log(@"Going to Language Settings");
        C6LanguageSettingsViewController *languageVC = [C6LanguageSettingsViewController initWithDevice:device];
        [_mainVC.view addSubview:languageVC.view];
    }
    else {
        C6Log(@"Going to User Settings", language);
        C6AccountSettingsViewController *accountVC = [C6AccountSettingsViewController initWithDevice:device];
        [_mainVC.view addSubview:accountVC.view];
    }
}

新选择第一视图

-(void) chooseFirstView{
    // If a language was not setted, go to language settings view
    _activeVC = [[UIViewController alloc] init];
    UIImage *bgImage = [UIImage imageNamed:@"bg.png"];
    UIImageView *bgView = [[UIImageView alloc] initWithImage:bgImage];
    [_activeVC.view addSubview:bgView];

    if (!language) {
        C6Log(@"Going to Language Settings");
        languageVC = [C6LanguageSettingsViewController initWithDevice:device];
        [_activeVC.view addSubview:languageVC.view];
    }
    else {
        C6Log(@"Going to User Settings", language);
        accountVC = [C6AccountSettingsViewController initWithDevice:device];
        [_activeVC.view addSubview:accountVC.view];
    }
}

最大的变化是我何时以及如何启动 _activeVC…以及 _languageVC 和 _accountVC 现在都是全局变量这一事实。

好吧,在进行此更改之后,NIB 按钮将调用两个 IBAction 方法:它是文件的所有者和协调控制器。

使用这种模式的另一件大事是如何在不消耗 iOS 设备内存的情况下从一个视图更改为另一个视图……以下是我在协调控制器中执行此操作的方法:

- (IBAction) requestViewChangeByObject:(id)object {
    int buttonTag = [object tag]; // dividend
    int viewTag = buttonTag / divisor; // quotient
    int actionTag = buttonTag - (divisor * viewTag); // remainder
    C6Log(@"ViewTag: %d", viewTag);
    switch (viewTag) {
        case LanguageTags:{
            C6Log(@"LanguageTags - button %d", actionTag);
            accountVC = [C6AccountSettingsViewController initWithDevice:device];
            UIView *fromView = languageVC.view;
            UIView *toView = accountVC.view;
            [self switchFrom:fromView To:toView usingAnimation:AnimationPushFromRigh];
        }
            break;
        case AccountTags:{
            C6Log(@"AccountTags - button %d", actionTag);
            switch (actionTag) {
                case 0:{
                    C6Log(@"Go back");
                    languageVC = [C6LanguageSettingsViewController initWithDevice:device];
                    UIView *fromView = accountVC.view;
                    UIView *toView = languageVC.view;
                    [self switchFrom:fromView To:toView usingAnimation:AnimationPushFromLeft];
                }
                    break;

                default:
                    break;
            }
        }
            break;
        default:
            break;
    }
}

在该方法的开始,我做了很多数学运算……我“创建”了一个模式,其中每个 NIB 都应该有以 100 倍数开头的标签……所以,语言从 0 开始,帐户以 100 开头…………

#define divisor         100
#define LanguageTags    0
#define AccountTags     1

然后,我从一种视图更改为另一种视图的方式就在那里:

-(void) switchFrom:(UIView*) fromView To:(UIView*) toView usingAnimation:(int) animation{
    C6Log(@"");
    /*************** SET ALL DEFAULT TRANSITION SETTINGS ***************/
    // Get the current view frame, width and height
    CGRect pageFrame = fromView.frame;
    CGFloat pageWidth = pageFrame.size.width;
    // Create the animation
    [UIView beginAnimations:nil context:nil];
    // Create the delegate, so the "fromView" is removed after the transition
    [UIView setAnimationDelegate: fromView];
    [UIView setAnimationDidStopSelector:@selector(removeFromSuperview)];
    // Set the transition duration
    [UIView setAnimationDuration: 0.4];

    // Add the "toView" as subview of "fromView" superview
    [fromView.superview addSubview:toView];

    switch (animation) {
        case AnimationPushFromRigh:{
            // Position the "toView" to the right corner of the page            
            toView.frame = CGRectOffset(pageFrame, pageWidth,0);
            // Animate the "fromView" to the left corner of the page
            fromView.frame = CGRectOffset(pageFrame, -pageWidth,0);
            // Animate the "toView" to the center of the page
            toView.frame = pageFrame;
            // Animate the "fromView" alpha
            fromView.alpha = 0;
            // Set and animate the "toView" alpha
            toView.alpha = 0;
            toView.alpha = 1;

            // Commit the animation
            [UIView commitAnimations];
        }
            break;
        case AnimationPushFromLeft:{
            // Position the "toView" to the left corner of the page         
            toView.frame = CGRectOffset(pageFrame, -pageWidth,0);
            // Animate the "fromView" to the right corner of the page
            fromView.frame = CGRectOffset(pageFrame, pageWidth,0);
            // Animate the "toView" to the center of the page
            toView.frame = pageFrame;
            // Animate the "fromView" alpha
            fromView.alpha = 0;
            // Set and animate the "toView" alpha
            toView.alpha = 0;
            toView.alpha = 1;

            // Commit the animation
            [UIView commitAnimations];
        }
            break;
        default:
            break;
    }
}

我真的希望这对尝试使用这种协调控制器模式的人有所帮助:P

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

Cocoa Touch 中的协调控制器设计模式 的相关文章

  • 将 UIToolBar 添加到所有键盘(swift)

    我正在尝试以尽可能少的重复次数将自定义 UIToolBar 添加到我的所有键盘中 我目前的做法要求我将代码添加到所有 viewDidLoads 中 并将每个文本字段的委托分配给我正在使用的 viewController 我尝试创建自己的 U
  • 如何动态获取 UITableViewCell 的高度

    我创建了自定义的tableViewCell 我在UITableViewCell中添加了UIView SubView 所以我在 UIView 中的所有动态文本和图像内容都会根据文本和图像大小而变化 但现在 HeightforRowAtInde
  • 无法在 ios 应用程序中通过 googlecast 正确投射视频

    我正在开发一个基于 AVPlayer 的自定义视频播放器项目 尝试整合谷歌演员 我已经根据谷歌图进行了集成 https codelabs developers google com codelabs cast videos ios http
  • Flutter 应用程序在 iOS 平台的 firebase 电话身份验证中崩溃

    我在我的项目中实现了 Firebase Phone auth 在 Android 端 一切正常 但对于 iOS 端 当我尝试从我的端发送验证码时 应用程序崩溃并失去连接 我已在下面提交了我的代码 主程序 dart class MyApp e
  • 访客模式如何不违反开放/封闭原则?

    来自维基百科 这个想法是 一旦完成 类的实现只能修改为 纠正错误 新的或更改的功能将需要创建不同的类 该类可以通过继承重用原始类的代码 据我了解 访问者模式是一种强大的技术 可以通过使用双重分派来遍历实现相同接口的相似但不同的对象 在我的一
  • 在 iOS 7 中 viewForHeaderInSection 部分是从 1 开始而不是从 0 开始

    我正在处理UITableView在我的项目中 这个项目是在 Xcode 4 5 中创建的 现在我正在使用 Xcode 5 所以我的问题是何时在 iOS 6 中运行我的项目 viewForHeaderInSection方法部分从 0 开始没问
  • 使用数组中的字符串淡入/淡出标签

    func setOverlayTitle self overlayLogo text Welcome var hello String Bon Jour GUTEN nMORGEN BONJOUR HOLA BUENOS D AS BUON
  • 如何删除 UITableView 中的缩进?

    首先 我对此很陌生 我很可能忘记了一些非常简单的事情 问题 我正在制作一个应用程序 在 a 中显示来自 imgur com 的随机图像tableView 由于某种原因 所有单元格都会缩进少量 如下图所示 我摆弄了许多设置storyboard
  • 使用 UITabBarController 时覆盖整个屏幕的视图?

    我想在 UITabBarController 设置中在整个屏幕上覆盖 HUD 样式的透明图形 执行此操作的按钮位于第一个选项卡的屏幕 FirstViewController 中 并且覆盖层也应该覆盖选项卡 这可能吗 您可以将新视图直接附加到
  • 在 Objective-C 中的 Swift 类上调用 NSStringFromClass 返回模块损坏的名称

    我知道这个问题 https stackoverflow com questions 24107658 get a user readable version of the class name in swift in objc nsstri
  • 无法将项目添加到 NSMutableArray ivar

    我的目标是将字符串添加到数组中 并在我调用的方法中执行此操作 在这个方法中 我在数组中得到一个空值 但不知道为什么 我在课程开始时有这样的内容 NSMutableArray listOfEvents 以及我在每个事件上调用的方法 void
  • UICollectionView setLayout:animated: 不保留 zIndex

    我注意到打电话时setLayout animated in a UICollectionView要在两个布局之间切换 当前可见的单元格不遵循zIndex它的布局属性已设置在layoutAttributesForItemAtIndexPath
  • Mac 上的 Delphi - 可能吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我负责一个 Delphi Win32 项目管理应用程序 我刚刚完成了向 Delphi 2009 的迁移
  • Glib 在 iPhone 应用程序中的使用

    我想基于现有的开源 Objective C 框架开发一个 iPhone 应用程序 但是该框架广泛使用了 glib 库 我找不到一种方法来构建和包含 iPhone 应用程序的 glib 库 非越狱 有什么办法可以做到这一点 或者有没有推荐的方
  • 使用日期 Swift 3 对字典数组进行排序

    我有一个名为 myArray 的数组 其中添加了字典 我希望该字典按时间排序 这是字典中的键 那个时间是在 String 中 时间的日期格式为 yyyy MM dd HH mm ss 我尝试使用下面的代码解决方案 但给出了 从 字符串转换
  • 上传存档错误:“缺少 iOS 发行版签名身份......”

    我正在尝试使用 Xcode 将我的 iOS 应用程序存档上传到 iTunes Connect 但是当我单击 上传到 App Store 时 出现错误 Xcode 尝试查找或生成匹配的签名资产并 由于以下问题未能做到这一点 缺少 iOS 为
  • Unwind segue 的用途是什么以及如何使用它们?

    iOS 6 和 Xcode 4 5 有一个称为 Unwind Segue 的新功能 展开转场可以允许过渡到故事板中场景的现有实例 除了 Xcode 4 5 发行说明中的 这个简短条目之外 UIViewController 现在似乎还有几个新
  • Fitbit oauth2 公共 API 停止工作。给出错误 - 抱歉,这不是你..是我们

    几个月前 我准备了一个关于 Fitbit oauth2 公共 API 的演示 其中我使用特定用户登录并获取他的活动 一切正常 但最近 我打开演示并尝试使用同一用户登录 但它没有登录并反复出现此错误 我尝试更改在 Fitbit 上注册的演示应
  • 如何在 UITableView 的 switch 语句中创建变量?

    我正在构建一个包含三个部分的 tableView 我已经完成了前两个工作 但最后一个有点阻力 我的问题似乎涉及尝试在 switch 语句中声明变量 实际上是嵌套的 switch 语句 据我所知 这不是一个好主意 但在这种情况下 这似乎是唯一
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • CakePHP:向表单添加字段(动态)

    我正在尝试动态地将字段添加到我的 CakePHP 表单中 但似乎我使用的每种方法都有其自己无法修复的缺点 这是我尝试过的 不要添加新的输入 只需用逗号分隔单个输入中的值即可 这看起来很简单 但在尝试分解输入并将每个值保存在数据库中的新行中时
  • 为 C# 生成 XML 文档的 XSD? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道某处是否有 XSD 文件可用于验证使用 doc 选项编译 C 项目时生成的 XML 文档 我想
  • 如何为依赖动态数据的函数编写单元测试?

    假设您有一个网站 它使用一个函数从数据库检索数据并返回要显示 解析 等的结果 由于从数据库检索的数据是动态的 并且可能每天都在变化 因此如何正确地为此函数编写单元测试 假设该函数应该返回一个结果数组 显然 单元测试可以测试是否返回数组 但是
  • 如何设置 Windows 符号服务器

    我在网络上有一个备用服务器 我想用它来托管我们所有的构建符号 我已经知道如何在本地开发系统上设置符号缓存并将调试器 例如 Windbg 指向 符号文件路径 中的该路径 我认为我可以对网络上具有自己的符号缓存 例如 host symbols
  • 错误:Firestore 已初始化。您只能调用 settings() 一次,并且只能在调用 Firestore 对象上的任何其他方法之前

    因此 我正在为 firebase 规则编写测试 以便我可以为我在 stackoverflow 上编写的另一个问题创建可重现的代码 但我收到此错误 mocha test2 js Our social app 1 Can read a sing
  • VBA从Word表格复制到Excel

    我正在尝试从 Word 文件中的特定表单元格生成一个包含 5 列的 Excel 文件 从 Word 表复制到 Excel 我的Word文件有280个表格 我对要从 Word 文件复制的单元格进行寻址没有问题 但我不知道为什么结果是一个空白的
  • 通过 iPhone Web 应用程序访问相机

    据我了解 不太可能通过 HTML 访问网络摄像头 那么在 iPhone 上呢 是否可以 从 iOS6 开始 您可以使用以下命令访问相机和照片
  • 如何为Python 3子进程分配CPU亲和力?

    我在 Python 方面还是个新手 我在 Windows 7 和 Windows 10 上运行 Tkinter GUI 我有一个子进程以 1 KHz 运行数据记录器例程 我想为子进程设置 cpu 亲和力 我正在使用 Python 3 8 进
  • 使用 Media * API 进行录制时,支持的媒体类型的完整列表在哪里?

    我正在尝试学习如何在浏览器中记录媒体 我可能会让事情变得过于复杂 有大量直接的例子 但当录音被推到一个高度时 我陷入了困境 Blob具有任意选择的媒体类型的对象 而不检查该格式是否受支持 因此 我认为有一个清单 或者人们只是继续以过去的经验
  • C++ 模板的性能? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在anaconda上安装cx_freeze时出现包冲突

    我正在尝试使用 anaconda 提示符安装 cx freeze 按照他们网站上的内容 我使用了 conda install c pyzo cx freeze 我收到此错误 UnsatisfiableError The following
  • 熊猫数据框条件更改

    我正在处理 csv 时间序列数据 它显示每个时间范围内的步数 一旦步数超过 65535 它将从 0 开始计数 等等 但是 由于并非所有数据集都有 65535 计数 有些从 65530 开始 然后是 5 如果他们在时间范围内走了几个步骤 我不
  • 将 MATLAB 轴移动半步

    我正在尝试定位 MATLAB 的刻度以与我的网格对齐 但我找不到偏移标签的好方法 另外 如果我跑set gca XTickLabel 1 10 我的 x 刻度标签最终的范围为 1 到 5 这给出了什么 您需要移动刻度 但先获取标签并在移动后
  • 如何检测 iframe 大小调整?

    我有一个页面 其功能可以将此页面中的 iframe 高度调整为 iframe 内容的高度 但是当 iframe 具有切换操作时 高度会发生变化 并且该函数不会检测 iframe 的大小调整 有没有办法检测我的 iframe 内容是否发生变化
  • 为什么缓存控制:最大年龄不起作用?

    我正在倾斜http标头 并且我想在 缓存控制 字段上运行测试 所以我构建了一个只有默认页面的asp net网站 在这个页面中 我正在测试 缓存控制 字段 其 Page Load 中的代码如下 Response AddHeader Cache
  • 跨平台.Net? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如果您要编写一个在本地运行并调用 Web 服务的 GUI 应用程序 以实现跨平台 您可以使用 Net 来完成吗 您会推荐哪些工具 我正在考
  • 从 Backbone.js 模型中删除属性

    有没有办法从 a 中删除属性Backbone http documentcloud github com backbone model 原因是我在保存时传递了额外的数据来执行某些操作 但随后该数据会自动添加到我的模型中 文档说不要直接编辑
  • 为什么某些 SQLite 方法需要 Object[] 形式的参数,而其他方法则需要 String[] 形式?

    我对它的设计很好奇Android SQLite API http developer android com reference android database sqlite SQLiteDatabase html 例如 我们有 publ
  • 是时候通过 9600 波特串行发送 32KB 了?

    我想知道我的数学是否正确 如果我的波特率为 9600 那么这意味着每秒发送 9600 位 对吧 如果是这样 那么 9600 bit sec lt gt 1000 ms 9600 bit 0 1042 ms bit 因此 发送 32KB 应该
  • Cocoa Touch 中的协调控制器设计模式

    我正在创建一个带有大量自定义视图的 iOS 应用程序 因此 使用默认的 Cocoa 视图不是一个选项 然后 我决定和协调 中介控制器设计模式 在 Apress Pro Objective C Design Patterns for iOS