【问题标题】:How to port a Cocoa app to iPhone-OS?如何将 Cocoa 应用程序移植到 iPhone-OS?
【发布时间】:2010-01-28 00:41:29
【问题描述】:

我即将创建一个 Cocoa 应用程序,我想确保有一天我可以轻松地将它移植到 iPad 甚至 iPhone。我该如何提前计划?

我知道我将不得不重做所有 NIB,并且可能会设计一个不同的工作流程。

但是代码呢?只是用 UIsomething 替换每个 NSsomething 不会削减它,对吧?关于如何确保我以后不会在自己的脚上开枪的任何提示?

谢谢!

(iPad-SDK 在 NDA 下。为了这个问题,假设我问的是 iPhone,好吗?或者认为 iPhone 的屏幕更大。)

【问题讨论】:

    标签: iphone cocoa macos ipad


    【解决方案1】:

    确保您在应用中严格遵守Model-View-Controller 分隔。尤其是模型,不应依赖于任何控制器或视图。

    在移植到 iPhone/iPod touch/iPad 时,您需要更换大部分或所有控制器以及所有 NSView 和 NSCell。如果有的话,您应该能够保留您的 CALayer 子类。您可以通过条件编译重用一个或两个控制器,如果大多数控制器都适用于两者但某些部分仅适用于 Mac 或适用于两者但使用完全不同的 API。而且您应该能够保持整个模型不变。

    iPhone 开发人员可能会警告您一些更具体的陷阱,但这是适用于从一种环境到另一种环境的任何过渡的一般规则。 (另一种环境转换的示例是为您的应用制作一个或多个命令行工具等效项或补充项,例如 xcodebuild、packagemaker 或 ibtool。)

    此外,请查看 the Introduction to the Foundation framework reference 了解哪些 Foundation 类仅适用于 Mac 和 iPhone。

    【讨论】:

      【解决方案2】:

      与桌面 Cocoa 库相比,Cocoa Touch 甚至不支持很多库。您需要考虑 AppKit 与 UIKit 的差异。此外,Objective-C 不允许在 iPhone 上进行垃圾收集。有许多触摸事件只存在于 iPhone 上,而不存在于桌面上。由于手机是与非常个人数据相关的非常个人化的设备,因此 iPhone 开发的限制要大得多。

      查看这些幻灯片以获得更好的比较:http://www.slideshare.net/lukhnos/between-cocoa-and-cocoa-touch-a-comparative-introduction

      【讨论】:

        【解决方案3】:

        与任何好的项目布局一样,您应该将 UI 与非 UI 组件分开。这不仅仅意味着磁盘布局(尽管这也很有意义),而是使用 MVC 方法,您的控制器 (C) 知道模型 (M) 和 UI (V) 分别呈现。

        您可以使用 Key-Value Observing(又名 KVO)来设置模型,这样当它们触发时,它会向所有已注册的侦听器发送通知以进行更新。如果您使用 XIB 生成用户界面,那么当您将对象绑定到显示小部件时会发生这种情况。

        因此,您最终可以为您的 iPhone、Mac OS 和(后来的)iPad 使用单独的 XIB - 但如果您正确调整大小,您可以为 iPhone 和 iPad 使用相同的 XIB。

        最后,在某些情况下,您通常需要将逻辑注入模型(例如,添加图像以从方法返回)。在这种情况下,iPhone 和 Mac OS 具有不同的 Image 类。为此,您可以创建以下内容:

        MyModel.m         // contains the data, no UI
        MyModel+UIImage.m // contains a category for adding the UIImage
        MyModel+NSImage.m // contains a category for adding the NSImage
        

        类别如下所示:

        @interface Host(UIImage)
        -(UIImage *)badge;
        @end
        
        @implementation MyModel(UIImage)
        -(UIImage *)badge 
        {
            if (green)
                return [UIImage imageNamed:@"green.png"];
            if (red)
                return [UIImage imageNamed:@"red.png"];
        }
        @end
        ---
        @interface Host(NSImage)
        -(NSImage *)badge;
        @end
        
        @implementation MyModel(NSImage)
        
        -(NSImage *)badge 
        {
            if (green)
                return [[NSImage alloc] initWithContentsOfFile: @"green.png"];
            if (red)
                return [[NSImage alloc] initWithContentsOfFile: @"red.png"];
        }
        @end
        

        这具有额外的优势,您的单元测试可以只加载模型(不加载任何图像类别),而在运行时您需要处理图像的代码(例如,在视图控制器中)可以加载模型-category 并以透明的方式使用[model badge] 加载徽章,无论它是为哪个平台编译的。

        【讨论】:

        • 我勾选了这个答案,但其他所有答案也都很好。谢谢大家!
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-04
        • 1970-01-01
        • 2011-06-03
        • 1970-01-01
        相关资源
        最近更新 更多