这个版本加入了一个全新的功能 – 全文双语翻译.
通过这个小软件的编写, 我学到了很多Cocoa的东西. 我会在短时间内归纳整理并发上来.
下面是截图.
1. 查单词界面.

2. 汉-英 全文翻译.

3. 英-汉 全文翻译.

这个版本加入了一个全新的功能 – 全文双语翻译.
通过这个小软件的编写, 我学到了很多Cocoa的东西. 我会在短时间内归纳整理并发上来.
下面是截图.
1. 查单词界面.

2. 汉-英 全文翻译.

3. 英-汉 全文翻译.

这个版本主要增加了”编辑”菜单, 说实话, 这个功能是我漏了做的, 现在可以”复制/剪切/粘贴”了.
想起计算机, 相比下面这幅图片或者类似的样子就会出现在脑子里:

相比这个形象已经深入人心了, 从小时候第一次看到计算器开始, 我的思维就存在定式了, 总是认为计算器就应该是这个样子.
可是Soulver确实给我了很大的惊喜, 能把计算器做成这个样子确实是我从来没想过的.

老实告诉我, 你是否想过计算器可以做成这样? 这也是我喜欢苹果的原因之一, 我总能找到一些让我眼睛一亮的软件, 惊人的创意, 舒服的人性化, 漂亮的界面, 这就是苹果独有的魅力.
下面介绍下这个好东西的特色.
1. 实时更新计算结果.
2. 它让你可以使用简单英语来计算.

这是它的两大特色功能, 大家可能会想, 它是如何知道例如 “half, million, third, thousand” 等等词汇的数学意义的. 其实说穿了很简单, 这些都是预先定于好的常数.

你也可以自己定义一些这样的常数来让它支持更多属于你的数学名词.
除了以上这些特色的功能之外它还具有一般科学计算器拥有的全部功能, 大家一起来探索吧.
Trados是Windows下面翻译辅助工具的老大, 以前在翻译一些技术文档的时候都靠它了, 确实能够增加翻译的质量和速度.
转换到Mac下之后就曾经找了很久替代品, 很多人都推荐WordFast, 一个Microsoft Word的插件, 但是因为Microsoft Office 2004在Mac OSX Inter版本下面实在太慢了, 用了一段时间之后受不了它的速度而放弃了.
最后找到了OmegaT, 它的功能现在已经很强大了, 相较于Trados也只在支持文件格式和团队协作方面有所不足, 但是对于我这样的单独翻译工作已经足够了.

