0

Objective C 学习笔记(3) – 实现特点

Posted by reedboat on Jun 9, 2011 in 编程

objc的内存管理方式

 1. retain count. 对象创建的时候(new, alloc, copy)系统自动为对象指定了计数1. 当向向对象发送retain消息的时候,计数+1,当发送release消息的时候,技术-1. 如果计数为0,对象就被销毁,并发送dealloc消息。 注意手工发送retain方法的时候,retain和release必须对应上,保持平衡。

2. 还可以向对象发送autorelease消息,该对象将被放到一个NSAutorelasePool对象池中。当对象池被销毁的时候,会给其中的每个对象,发送release消息. 这些对象的计数都会-1,如果计数减为0,对象就会被销毁. 如果使用Appkit, 会在特定的时间给对象池发送销毁消息,比如当前的用户事件处理完后。

3. 垃圾回收机制。编译的时候,指定-fobjc-gc-only选项,将启用gc机制。用户不需要自己管理内存,像java一样,系统自动识别哪些对象没有指针指向了,自动释放这些内存。. GUI程序中,gc也在事件处理完后触发。 只是目前iphone开发中还不能用这个特性.

对象初始化

objc的对象初始化包括两步
 1. 分配内存[ClassName alloc],alloc方法继承自NSObject,分配内存,并清空置0.
2. 初始化[Object init], 返回对象实例; 注意init方法有可能返回的是跟alloc取得的不同的对象. init 是个普通的方法,类可以有多个初始化方法.

- (id) init {
    if (self = [super init]){
    }
    return (self);
}


object = [[ClassName alloc] init];

categories

作用: 给已经存在的类增加新的对象方法
用法
1. 将类的实现代码拆分到多个文件,如果很多的话
2. 创建私有方法的前向引用
3. 给对象增加非正式的协议

动态特性 [待补充]

Tags:

 
0

Objective C 学习笔记(1) — 语法

Posted by reedboat on Jun 8, 2011 in 编程

objective c 是在C语言上扩展出来的,C的各种语法特性仍然适用。

#import 引用头文件,比#include 好的地方在于头文件只会包含一次,不用再写#ifdef 了.

NSLog Cocoa提供的函数库,统一以NS作为前缀,以示同C标准库的差别. NSLog与printf类似。

@”strings” @后接双引号字符串,代表NSString类型的字符序列,比普通的字符串有更多的用法。

main方法,同c语言一致 int main(int argc, const char * argv[]){return (0);}

面向对象.

id:对象指针类型
方法调用 [shape draw] ,调用shape对象的draw方法.shape 是id类型

[circle draw]
//带参数的调用,green是参数
[circle setFillColor:green]

@interface 声明类接口 

@interface Circle :NSObject
{
    ShapeColor fillColor;
    ShapeRect bounds;
}
- (void) setFillColor: (ShapeColor) fillColor;
- (void) setBounds: (ShapeRect) bounds;
- (void) draw;
@end

@implementation 实现类

@implementation Circle. 实现代码中省略掉了self self->fillColor = c;
- (void) setFillColor: ( ShapeColor ) c
{
    fillColor = c;
}
@end //Circle

创建新实例, 调用类的new方法

[Circle new]

构造方法
init

访问器 getter/setter
set方法需要带上set前缀,get方法不需要,保持跟属性一致即可。
@property 可以简化访问器. 声明同数据成员相同的属性,可以省去访问器方法的编写
@property (选项) 类型 名字;选项包括readwrite/readonly/assign/retain/copy/atomicity等。
在实现中需要用@synthesize让编译器获取实现代码
之后可以用.来引用属性来读取和写入,而不需要调用方法。

继承/组合
super 访问父类
self

@class 声明使用的类,可以不需要#import a.h, 避免循环引用

静态方法, 以+开头
+ (void) instance;

@protocol 协议,类似其他语言中的接口。 遵循协议就必须实现其中规定的方法。
一个类可以同时遵循多种协议。还可以用@optional指定非必须实现的方法

@protocol NSCoding
 
- (void) encodeWithCoder: (NSCoder *) aCoder;
- (id) initWithCoder: (NScoder *) aDecoder;



