Archive for the ‘iPhone开发’ Category.

不要对viewController作这样的事情

错误:

UIViewController *aViewController = [[UIViewController alloc] init];
 
[window addSubview:aViewController.view];
 
[aViewController release];

这样的话,系统会崩溃的… window或着其他父视图是不会retain整个viewController的,这个时候不能立刻release

正确:

[aViewController.view removeFromSuperview];
 
[aViewController release];

也就是说,在release之前需要从superview中移除这个viewController的view。如果一直都需要这个view,那就在dealloc里面作这些事情就可以了

数据类型/对象类型介绍(1)NSString

字符串是程序设计最常用的数据类型之一了。在Mac/iPhone编程中,苹果为我们提供了一个不同的字符串类型NSString。有别与普通的String为数据类型,NSString其实是一个对象类型。NSString是NSObject(Cocoa Foundation的基础对象)的子类,所以具有NSObject的所有特性,好的和好的… ….

小常识:
NS是Cocoa类对象类型的前缀,来源于史蒂夫-乔布斯被苹果开除那段时间建立的公司NeXT.
@是Cocoa元素的前缀,很多地方我们会看到,比如接下来...

1, 创建一个NSString对象

简单方法:

NSString *aString = @"我是个NS字符串!";  //除了引号外加@, 没别的区别

*上面的不需要操心内存管理哟~

复杂一点儿:(需要内存管理的)

NSString *aString = [[NSString alloc] initWithFormat:@"这也是个NS字符串!"];

*initWithFormat是其中一个初始化方法,常用的还有

//从一个文件读取需要的内容
- (id)initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error
//从一个地址读取需要的内容
- (id)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error

*以上方法得到的NSString的retain值为1,所以记得release掉阿~~

2,使用一个NSString对象

NSString *aString = @"This is a NSString";
 
NSLog(aString);   //在控制台输出信息,该函数方法需要一个NSString对象作为参数
 
NSLog("这样不会好使的");
 
NSLog(@"这样就会好使拉~");

再比如设置一个UIView的标题:

[UIView setTitle:aString];
 
[UIView setTitle:@"标题"];
 
UIView.title = aString;

3,释放NSString

[aString release]; //对象将被系统释放掉咯

*记得不要释放直接用 = @”xxx” 的NSString对象哟,系统会管的~

4,快速使用一个NSString

NSLog([NSString stringWithFormat:@"一个NS字符串"]);

//这种快速方法返回的是一个retain为1,autorelease的对象,不需要操心它的内存管理

5,常用方法

我喜欢NSString的地方就在于很多方法非常方便,比如:

nString = [aString substringToIndex:4]; //nString将得到aString中的前四个字符

6,小结

暂时能记起来的就这么些了,有机会再补充,希望大家NS的愉快~

iPhone上的JSON(三)JSON+UITableView

既然JSON这么好,它怎么和UITableView结合使用呢?

首先看看我们的JSON文件吧:

{
	"老张家":["大张","二张","三张"],
	"老李家":["大李","二李"]
}

完成的作品是这样样子的~~(点击放大阿~~)

屏幕快照 2009-08-10 下午02.38.49

好,开始打代码吧。

1,首先copy JSON库到当前的Project里面。

屏幕快照 2009-08-10 下午02.50.52

2,建立一个数据源类。我给它起名叫MyDataSource, 看看里面都有什么吧:

@interface MyDataSource : NSObject {}
+ (id)dataSource;
@end
 
#import "JSON.h"
 
@implementation MyDataSource
+ (id)dataSource
{
	NSString* JSONString = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"data" ofType:@"json"]
							 encoding:NSUTF8StringEncoding error:nil];
	return [JSONString JSONValue];
}
@end

里面非常简单,只有一个类方法dataSource。在其中我们读取json文件的内容到一个NSString中,并用JSON框架来解读成一个NSDictionary,返回值为id。因为虽然大多的时候最外的对象都为NSDictionary,但是出于严谨,万一是NSArray不就崩溃了。所以使用id,这样其实就有再次可以用的特性了。

3,建立一个UITableViewController, 然后作适当的设置:

#import "MyTableViewController.h"
#import "MyDataSource.h"
 
@implementation MyTableViewController
 
- (id)initWithStyle:(UITableViewStyle)style
{
	if (self = [super initWithStyle:style]) {
		myData = [[MyDataSource dataSource] retain];
		//在这里我们初始化myData,其实就是一个id对象
		//传入由MyDataSource解析出的NSDictionary
	}
	return self;
}
 