今天兴冲冲下载了iWork08结果发现它居然要求必须是 MacOSX 10.4.10 和 QuickTime 7.2才能安装.
可是我现在安装的是 MacOSX x86版本, 升级风险太大了(实际上昨天晚上我的系统崩溃就是因为试图升级…..), 怎么办呢?
感谢Mac下面的可执行文件格式, 我发现很简单就能绕过版本检查. 以下就是详细步骤:
1. 装载下载下来的磁盘映像.
2. 把iWork08Trail的安装文件复制到本地硬盘(这里需要注意的就是磁盘映像打开的时候看到的只是个快捷方式).
3. 在复制到本地的安装文件上面右键->显示包内容->Contents.
4. 用任意文本编辑器打开 iWorkTrial.dist.
5. 如下修改第61行(检测QuickTime版本)
6. 如下修改第67行(检测操作系统版本)
7. 保存.
搞定了, 我装上了之后没有发现任何问题.
懒得自己修改的朋友就直接下载这个修改好的文件替换安装包里的就好了.
Notification Queues
NSNotificationQueue(或者成为notification队列)代表了notification center的缓冲. NSNotificationQueue为Foundation Kit的通知机制贡献了两个重要的功能: 合并notification和异步发送.
在这篇文章中将提到:
Notification Queue 基础
异步发送notification
合并notification
Notification Queue 基础
使用 NSNotificationCenter的postNotification:方法和它的参数就能简单的发送一个notification到notification center. 当然, 这个方法是同步的, 也就是说在notification center完成发送和接受者处理完成之前是不会返回的. 而notificatoin队列则提供了另外一种发送策略, 大致上说, 它维护一个先进先出的notification队列. 当一个notification被发送到队列的前面的时候, 队列把它发送到notification center, 然后由notification center负责把这个notification发送给所有注册过的接收者.
每一个线程都默认拥有一个notification center, 而每个notification center则默认拥有一个notification队列. 你也可以创建自己的notification队列并把它加入到notification center中.
异步发送notification
使用 NSNotificationQueue 的 enqueueNotification:postingStyle: 和 enqueueNotification:postingStyle:coalesceMask:forModes: 方法就能通过将其加入队列来异步的发送一个notification到当前线程. 这些方法在把notification加入队列之后就立即返回.
注意: 当notification center所在线程在一个notification加入队列过程中退出的话这个notification将会发送失败. 查看”发送Notificaiton到特定线程”.
在notification基于enqueue方法的参数 posting style 和 run loop mode 被发送之后, 这个notification将被从notification队列中删除. The mode argument specifies the run loop mode in which the queue will be emptied. 例如, 当你选择了 NSNodalPanelRunLoopMode, 那么notification将在 run loop 处于这种模式的时候被发送. 如果 run loop 不是这个模式, 那么notification一直等待到再次进入这个模式的时候才会被发送. 查看 “输入模式” 得到更多关于 run loop mode 的信息.
posting style 包含三种不同的 style: NSPostASAP, NSPostWhenIdle 和 NSPostNow. 关于它们的详细信息会在下面的章节中提到.
尽快发送
所有选择了 NSPostASAP 的notification会在 run loop 完成当前运行周期之后被发送到notification center. (如果所选的 run loop mode 和当前的不同, 那么notification将在进入所选 run loop mode 的时候被发送. ) 因为 run loop 会在每个运行周期进行多次外部调用, 我们并不知道这些外部调用什么时候返回, 所以也就不能保证notifiation在此期间能够被发送. 其他的外部调用将会被优先执行, 比如一个timer或者发送其他异步notification.
一般来说 NSPostASAP 会用来发送昂贵的资源, 比如显示服务器. 当很多客户端在 run loop 中调用窗口缓存绘制的时候, 在每次绘制操作中把缓存中绘制好的内容发送到显示服务器是非常昂贵的. 在这中情况下, 每个绘制方法把一些标记为 NSPostASAP 的notification (比如 FlushTheServer) 加入队列. 结果是, 这些notification中只有一个会在当前 run loop 完成之后被发送, 确保窗口缓存中的数据只会被发送一次.
在空闲时发送
所有选择了 NSPostWhenIdle 的notification只在 run loop 处于空闲状态的时候发送. 处于这个状态的时候, run loop 没有任何需要处理的东西, 无论是timer还是其他异步事件. 一个 NSPostWhenIdle 的典型用例就是当用户输入一些文字的时候程序会在其他什么地方显示文字的长度. 在用户键入每个字符之后更新文字输入框是非常耗时的, 特别是用户输入的很快的时候. 所以面对这种情况的时候, 应用程序会在每个字符输入之后把相应的notification标记为 NSPostWhenIdle, 合并, 然后加入队列, 比如 ChangeTheDisplaySize. 当用户停止输入之后 run loop 会进入等待状态, 一个 ChangeTheDisplayedSize notification会被加入队列, 然后更新文字长度显示. 注意, 在 run loop 将要退出的时候 (通常发生在所有的输入都停止之后) 并不处在等待状态, 所以notification并不会被发送.
(未完待续)
Notifications
Notification包装了事件的信息, 比如窗口正在获取焦点或者网络连接正在断开. 需要订阅事件(例如, 一个文件想要知道正在编辑它的窗口将要被关闭)的object需要在notification center注册, 之后当事件发生的时候就会得到通知. 当事件发生的时候, 一个notification会被发送到notification center, 而后notification center马上就会把这个notification转发给所有订阅过这个事件的object. 当需要的时候, notification会被缓存在notification queue中….
Notification的原理
在两个object之间传递信息最标准的方法是传递消息 – 一个object调用另外一个object的方法. 但是, 传递的消息这种方法要求发送消息的object知道消息的接收者和它能接收的消息类型. 这将会把两个object紧密的绑定起来 – 最值得注意的是这会让两个本来独立的子系统耦合在一起. 为了解决这些问题, 广播模型被提了出来. Object只是负责发送notification, 而NSNotificationCenter将负责把这个notification转发给所有相关的object.
一个NSNotification(在这片文章里面简称notification)包含一个name, 一个object和一个可选的dictionary. Name是notification的标识. Object包含notification发送者想要发送的任意类型的object(一般来说就是发送这个notification的object本身). Dictionary用来保存其他相关的东西(如果有的话).
任意object都可以发送notification. 任意object都可以在notification center注册以便在某个事件发生的时候能够得到通知. Notification center负责把接受的notification发送给所有注册过的消息接收者. 发送notification的object, notification里面包含的object和接收这个notification的object可以是同一个object, 也可以是三个不同的object. 发送notification的object不需要知道关于接受者的任何信息. 但是, 接受者至少需要知道notification的name和其所包含dictionary的key(如果有的话).
Notification和Delegation
就使用上看, notification系统和delegate很像, 但是他们有以下不同:
*Notification的接受者可以是多个object. 但是delegate object只能有一个. 这就阻止了返回值.
*一个object可以从notification center接受它想要的任意数量个notification, 而delegate只能接受预先定义好的delegate方法.
*发送notification的object完全不知到接受者是否存在.
Notification Centers
Notification center负责接收和发送notification. 当它接受到notification的时候会通知所有符合特定条件的接受者. Notification信息被包装在NSNotification里. Notification接收者在notification center里面注册以获得其他object发出的notification. 当事件发生的时候, 一个object发送相关的notification到notification center. Notification center将消息分发给每一个注册过的接受者. 发送notification的object和接受者可能是同一个.
Cocoa包含两种notification center:
*NSNotificationCenter类管理单个进程内部的notification.
*NSDistributedNotificationCenter管理一台机器上跨进程的notification.
NSNotificationCenter
每一个进程都有一个默认的notification center, 你可以通过访问 NSNotificationCenter 的 +defaultCenter方法来得到它. 这种类型的notification center负责管理单个进程内部的notification. 如果需要管理同一台机器上不同进程之间的notification则需要用到NSDistributedNotificationCenter.
Notification center发送notification给接收者的方法是同步的. 也就是说, 当发送一个notification的时候, 除非所有的接收者都接到和处理了这个notification, 否则不会返回. 想要发送异步notification的话就需要用到notification queue了.
在一个多线程应用程序里, notification总是和发送者处于同一个线程里, 但是接受者可以在其他线程里.
NSDistributedNotificationCenter
每一个进程都有一个默认的distributed notification center, 你可以通过访问 NSDistributedNotificationCenter 的 +defaultCenter方法来得到它. 这种类型的notification center负责管理一台机器上多个进程之间的notification. 如果需要在多台机器间通讯的话, 使用distributed objects.
发送一个distributed notification是非常昂贵的. Notification首先会被发送到一个系统级别的服务器上, 然后在分别分发到每一个注册过的进程里. 从发从消息到消息被接受到之间的延迟理论上来说是无限的. 事实上, 如果太多的notification被发送到服务器上, 那么服务器上的notification队列可能会被撑满, 这就有可能会造成notification的丢失.
Distributed notification会在一个进程的主循环里被发送出去. 一个进程必须保证有一个主循环在其内部运行, 例如 NSDefaultRunLoopMode, 然后才能接受到distributed notification. 如果接收进程是多线程的, 那么notification并不一定会被主线程接受到. 一般来说notification会被分发到主线程的主循环, 但是其他线程一样可以接收到.
一般类型的notification center可以注册所有object的notification, 但是 distributed notification center只能注册字符串类型的notification. 因为发送者和接受者可能在不同进程里, notification里面包含的object不能保证指向同一个object. 所以, distributed notification center只能接受包含字符串类型的notification. Notification会基于字符串来匹配.
Singleton模式经常来做应用程序级别的共享资源控制, 应该说这个模式的使用频率非常高, 现在来看看在Objective-C里面的实现方法.
要实现一个Singleton Class, 至少需要做以下四个步骤:
1. 为Singleton Object实现一个静态实例, 初始化, 然后设置成nil.
2. 实现一个实例构造方法(通常命名为 sharedInstance 或者 sharedManager)检查上面声名的静态实例是否为nil, 如果是则新建并返回一个本类实例.
3. 重写 allocWithZone: 方法来保证当其他人直接使用 alloc 和 init 试图获得一个新实例的时候不会产生一个新的实例.
4. 适当的实现 copyWithZone:, release, retain, retainCount 和 autorelease.
下面是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | static MySingletonClass *sharedSingletonManager = nil; + (MySingletonClass*)sharedManager { @synchronized(self) { if (sharedSingletonManager == nil) { [[self alloc] init]; // assignment not done here } } return sharedSingletonManager; } + (id)allocWithZone:(NSZone *)zone { @synchronized(self) { if (sharedSingletonManager == nil) { sharedSingletonManager = [super allocWithZone:zone]; return sharedSingletonManager; // assignment and return on first allocation } } return nil; //on subsequent allocation attempts return nil } - (id)copyWithZone:(NSZone *)zone { return self; } - (id)retain { return self; } - (unsigned)retainCount { return UINT_MAX; //denotes an object that cannot be released } - (void)release { //do nothing } - (id)autorelease { return self; } |