@end

@interface Car: NSObject
{
}

@end

 

Tags:

 
1

构建我们的离线Web应用

Posted by reedboat on Jan 16, 2011 in 产品, 编程, web

公司希望为我们的Web站点,开发一个html5版本,拓展到Pad端,给使用高级浏览器的用户一个更加完善的用户体验。其中一个重要的功能就是支持离线应用。

利用html5构建一个离线应用,主要依赖于三个新的特性

1. 离线资源缓存:
可以在一个manifest文件中指明离线应用工作所需的资源文件。缓存的文件可以在manifest文件本身发生变化的时候更新,或者检测window.applicationCache.status,然后调用window.applicationCache.update()更新缓存。
2. 在线状态检测:
html5支持通过navigator.onLine获取当前的在线状态。html5还提供在线和离线事件机制.针对在线状态,我们可以做出不同的处理
3. 本地数据存储:
html5提供了LocalStorage和WebDatabase(WebSQL/indexedDB)两种存储机制。前者提供key/value存储方式,后者提供关系数据库存储功能。

离线资源缓存

要使用离线缓存功能,需要在编写manifest文件,并指定使用的manifest.

    <doctype html5>
    <html manifest="demo.manifest">
    ...
    </html>

manifest文件格式.

  • 首行必须是 CACHE MANIFEST。其后,每一行列出一个需要缓存的资源文件名。
  • 可根据需要列出在线访问的白名单。白名单中的所有资源不会被缓存,在使用时将直接在线访问。声明白名单使用 NETWORK:标识符。
  • 如果在白名单后还要补充需要缓存的资源,可以使用 CACHE:标识符。
  • 如果要声明某 URI 不能访问时的替补 URI,可以使用 FALLBACK:标识符。其后的每一行包含两个 URI,当第一个 URI 不可访问时,浏览器将尝试使用第二个 URI。
  • 注释要另起一行,以 # 号开头。

文件示例

 CACHE MANIFEST
 demo.html
 demo.css
 demo.js

 NETWORK:
 demo.php

 CACHE:
 demo2.css

 FALLBACK:
 /files/ /default.html

在线状态检测

上面提到过,目前html5提供了两种检测是否在线的方式

检测 navigator.onLine
侦听document的online和offline事件

本地数据存储

通常我们用cookie来存储数据,但是cookie存储的数据量太小.而且每次发起http请求都要带上,增加了数据的传输量.html5新引入了两种key/value存储方式,提供比较大规模,性能更高安全性更好的存储方式。 localStorage 和 sessionStorage
sessionStorage只在本次浏览器会话中保存,浏览器关闭之后存储就被丢弃。localStoage则可以比较长期的保存。但是使用方式都一样,非常简单.
直接

localStorage.key1 = val1;
console.log( localStorage.key1 );

另一种方式是关系数据库存储,不过虽然chrome提供了websql特性。但是貌似html5工作组停止了这个标准的制定工作,转而支持另一种indexedDb的标准。但是indexedDB目前还没有浏览器实现。我的理解,前者基于Sqlite的Sql来操作数据,后者可能更像是ORM的方式,数据操作更加优雅更加对象化。所以可能暂时这个功能得不到大范围使用。

问题

利用离线资源缓存,我们就可以能够访问读到应用了。然后利用状态检测和数据存储功能,我们就可以在离线的时候,将用户的操作保存起来,等到在线的时候,再将它们发布到服务器上。做了一些demo后发现,已经能实现一些简单的应用了, 还有一些问题需要解决,包括。

  1. manifest文件不支持通配符,因此我们的一些通过动态生成的文件,比如合并压缩的js和css文件,不太好缓存。以及很多根据ID通过ajax生成的数据也不容易缓存。
  2. 一些离线状态下的操作,比如发表的评论和执行的转发操作。即时能够通过在线的时候同步,但是也可能面对失去了时效性之类的问题。而且下次再次离线上来的时候,还没能够同步到服务器的这些离线操作内容不容易呈现出来。
  3. 如何在线上的内容更新的时候,通知客户端更新缓存。动态生成manifest文件,可能导致所有的内容都更新。
  4. httpCache和offlineCache的内容无法共享,导致的客户端存储空间浪费。

