zoukankan      html  css  js  c++  java
  • 简析MonoTouch工作原理

    MonoTouch使用静态编译方式将代码编译为ARM二进制代码。使用MonoTouch创建的每一个应用程序都是独立的,也就是说,应用程序所需要的东西都要打包,之所以这样,是因为iPhone不允许使用共享库。MonoTouch通过绑定方式向C#公开iPhone的原生库,因而不需要在语 言之间做转换。通过静态编译(Ahead-Of-Time,AOT)生成ARM二进制代码,MonoTouch应用程序就可满足发布应用程序到App Store的所有必需条件。

    注意 在写本书(《MonoTouch应用开发实践指南:使用C#和.NET开发iOS应用》)的时候,许多使用MonoTouch开发的应用程序已经发布到App Store。在网站monotouch.info里有这些应用程序的完整列表,并有大量相关资源的链接。现在还可以在http://monotouch.net/Apps查看应用程序的展示。

    然而,由于苹果政策和内核的限制,JIT编译的代码是不允许的。这就限制了.NET的某些领域(如CodeDOM、Reflection-Emit(尽管映 射可以使用)、虚拟泛型方法、非确定性泛型和动态语言运行库(Dynamic Language Runtime,DLR))的使用。在一般情况下,大多数非UI的C#代码都可以稍做修改或不做修改就能移植到MonoTouch中。

    对于刚才在MonoTouch中创建的应用程序,现在来看看它们在MonoDevelop中生成时都做了什么事情(例如在虚拟器生成一个发布版本)。

    设置配置为Release | iPhoneSimulator,然后生成解决方案。生成后,在Finder中浏览工程目录。

    提示 在MonoDevelop解决方案树中右击该工程,并选择Open Containing Folder就可在Finder中打开工程目录。

    在Finder的工程目录依次打开以下目录:bin→iPhoneSimulator→Release。在目录中,可以看到生成的应用程序包。如果生成的是 debug(调试)版本,就可在Debug目录中找到它,它在iPhone目录中而不是iPhoneSimulator目录中。在所有情况下,目标目录结 构就是编译应用时生成应用程序包的形式。有一个扩展名为.app的特殊文件夹,它的作用是使应用程序看起来像单一的文件,便于部署。对于当前的应用程序, 会看到文件的名字为LMT2-2.app。如果在Finder中右击该文件并选择Show Package Contents,将看到如下图所示的编译后的执行文件和应用程序所依赖的文件。

    应用程序包的内容

    各种DLL文件和EXE文件是剩余的元数据。此外,两个图片文件用前面的Build Action of Content,以及info.plist文件和MainWindow.nib标记。文件info.plist是一个属性列表文件,它是XML文件,包含 了应用程序不同元数据构成的字典。文件MainWindow.nib是MainWindow.xib文件的二进制版本。

    注意 在部署应用程序到App Store的时候,需要将.app文件压缩为zip文件和一些图片文件一起上传。

    在应用程序包中,最重要的文件是LMT2-2,这是由AOT编译的,包含项目中所有的依赖项,包含MonoTouch提供的用于应用程序内管理内存的工具, 是可在Unix上执行的文件。MonoTouch的内存管理与iPhone上的Objective-C不同,它是Mono垃圾收集器的一个分支版本,负责 应用程序代码中所有的内存管理工作。

    注意 MAC OS X中的Objective-C 2.0并没有垃圾收集器。此外,在模拟器上,MonoTouch使用JIT编译而不是AOT。

    回 头看看Objective-C版本的应用程序,会注意到dealloc方法会发送一个释放信息给imageView;而在MonoTouch版本中,则不 需要。其原因就是因为MonoTouch有垃圾收集器,而在iPhone的Objective-C中没有。它依赖于基于引用计数(retain count)的内存管理模型。如果熟悉的话,会发现这有点儿类似于COM,至少表面上是这样。但是,UIImageView并不是一个.NET的类,怎样 才能收集它呢?下面将讲述这问题。

    内存管理

    要了解 MonoTouch如何使用原生类管理内存,首先要了解Objective-C管理内存的知识。在Objective-C中,内存管理是通过引用计数来实 现的。每当创建对象时,就会向Objective-C发送一个alloc信息,然后返回对象(实际上是对象的指针,这里把引用作为对象)和它的引用计数。 每发送一个引用信息给对象,对象的引用计数就会加1;而每当一个释放信息发送给对象,引用计数就会减1,当对象的引用计数为0时,内存就会释放。

    注意 Objective-C的alloc和init版本的组合类似于C#中的构造函数。

    此外,在许多情况下,工厂方法(factory method)模式的类只返回一个对象。在这种情况下,如果分配内存后,工厂方法在内部释放对象,那么在调用者有机会使用它之前,该对象将销毁,这时,如 果工厂方法对这视而不见,并返回了该分配对象(包含引用计数),那么该对象将永远不会销毁。通过由NSAutoreleasePool类实现的自动释放池 (autorelease pool),可以解决这个问题。基本上,NSAutoreleasePool会延迟对象的销毁,这样调用者就能在它销毁前使用它。在iPhone的引用计 数世界中,对象会添加到自动释放池直到释放池自身发出一个遗漏(drain)信息(或释放信息)时,才会发送释放信息。只要释放池中的对象不明确地发送一 个保留信息,对象就会销毁。

    当任何带有引用计数为1的对象释放时,就会调用dealloc方法,这时就可以调用对象的释放方法来清理对象(即释放对象的指针)。

    基于以上信息,现在探讨MonoTouch如何与原生代码交互。对于Objective-C对象,MonoTouch在主线程创建一个自动释放池和线程池线 程。因此,每当线程使用Objective-C类时,MonoTouch开发人员就要创建一次自动释放池,例如,使用以下代码创建线程:

    void DoSomethingOnAnotherThread ()
    {
          Thread t = new Thread (DoSomething);
          t.Start ();
    }

    在“DoSomething”方法内要使用Objective-C对象(也就是说,从NSObject派生的任何类),都需要将代码包含在自动释放池内,如以下代码:

    void DoSomething()
    {
          using(var pool = new NSAutoreleasePool())
          {
               //code that touched Objective-C objects ...
          }
    }

    提示 如果在运行时出现“autoreleased with no pool in place—just leaking,”这样的警告,如之前所示那样将代码包含到NSAutoreleasePool中即可。

    除此之外,我们发现MonoTouch在内存管理方面做得相当出色。当然,.NET对象会通过MonoTouch GC自身进行管理。需要内存管理的其他地方,可能还需要采取更精细的内存控制,或者至少清楚NSObject基类的IDisposable实现。在 MonoTouch端,会发送释放信息到NSObject对象子类的实例(附带一些内部数据结构的清理),如果要销毁的是占用大量内存的对象,这非常有用,而且宜早不宜迟。对于NSAutoreleasePool,当释放信息发送到释放池时,会将释放信息发送到它内部所有的自动释放对象。

    -----------------------------

    本文节选自《MonoTouch应用开发实践指南:使用C#和.NET开发iOS应用》第2.3节“MonoTouch的工作原理”

    原书名:Learning MonoTouch: A Hands-On Guide to Building iOS Applications with C# and .NET

    作者:(美)Michael Bluestein   著

    译者:黄灯桥 黄浩宇 译

    本书系统讲解了利用MonoTouch开发iOS应用的技术和方法,并包含大量精心设计的案例,可操作性极强。它是有效指导有经验的.NET开发者利用已掌握的.NET技术快速开发iOS应用的参考书,为.NET开发者低成本地向iOS开发者过渡提供了捷径。

    阅读本书PDF样章,请访问:http://vdisk.weibo.com/s/j8IFO

    豆瓣收藏本书,请访问:http://book.douban.com/subject/20394299/


  • 相关阅读:
    P1030 求先序排列 P1305 新二叉树
    spfa
    Clairewd’s message ekmp
    Cyclic Nacklace hdu3746 kmp 最小循环节
    P1233 木棍加工 dp LIS
    P1052 过河 线性dp 路径压缩
    Best Reward 拓展kmp
    Period kmp
    Substrings kmp
    Count the string kmp
  • 原文地址:https://www.cnblogs.com/hzbook/p/2800012.html
Copyright © 2011-2022 走看看