#pragma mark Table view methods
 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [myData count];    //有多少个section,也就是“几家”
}
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[myData valueForKey:[[myData allKeys] objectAtIndex:section]] count];
//这里我们需要告诉UITableViewController每个section里面有几个,也就是“一家里面有几口人”
}
 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                                reuseIdentifier:CellIdentifier] autorelease];
    }
   //上面的东西都是重复白给的,平时没事不用想为什么,照抄就可以了
	cell.textLabel.text = [[myData valueForKey:[[myData allKeys] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
	//这句看上去复杂,但是其实不过是在特定section里面找到对应的array,
	//然后在array中找到indexPath.row所在的内容
    return cell;
}
 
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
	return [[myData allKeys] objectAtIndex:section];
//这里设置对应section的名字,很简单allKey返回所有的键值为一个array,也就是“张家”,“李家”
//然后用objectAtIndex: 来找出究竟是哪一个就可以了!
}
 
- (void)dealloc {
    [myData release]; //“我们是runtime的好市民”...release就好Alan......
    [super dealloc];
}
@end

4,在主程序代理 xxxAppDelegate 里面初始化这个UITableViewController然后添加它的view到window的subview中就OK拉!

5,编译运行,没有错误就万事大吉!大吉!

阿弥陀佛,祝各位愉快~


第一期请参看iPhone上的JSON
第二期请参看iPhone上的JSON(二)

iPhone上的JSON(二)

上一期基本上讨论了Objc的JSON框架的原理,现在简单介绍一下使用。

在CS193P的课堂程序上,列出了以下函数:

+ (id)fetchJSONValueForURL:(NSURL *)url
{
    NSString *jsonString = [[NSString alloc] initWithContentsOfURL:url
                                                          encoding:NSUTF8StringEncoding error:nil];
 
    id jsonValue = [jsonString JSONValue];
    [jsonString release];
    return jsonValue;
}

基本上这个函数方法就是将一个传入的互联网地址,当然是一个.json文件的位置。然后传出的就是一个NSDictionary~

我在使用的时候,写了一个方法来调用它:

+ (NSDictionary *)fetchLibraryInformation
{
    NSString *urlString = [NSString stringWithFormat:@"http://gzl.name/appData/MyFodian/Lib/main.json"];
    NSURL *url = [NSURL URLWithString:urlString];
	NSLog(@"fetching library data");
    return [self fetchJSONValueForURL:url];
}

这个方法不过是将我存放json文件的地址告诉了前面的方法,然后返回这个NSDictionary,这回的返回值我用得NSDictionary,其实和id在这里没有区别。记得在使用这个对象的时候还要retain一下,否则一会儿就没有咯。因为JSONValue方法返回的应该是一个autorelease对象。

接下来我们就可以使用这个NSDictionary中的数据拉!

第一期请参看iPhone上的JSON

TTView的简单使用

屏幕快照 2009-08-10 上午11.11.26,320库真是好的不得了,都不知道该怎么夸它了,我在自己的佛历View中就使用了其中一个TTView,非常漂亮简单的风格。再也不用考虑是不是在UILabel下面放一个UIImageView等等… 而且还要自己弄图片的大小

在TTCatalog中展示了14种TTView的style,不知道你喜欢哪一个呢?

**我想我用的是第二个吧~

/*******************************************************************/

看看我的代码吧~

UIColor* blue = RGBCOLOR(191, 197, 208);
TTStyle *myStyle = [TTShapeStyle styleWithShape:[TTRoundedRectangleShape shapeWithRadius:10]
next:[TTShadowStyle styleWithColor:RGBACOLOR(255,255,255,0.9) blur:1 offset:CGSizeMake(0, 1)
next:[TTLinearGradientFillStyle styleWithColor1:RGBCOLOR(255, 255, 255)
		color2:RGBCOLOR(216, 221, 231)
next:[TTSolidBorderStyle styleWithColor:blue width:1 next:nil]]]];
 
viewA = [[[TTView alloc] initWithFrame:CGRectMake(10, 220, 300, 40)] autorelease];
viewB = [[[TTView alloc] initWithFrame:CGRectMake(10, 263, 300, 40)] autorelease];
viewC = [[[TTView alloc] initWithFrame:CGRectMake(10, 306, 300, 100)] autorelease];
viewA.backgroundColor = self.view.backgroundColor;
viewB.backgroundColor = self.view.backgroundColor;
viewC.backgroundColor = self.view.backgroundColor;
viewA.style = myStyle;
viewB.style = myStyle;
viewC.style = myStyle;
[self.view addSubview:viewA];
[self.view addSubview:viewB];
[self.view addSubview:viewC];

我一共需要三个框子,而style那个部分其实是完全照抄TTCatalog的(人懒也不是罪过)

但是需要注意一下事项:

1,必须要设置self的backgroundColor, 然后再赋值给TTView, 否则缺省值会变成黑色…
2, 记得release掉那些TTView,我使用的autorelease,因为superView会retain那些对象的~
3,在使用UILabel的时候,如果想设置UILabel为透明,只需要设置UILabel.backgroundColor为[UIColor clearColor]就可以拉,这样就不会让UILabel弄出一个窟窿来咯~

快去下载320库来试试阿!

实例:iPhone随机数生成器

我作了一个iPhone版本的随机数生成器,希望大家喜欢

>>>>RandomNumber<<<<

其实就是很简单的利用 random() 函数计算,和简单的UISlider的使用

屏幕快照 2009-08-09 下午02.29.52

TTPhotoViewController使用向导

TTPhotoViewController

Three20库是再好不过的iPhone开发资源了,尤其是其中提供的TT图片视图控制器提供了简单易用的图片浏览功能,下面我就简单的介绍了一下如何使用TTPhotoViewController

/*********************************************************************************************/

首先我们建立一个TTPhotoViewController的子类:

@interface LibDetailViewController : TTPhotoViewController {

然后在viewDidLoad代理方法中添加数据源(datasource)

... ...
for (NSInteger i=1; i&lt;=libLength; i++) {
	picIndex = [Zeros stringByAppendingString:[NSString stringWithFormat:@"%d",i]];
 
	picIndex = [picIndex substringFromIndex:([picIndex length] - libDigits)];
 
	[photosArray addObject:[[[MockPhoto alloc]
			initWithURL:[NSString stringWithFormat:@"%@%@/o/%@%@%@.jpg",addr,libName,libName,addiPage,picIndex]
			smallURL:[NSString stringWithFormat:@"%@%@/%@%@%@.jpg",addr,libName,libName,addiPage,picIndex]
			size:CGSizeMake(320, 480)]autorelease]];
	//这一行是最重要了,因为TTPhotoViewController需要的是一个TTPhotoSource作为数据源对象,
	//但是这个对象其实就是一个TTPhoto的数组,所以我们在这里创建并添加所有的图片信息到一个可变数组内。
}
 
self.photoSource = [[[MockPhotoSource alloc]
		initWithType:MockPhotoSourceDelayed
		title:libTitle
		photos:photosArray
		photos2:nil]
			autorelease];
	//这里初始化并赋值这个TTPhotoSource对象到self.photoSource上
 
[photosArray release]; //由于self会retainphtosArray,所以可以release掉它了。

我在这里使用了Three20样例sample里面的类MockPhotoSource来创建TTPhoto和TTPhotoSource对象。

就这么简单,你就可以使用TTPhotoViewCotroller的便利咯~

iPhone上的JSON

JSON我就不多解释了,需要更多信息的朋友请到json.org上查看。

在iPhone上访问网络内容是很必须的,而一些数据就需要以某种形式储存在web服务器上。比如一个app的目录,内容,索引等等。而xml和json,plist都是比较方便的方式。

-XML在iPhone上是非常好用的,但是对复杂的数据结构使用上就不那么方便了,具体可以参阅苹果的“基于事件的XML”和“基于树的XML”编程向导

-plist是再方便不过了,不过我看最多也就是一个NSDictionary而已,复杂一些的话,数据输入上也会非常非常的麻烦。

-JSON本来是不被苹果支持的,但是有人很Nice的帮我们解决了这个问题: for OBJC http://code.google.com/p/-framework/

基本上来说,这个框架异常的简单易用,会将得到的json字符串处理成一个复杂NSDictionary对象,而每一个值都还是一个NSDictionary对象

比如:

{
	"华藏净宗学会":
	{
		"zhaomu":
		{
			"name":"净宗朝暮课本",
			"length":142,
			"digits":3
		},
		"kesong":
		{
			"name":"净宗共修课本",
			"length":75,
			"digits":2
		}
	},
	"生命基金会":
	{
		"dabei88":
		{
			"name":"大悲出相图",
			"length":88,
			"digits":2
		}
	}
}

就会转换为一个复杂无比的NSDictionary:

[[NSDictionary alloc] 
 initWithObjects:[NSArray 
		  arrayWithObjects:
		  [NSDictionary 
		   dictionaryWithObjects:[NSArray 
				  arrayWithObjects:
				  [NSDictionary 
				   dictionaryWithObjects:[NSArray 
						  arrayWithObjects:
							  @"净宗朝暮课本",
							  @"142",
							  @"3",nil] 
				   forKeys:
				   [NSArray arrayWithObjects:
				   @"name",
				   @"length",
				   @"digits",nil]],
				  [NSDictionary 
				   dictionaryWithObjects:[NSArray 
						  arrayWithObjects:
						  @"净宗共修课本",
						  @"75",
						  @"2",nil] 
				   forKeys:
				   [NSArray arrayWithObjects:
				   @"name",
				   @"length",
				   @"digits",nil]],nil]
		   forKeys:[NSArray arrayWithObjects:@"zhaomu",@"kesong",nil]],
		  [NSDictionary 
		   dictionaryWithObjects:[NSArray 
				  arrayWithObjects:
				  [NSDictionary 
				   dictionaryWithObjects:[NSArray 
						  arrayWithObjects:
						  @"大悲出相图",
						  @"88",
						  @"2",nil] 
				   forKeys:
				   [NSArray arrayWithObjects:
				   @"name",
				   @"length",
				   @"digits",nil]],nil]
		   forKeys:[NSArray arrayWithObjects:@"dabei88",nil]],nil]
 forKeys:[NSArray arrayWithObjects:@"华藏净宗学会",@"生命基金会",nil]];

我是非常佩服自己能打出来上面的巨大无比的定义式。。。。没有编译错误

不管怎么样,转换后,在系统中就可以非常方便的使用json的键值结构信息咯~!!!

UITableViewController重要配置方法和Delegate

列表在iPhone开发中起着决定性的重要作用,但是UITableViewController并不是那么简单使用的,以下就是其中的重要方法和Delegate:

//这个delegate会获取有多少个"章节"
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1; //这里返回的是章节(section)的个数
//如果数据源是一个复杂array或dictionary,则可以返回
    return [NSArray count];  作为章节的个数
}
 
 
//这个delegate会获取章节内有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 0; //这个部分是必须要改的,否则0行的话,就是一个空表了
//如果数据源是一个复杂array或dictionary, 可以使用嵌套的查询来返回这个个数了
//比如:
    return [[NSArray objectAtIndex:section]    //section为整数,所以如果使用NSDictionary,
                                                                   //记得使用辅助方法来计算其索引的key,或嵌套查询 
                                        count];   //因为返回的依旧是一个array或dictionary对象,所以我们获取它的大小count
}
 
 
 