Tags: , , ,

 
0

yield的简单理解

Posted by reedboat on Jan 12, 2011 in 编程

python中的yield关键字,之前没有仔细看。今天看了一下。我的理解是这样的, yield将一个函数打断成了多段,形成了一个迭代器(简单的理解成一个数组,数组中的每个元素是一段代码)。每次调用该迭代器的next()或者send()方法的时候,执行这个函数的下一段,然后保存函数执行中的各个变量的值和当前的控制流程,等待下次执行next()或者send()的时候恢复。

例如 下面定义的add函数

def add(a):
  print a
  a=a+1
  yield
  print a

c=add(10)
c.next()

调用add函数的时候,并不执行add函数中的代码。而是返回一个迭代器 . ( c=add(10) )c就是一个迭代器。调用c.next()方法的时候,才开始执行add函数的内容。第一次调用的时候执行到yield这一行中止了,输出a的值10。下一次调用c.next()才输出11。

yield 后面还可以跟一个参数,当调用next()方法的时候,就会返回这个值,外界也可以得到。如果用send(msg)方法,那么yield就直接返回msg值。

def add(a):
  b = yield 1
  a = a+b
  print a

c = add(10)
c.next()

上面的这个例子。
第二次执行的时候,如果用c.next(), 那么b=1,c.next()的返回值也是1,输出内容是11。
如果使用c.send(5), 那么b=5,输出内容将是15。

yield这种使用方式,改变的通常的编写程序的思路,在循环递归中的用法就比较复杂了,还需要慢慢体会。

Tags: , ,

 
0

用Redis来做排行榜存储

Posted by reedboat on Dec 5, 2010 in 编程

随着SNS和微博产品的火热,NoSQL概念逐渐的兴起。出现了一大批各种各样的KeyValue存储系统。我比较感兴趣的是MongoDb和Redis, 因为单纯的Key-Value存储系统难以满足各种复杂的逻辑业务, 仍这两个数据库分别加入了一些关系性的特性,如能有效利用会有很好的效果。

redis目前提供四种数据类型:string,list,set,zset(sorted set)和hset(hash set)。
string是最简单的类型,你可以理解成与Memcached一模一个的类型,一个key对应一个value,其上支持的操作与Memcached的操作类似。但它的功能更丰富。
list是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。
set是集合,和我们数学中的集合概念相似,对集合的操作有添加删除元素,有对多个集合求交并差等操作。操作中key理解为集合的名字。
zset是set的一个升级版本,他在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。操作中key理解为zset的名字。
hset是另一个set,一个key对应的不再是一个元素而是一个hash表。

zset是个非常好的排行榜存储,一个key对应的一个数据集合,集合中的每个元素包涵两部分,value(待)排序的元素)和score(用来排序的得分依据)。例如用来存储微博关注数排行榜,value可以是微博用户的ID,而score则是该用户的关注数。
而且对于大部分排行榜数据,其实只需要存储Top N的数据,数据量小,效率高,用内存来存储非常合适,排行榜的实时性也可以做到很高。因为数据是用集合来存储的,存储的时候实际上是没有顺序的,排序计算是在获取的时候来做的.如果访问并发量很大的话,还可以再在前面做一个缓存。
利用redis的一个内置操作直接清除TopN外面的元素, 保持存储量的大小。
例如一个需要发布前30名的排行榜,我们使用的时候可以保留前500名的数据,防止需求变化。然后不断的往其中添加新数据,每当集合中的元素达到1000条的时候,进行一次trim操作,将集合的元素数量压缩成500。当获取前30名的时候,同样用redis做一个缓存,缓存时间设成30秒等。

redis zset数据结构支持的操作包括:
– 添加/删除/统计数量
– 修改score
– 获得score/排名
– 获取排名在某个区间的元素集合
– 获取score在某个范围的元素集合/数量
– 清理score/排名在某个区间外的元素
– 交集/并集运算

Tags: ,

Copyright © 2012 苇叶舟 All rights reserved. Theme by Laptop Geek.