Cocoa学习

我的Cocoa/Cocoa Touch学习笔记

在Sandbox的程序中加入Growl支持

Growl是一个知名的第三方消息提示框架,几乎是Mac装机必备的软件。虽然从Growl 1.3开始,Growl变成了收费软件,但是它依然是Mac App Store收费榜名列前茅的软件。虽然从OS X 10.8 Mountain Lion开始,OS X将加入Notification Center的支持,但是现在距离OS X 10.8发布依然有一段时间,而且,OS X 10.8之前的Mac OS X要退出历史舞台还有很长的路。

我曾经撰写过关于Growl的文章,因此关于Growl.framework的基本使用的内容我在本文中不再赘述了,大家可以去回顾一下。基本上就是:

  • 下载Growl SDK
  • 解压,添加Framework目录下的Growl.framework到项目中;
  • 添加一个plist文件,名为:Growl Registration Ticket.growlRegDict,添加合适的值(不详述);
  • 增加一个Copy Build Phase,设置为Framework,把Growl.framework加入进去;
  • 在代码中实现GrowlApplicationBridgeDelegate的方法;
  • 发布Growl Notification。

在iOS 4中自定义BarButtonItem

在iOS 5中已经有了自定义UIBarButtonItem背景的API。但是在iOS 4中,自定义BarButtonItem背景就复杂很多了。其中最典型也最容易实现的一种是方法是试用UIBarButtonItem-initWithCustomView:方法,传递一个自定义UIButton对象进去。

在深入讨论自定义UIBarButtonItem,让我们来先解决自定义UIButton的一个问题:那就是Button的标题的长度是变化的,我们应该通过什么方法让背景图片适应标题长度的变化呢?

下面是解决方案:

再谈iOS 4下NavigationBar的自定义

iOS 5已经有了很方便的自定义UINavigationBar的方法,但是iOS 4现在还远未完全被iOS 5取代,因此,在做程序开发的时候必须要考虑对iOS 4的兼容。因此,要自定义UINavigationBar还不能简单的直接用iOS 5中才有的自定义API。

关于这个话题,我曾经写过一篇日志,但是后来发现那篇日志里面的实现方法有诸多缺陷。因此我后来对那篇文章做过部分删改。这两天,我再次研究了一下NavigationBar的自定义,总算找到了一个近乎完美的解决方法,因此,我决定写出来和大家分享一下。

本文中的实现方法很大程度上参考了这篇文章,不过我这里介绍的实现方法在原方法的基础上加入了对设备旋转的支持。

方法的核心思想是创建一个UINavigationBar的子类,让这个子类支持背景图,然后在项目中用自定义类替换UINavigationControllernavgationBar。不过有一个问题是,UINavigationControllernavgationBar属性是一个只读属性,因此我们只能在xib中将navgationBar的类改成我们的自定义类。

我还没有找到适合StoryBoard的无xib的解决方法,因此我在上面说这个方法是“近乎完美”。不过既然是部署到iOS 4,那项目不采用StoryBoard也不算特别反人类。好了,下面开始代码说话(注:代码用了ARC):

Twitter for Mac风格的Sheet定位

昨天在用Twitter的时候,突然意识到,在删除Twitter消息的时候弹出的Sheet是定位在要删除的那条消息的顶部,而不是窗口标题栏的下方。

我很好奇这是如何做到的。今天抽了点时间,在简单的查阅文档之后,我找到了答案。其核心就是NSWindowDelegate的一个方法:-window:willPositionSheet:usingRect:,可以指定Sheet的显示位置。

我做了一个简单的View-based Table View(Lion下),然后用下面的方法做了实现:

点击按钮复制粘贴到文本框

相信很多读者看到标题肯定会疑惑,文本框本来就支持复制粘贴,为什么要专门写一篇日志来介绍文本框的复制粘贴呢?其实,本文要讲述的是,如何通过按下按钮,来复制粘贴文本到文本框 – 不是通过菜单操作,也不是通过快捷键cmd-c和cmd-v来完成。

提到复制粘贴的菜单操作和快捷键操作,看过“Cocoa Programming for Mac OS X”的读者肯定知道,他们属于“nil-targeted action”,也就是说,他们的receive是在运行时被指定的。在Interface Builder中,-copy:-paste:方法都是连接到一个占位对象“First Responder”上的。而First Responder到底是谁是在程序运行过程中动态变化着的。

事实上,在NSTextField这个例子中,-copy:-paste:的Receive是一个NSText对象。知道了这一点,剩下的问题就是如何获取这个对象。