// 这里编辑每个栏格的外观
- (UITableViewCell *)tableView:(UITableView *)tableView 
      cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                reuseIdentifier:CellIdentifier] autorelease];
    }
 
    // 一般我们就可以在这开始设置这个cell了,比如设置文字等:
    cell.textField.text = [NSArray objectAtIndex:indexPath.row]; 
        //假设这个NSArray就是本section的数据了,否则需要嵌套来查询section的信息,如前一个delegate
 
    return cell;
}
 
 
 
//当栏格被点击后需要触发的事件
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	AnotherViewController *anotherViewController = [[AnotherViewController alloc]
                                                                         initWithNibName:@"AnotherView" bundle:nil];
        // 建立并使用本地导航管理推入视图控制器是最普遍的方法
	[self.navigationController pushViewController:anotherViewController];
	[anotherViewController release];
}
 
 
 
// 该delegate是可选的,对那些可以被编辑的对象返回YES
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
 
 
 
// 对特定编辑风格进行操作
- (void)tableView:(UITableView *)tableView 
        commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
        forRowAtIndexPath:(NSIndexPath *)indexPath 
{
//以下是apple的缺省实例
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // 如果是要删除那行栏格,那么就去删除数据源中的对象
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // 如果是要添加栏格,那么就应该将要添加的内容添加到数据源中
    }
}
 
 
 
// 可选delegate,对那些被移动栏格作特定操作
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath 
        toIndexPath:(NSIndexPath *)toIndexPath {
}
 
 
 
// 对那些可以移动的行返回YES
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // 如果不像让栏格移动,就返回NO
    return YES;
}

以上就是所有重要的delegate方法,只要数量使用这些方法,我们就能创建和自定义自己想要的iPhone表格

iphone程序的开始画面设置

* iPhone软件启动后的第一屏图片是非常重要的往往就是loading载入中的意思。设置它说来也简单,但是却无比重要

只需要在resource里面将你希望设置的图片更名为Default.png,这个图片就可以成为iPhone载入的缺省图片

屏幕快照 2009-07-25 上午10.50.19