分类存档: Develop - 第8页

爱糗事上线啦

漫长的 In Review 终于过了,爱糗事终于上线了。

爱糗事是一个糗事百科的 iOS 客户端,支持 iPhone 以及 iPad,详细介绍及截图请看这里

通过 iTunes 下载

Snow Leopard Server 上配置 Gitosis 笔记

为了迁移项目 Git 仓库到 Mini Server 上,需要在 Snow Leopard Server 上配置一下 Gitosis,但是 Mac OS X 和 Linux 不太一样,有些地方需要特殊处理一下。

安装 Gitosis

Gitosis 的安装就不多说,在参考文档2中有。

添加 Git 用户组及用户

添加用户可以用参考文档1中的方法来创建,没有尝试直接用 OSX 的用户管理来创建是否可用。

# 这里的用户组和用户ID 用 401,但是实际用时需要根据服务器上的情况来创建
# 我在使用时 401 这个 gid 就已经被占用了,可以使用以下两个命令看看要用的
# ID 是否已经被用了。
sudo dscl . list /Users uid
sudo dscl . list 


阅读全文 »

[Cocoa学习]格式化日期和解析日期字符串

在应用程序中,显示消息的时候一般都需要附带一个消息接收的时间,使用 NSDate 和 NSDateFormatter 即可完成格式化输出日期的任务,但是在使用时会比较麻烦,通过 Category 的方式来给 NSDate 类直接添加两个类方法来做这些事情会比较好,在以后需要格式化字符串时不需要每次都去创建一个 NSDateFormatter 对象。

对于解析日期时间也是同理。

@interface NSDate (FormatString)

- (NSString*)stringWithFormat:(NSString*)fmt;
+ (NSDate*)dateFromString:(NSString*)str withFormat:(NSString*)fmt;

@end

@implementation NSDate (FormatString)

- (NSString*)stringWithFormat:(NSString*)fmt {
    static NSDateFormatter *fmtter;
    
    if (fmtter == nil) {
        fmtter = [[NSDateFormatter alloc] init];
    }
    
    if (fmt == nil || [fmt isEqualToString:@""]) {
        fmt 


阅读全文 »

[Cocoa学习] 限制 NSTextField 中输入文本的长度

需求

NSTextField 作为一个常用的输入控件,有些在使用时需要去限制其中可以输入文本的长度,而 NSTextField 本身并没有提供这个功能,这就需要我们自己去想办法来实现了。

方法

在网上找了一下,发现可以通过继承 NSFormatter 实现一个子类来实现这个功能,参考了一下找到的代码[1],再将主要的 isPartialStringValid 方法根据自己的需要改了一下。


- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
       proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
              originalString:(NSString *)origString
       originalSelectedRange:(NSRange)origSelRange
            errorDescription:(NSString **)error 
{
    int size = [*partialStringPtr length];
    if ( size maxLength ) {
        if (origSelRange.location == [origString length]) {
            // 如果修改的位置在原来字符串的最后,则不做修改,只是拒绝内容修改
        } else {
            // 如果修改的位置在原来字符串的中间,就根据剩余的可用的长度把新增加的字符串进行截取
            int preLen = 


阅读全文 »

在 REALbasic 中注册 AppleEvent

之前为了注册一个自定义协议,需要通过注册 AppleEvent 来实现,在 Objective-C 中,可以很方便的使用 NSAppleEventManager 来注册 AppleEvent 句柄,但是在 REALbaisc 中,是没有办法直接去调用 NSAppleEventManager 的,所以需要通过声明然后调用 C API 来实现相应的功能。

与 NSAppleEventManager 中功能相对应的 C API 有 AEInstallEventHandler, NewAEEventHandlerUPP 等,通过这些 API 我们也可以在 REALbasic 中来注册 AppleEvent 了,再配合 Info.plist 中的 URLScheme 声明,即可实现 URL 自定义协议处理句柄。

#if TargetCarbon
    soft declare function AEInstallEventHandler Lib CarbonLib ( _
    theAEEventClass as Integer, 


阅读全文 »

慎用 script 节点的 src 属性来传递参数

在有些使用 javascript 来渲染数据的时候,为了能动态获取不同的数据,并且保持 javascript 代码的可扩展性,会将 javascript 代码中获取数据的部分需要的参数提取出来,做为参数放在 script 节点的外部。

一般来说,传递参数到 javascript 文件内部的方法有两种,一种是将参数写在一个 script 节点中,写成全局变量的方式的传递给紧接着这个 script 节点的外部 javascript 中,Google Analytics 就是使用这样的方式:

<script type="text/javascript">
var p1 = "v1", p2 = "v2";
</script>
<script type="text/javascript" src="foo.js"></script>

另外一种是将参数直接写在 script 节点的 src 属性中,相当于一个页面的查询字符串一样:

<script type="text/javascript" src="foo.js?p1=v1&p2=v2"></script>

不过,使用 script 节点的 src 属性来传递参数需要注意一个很重要的问题,那就是动态变化的 src 属性会导致缓存失效。…

阅读全文 »

REALbasic 中使用结构体作为 Win32 API 的参数及使用 Win32 API 停止服务

在之前,我使用 ShellExecute 这个 API 来执行命令(《REALbasic 中使用 ShellExecute 执行命令》),然后通过这个方法来停止某个服务,但是今天想加服务运行状态检测,这样就可以在服务没有运行的情况下不再询问用户是否需要停止某个服务。

为了省事,我一开始决定同样使用 cmd 去执行一个命令,将服务状态输出到一个临时文件中,再通过读取这个临时文件,查找特征字符串来判断服务是否运行:

// 伪代码
ShellExecute("cmd.exe /c sc query service_name > tmpfile")
dim serviceStatus as string
serviceStatus = TextInputStream.Open(tmpfile).ReadAll()
if instr(serviceStatus, "STOPPED") < 1 then
  // 提示用户是否停止服务
end if

但是这样做不太靠谱,因为 sc 这个命令执行是要时间的,而 ShellExecute 是异步的,这就导致了在调用 ShellExecute 执行完 sc query 之后,临时文件 tmpfile 里并不是马上就有服务状态的内容了。

为了防止这个情况,我再加了一个临时文件内容的检测,如果为空的话,sleep …

阅读全文 »

关于 REALbasic 中使用 AutoDiscovery 时发生错误 40 的问题

今天在使用 AutoDiscovery 发送数据时,发生了错误码为 40 的错误,直接在 UDPSocket 的属性列表里找了一下,没有找到对应的错误码。

在网上搜了一下,找到这篇帖子,里面提到在发送大量数据时,UDPSocket 就会报错误,并且这个错误没有在文档中提到,因此这应该是一个系统级别的错误。

MonkeybreadSoftware 提到了 unix 的错误码定义:

#define    EMSGSIZE    40     /* Message too long */

联想到在程序中是在今天开始有问题的,而且今天添加了一大堆数据,看来的确是同于 UDP 消息过大造成的错误 40。

在网上找了找,使用 UDP 发送消息时,报文的大小最好不要超过 MTU,否则会就容易丢包。我在测试时是使用的 127.0.0.1,包大小为 12.5K,照理说应该是直接走 loopback 而不需要走路由的,就算超过 MTU 也应该能发送,不清楚是不是因为 OS 内部实现机制的问题。

为了彻底解决这个问题,最后还是采用了 TCP 来传递大量数据,只使用 UDP 来传递一些控制信息。

在 AIR 中突破同源策略访问 iframe 中的内容

本篇所讲关于 AIR 的内容是基本 HTML+JS,而不是 Flex 或其他。

在 AIR 中,如果当前页面有一个 iframe,并且我们需要获取这个 iframe 的内容,但是如果 iframe 里包含的是远程页面,在默认情况下,浏览器策略并不允许这种情况,这就是同源策略的限制。

在 Titanium 这个类似于 AIR 的平台中,默认情况下是可以直接从应用的页面中去读取 iframe 中的内容而没有任何限制,但是在 AIR 中不可以。在网上搜索了一番,再看了好几遍 AIR 的文档之后,终于找到解决问题的方法了。

在 AIR 中,iframe 标签拥有额外的几个属性:sandboxRoot、documentRoot、allowCrossDomainXHR 及 ondominitialize。这里为了解决读取 iframe 内容所用到的属性就是 sandboxRoot 及 documentRoot。

通过 sandboxRoot 及 documentRoot,可以将本地的页面映射为远程页面,并在沙盒中运行,另外,在沙盒中运行的页面就会拥有映射域名的域。例如,我们可以将本地的 proxy.html 映射为 http://example.com/local/proxy.html,这样,在实际运行时,proxy.html 中如果用 document.domain 获取页面所在的域,就会得到 example.com,这个时候如果在 proxy.html 



阅读全文 »

使用 arguments.caller 实现自动回调

这是一篇介绍类似于 js hack 的文章,只是说明了一种可行的途径,并且可能会增加代码复杂程度,具体项目中是否可以使用还请自辨:)

在前端开发过程中,有许多业务流程可能是需要用户进行登录的,并且登录过程是放在弹出层中,这样就可以不用刷新页面,增强用户体验。在登录时,用户的操作就会被打断,为了进一步增强用户体验,我们可能需要在登录完成后自动继续进行用户在登录前想进行的操作。

假设有这样一个场景,用户需要发表一个留言,但是发表留言是需要登录的,而发表留言的输入框是一直显示的,这也就要求在用户点击了发表按钮时对用户登录状态进行验证,传统的做法是将在用户登录状态检查封装在一个函数之中,这个函数接收一个回调参数,如果登录验证通过,则执行回调函数。这样的逻辑可以用以下代码表示:

function doAction() {
checkLogin(function() {
// 处理业务逻辑
});
}
function checkLogin(callback) {
if (isLogin) {
callback();
} else {
showLogin(callback);
}
}
function showLogin(callback) {
document.getElementById("login-btn").onclick = function() {
isLogin = true;
callback();
};
}

    总觉得这样的方式会将业务逻辑放到一个匿名函数中,而不是放在了按钮的事件响应函数中,感觉上不是那么好。这对整个事件响应函数的改动比较大,主要的业务逻辑都放在了登录验证函数的回调中。而希望可以是下面这样:



    阅读全文 »