Archive for the ‘Cocoa开发’ Category.
2009年08月27日, 11:59 下午
在我们分析了程序主代理文件(AppDelegate)之后,我们先来看看一对自动生成的文件Event.h/.m
@interface Event : NSManagedObject {}
@property (nonatomic, retain) NSDate *creationDate;
@property (nonatomic, retain) NSNumber *latitude;
@property (nonatomic, retain) NSNumber *longitude;
@end
#import "Event.h"
@implementation Event
@dynamic creationDate;
@dynamic latitude;
@dynamic longitude;
@end
从上面我们能看出来,一个实体Event也就会被生成一个NSManagedObject(被管理对象),然后任何accessor和getter都是被动态生成的,我们其实完全不用操任何的心,只需要在xcdatamodel文件里面配置后,点击添加文件,添加NSManagedObject文件,就会看到自动感知的类对象,然后生成就可以了。
下面是根视图控制器,是一个列表视图(UITableViewController)
#import <CoreLocation/CoreLocation.h>
@interface RootViewController : UITableViewController <CLLocationManagerDelegate> {
//看到是UITableViewController的子类,由于需要使用Core Location,
//所以在后面履行其protocal
NSMutableArray *eventsArray;
NSManagedObjectContext *managedObjectContext;
//这个被管理对象内容器就是我们真正对Core Data数据的操作对象
CLLocationManager *locationManager; //用来得到地理位置的Core Location对象
UIBarButtonItem *addButton; //右上角的添加键
}
@property (nonatomic, retain) NSMutableArray *eventsArray;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, retain) UIBarButtonItem *addButton;
- (void)addEvent;
@end
#import "RootViewController.h"
#import "LocationsAppDelegate.h"
#import "Event.h"
@implementation RootViewController
@synthesize eventsArray, managedObjectContext, addButton, locationManager;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Locations"; //设置列表视图的标题
self.navigationItem.leftBarButtonItem = self.editButtonItem; //导航栏左边的编辑按钮
addButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:@selector(addEvent)]; //初始化添加按钮,
addButton.enabled = NO; //在Core Location初始化之前将其关闭
self.navigationItem.rightBarButtonItem = addButton;
//把这个添加按钮添加到导航栏右侧
// 启动CLocation
[[self locationManager] startUpdatingLocation];
//初始化一个“获取请求”到我们的实体“Event”
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event"
inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// 将时间以建立时间排序,最新的在最上
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// 执行“获取”操作,得到一个“可变数组”的拷贝
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext
executeFetchRequest:request
error:&error] mutableCopy];
if (mutableFetchResults == nil) {
//如果结果为空,在这作错误响应
}
// 将得到的本地数组赋值到本类的全局数组,然后清理无用的对象
[self setEventsArray:mutableFetchResults];
[mutableFetchResults release];
[request release];
}
- (void)viewDidUnload {
// 当视图被卸载后,将以下指针置空
self.eventsArray = nil;
self.locationManager = nil;
self.addButton = nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// 只有一个章节
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// 在数组里面有多少个对象,在列表视图就有多少行
return [eventsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 一个“日期格式化器”(凑合明白就好...)用来以特定的格式创建得到的日期
static NSDateFormatter *dateFormatter = nil;
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
}
static NSNumberFormatter *numberFormatter = nil;
if (numberFormatter == nil) {
numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:3];
}
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
UITableViewCellStyleSubtitle;
}
// 从数组中得到这个Event对象
Event *event = (Event *)[eventsArray objectAtIndex:indexPath.row];
cell.textLabel.text = [dateFormatter stringFromDate:[event creationDate]];
NSString *string = [NSString stringWithFormat:@"%@, %@",
[numberFormatter stringFromNumber:[event latitude]],
[numberFormatter stringFromNumber:[event longitude]]];
cell.detailTextLabel.text = string;
return cell;
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// 删除被惯例对象在索引路径(index path)
NSManagedObject *eventToDelete = [eventsArray objectAtIndex:indexPath.row];
[managedObjectContext deleteObject:eventToDelete];
// 更新数组和列表视图
[eventsArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
// 提交更改到Core Data
NSError *error;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
}
}
- (void)addEvent {
//如果得不到位置,就返回.
CLLocation *location = [locationManager location];
if (!location) {
return; }
//建立一个Event实体对象
Event *event = (Event *)[NSEntityDescription
insertNewObjectForEntityForName:@"Event"
inManagedObjectContext:managedObjectContext];
//得到经纬度,然后赋值到event对象去
CLLocationCoordinate2D coordinate = [location coordinate];
[event setLatitude:[NSNumber numberWithDouble:coordinate.latitude]];
[event setLongitude:[NSNumber numberWithDouble:coordinate.longitude]];
// 实例里面并没有使用CL的时间标签,因为在模拟器中会是一样的
// [event setCreationDate:[location timestamp]];
[event setCreationDate:[NSDate date]];
//所以现在使用的是现在的时间,而不是得到位置的时候的时间
// 保存更改
NSError *error;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
// 将新Event放到最上面,所以添加到0的位置
// 然后滚动列表视图到最上面,如果没有那么多的数据是看不出来区别的
[eventsArray insertObject:event atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (CLLocationManager *)locationManager {
//自定义的CLocation的getter,方便初始化
if (locationManager != nil) {
return locationManager;
}
//初始化CL对象,然后设置精准度,然后将代理对象设为本地
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDelegate:self];
return locationManager;
}
//CLocation的一个代理方法,如果成功就开启右侧添加按钮
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
addButton.enabled = YES;
}
//CLocation的一个代理方法,如果失败了就关闭(disable)右侧添加按钮
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
addButton.enabled = NO;
}
- (void)dealloc {
//释放对象
[managedObjectContext release];
[eventsArray release];
[locationManager release];
[addButton release];
[super dealloc];
}
@end
从上面的源代码,我们可以看出,
1,在这里数据并不是每次都由NSManagedContext对象得到,而是由一个数组得出。
2,数组是一个可变数组,由第一次载入的视图的时候从NSManagedContext中得到
3,从NSManagedContext对象中得到数据需要使用NSFetchRequest来初始化一个“获取”
4,每次获得新的数据的时候,同时保存到数组和NSManagedContext中,添加后需要对更改进行提交
2009年08月26日, 7:18 下午
补一下“实体”的概念,实体也就是Entity,在打开xcdatamodel文件的时候,我们可以看到

在这里,这个实体叫“Event”,而实体的参数有“创建日期”,“纬度”,“经度”。也就是说,其实这个实体被使用后,我们可以这样理解,实体就是表名,而参数就是列名,然后整个实体就是一张表。当这个Model描述多个实体的关系的时候,就像是一个关系型数据库一样,虽然苹果说“不是!”
2009年08月26日, 6:10 下午

Core Data是个好东西,在数据储存操作上速度快,容易操作,是一种类似关系数据库的东西。但是有些不那么好学,那到底Core Data是怎么操作的呢?怎么用呢?怎么来编程呢?我们一起来学习吧,接下来使用苹果提供的实例程序Locations来作分析:
>程序介绍:
右侧是改程序的截图,基本上来说就是通过使用Core Location来得到当时的位置,然后在点击“+”的时候记录下当时的经纬度。通过UITableViewController的功能来添加,编辑,删除等功能。整体程序使用Core Data来储存数据,实体(Entity)为一个位置,包括以下参数:1,时间(收集数据的时间)2,纬度,3,经度
首先我们看看该程序的AppDelegate.h
@interface LocationsAppDelegate : NSObject {
UIWindow *window;
UINavigationController *navigationController; //导航栏
//以下定义了Core Data的三个决定性组建,等后面m文件里面再多介绍
NSPersistentStoreCoordinator *persistentStoreCoordinator;
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) UINavigationController *navigationController;
- (IBAction)saveAction:sender; //这个没找到作用...根本就没用到IB
//还记得吧,nonatomic是因为这个程序是单线程
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator
*persistentStoreCoordinator;
@property (nonatomic, readonly) NSString *applicationDocumentsDirectory;
//程序文档目录是主要为了给NSPersistentStoreCoordinator找个存SQLite文件的地方
@end
从上面的我们能看出来,该程序是通过一个根Core Data数据管理来管理整个程序的CoreData数据的,接下来看m文件也会对此作更多的理解。
#import "LocationsAppDelegate.h"
#import "RootViewController.h" //该程序使用了一个根视图控制器,所以导入了这个类
@implementation LocationsAppDelegate
@synthesize window;
@synthesize navigationController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
//初始化根视图控制器,它是一个列表视图控制器
RootViewController *rootViewController = [[RootViewController alloc]
initWithStyle:UITableViewStylePlain];
//通过下面的自定义getter得到CoreData的“被管理对象内容器”
NSManagedObjectContext *context = [self managedObjectContext];
if (!context) {
// 如果getter出错,在这里来排错
}
rootViewController.managedObjectContext = context;
//rootViewController有一个本地“被管理对象内容器”,在这里赋值过去
UINavigationController *aNavigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];
self.navigationController = aNavigationController;
//初始化导航栏,根视图为rootViewController,并指定该导航栏为程序导航栏
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
//由于导航栏retain了根视图,所以在这里可以release掉它了
[rootViewController release];
//由于self已经retain了导航栏,所以导航栏可以release
[aNavigationController release];
}
//applicationWillTerminate: 在程序结束前,Core Data会保存任何对其的更改
- (void)applicationWillTerminate:(UIApplication *)application {
NSError *error;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Handle the error.
}
}
}
//在得到点击事件后,保存更改
- (IBAction)saveAction:(id)sender {
NSError *error;
if (![[self managedObjectContext] save:&error]) {
// Handle error
}
}
//自定义的managedObjectContext的getter, 它其实是真正在使用的时候的被操作对象
- (NSManagedObjectContext *) managedObjectContext {
//如果已经有这个对象,就直接返回,否则继续
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
//这里可以看到,“内容管理器”和“数据一致性存储器”的关系,
//managedObjectContext需要得到这个“数据一致性存储器”
}
return managedObjectContext;
}
//自定义的CoreData数据模板的getter,数据模板其实就是一个描述实体与实体的关系
//,类似于关系型数据库的关系描述文件
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
//从本地所有xcdatamodel文件得到这个CoreData数据模板
return managedObjectModel;
}
//自定义“数据一致性存储器” persistentStoreCoordinator的getter
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
//定义一个本地地址到NSURL,用来存储那个SQLite文件
NSURL *storeUrl = [NSURL fileURLWithPath:
[[self applicationDocumentsDirectory]
stringByAppendingPathComponent: @"Locations.sqlite"]];
NSError *error;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel: [self managedObjectModel]];
//从这里可以看出,其实persistentStoreCoordinator需要的不过是一个
//存储数据的位置,它是负责管理CoreData如何储存数据的
if (![persistentStoreCoordinator
addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeUrl
options:nil
error:&error]) {
// Handle the error.
}
return persistentStoreCoordinator;
}
//返回该程序的档案目录,用来简单使用
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
//我原来的帖子中介绍过,方法其实是一模一样的
}
- (void)dealloc {
//释放内存
[managedObjectContext release];
[managedObjectModel release];
[persistentStoreCoordinator release];
[navigationController release];
[window release];
[super dealloc];
}
@end
从上面的程序主代理文件可以看出,CoreData的简单使用不过是通过三个组建。
NSManagedObjectModel来描述实体与实体的关系,也就是类似于表和表的关系。
NSManagedObjectContext来得到被储存内容的文件管理器,对数据作直接操作
NSPersistentStoreCoordinator来管理数据的储存位置,储存方法(SQLite)
你对Core Data理解更多了么?
CoreData实例分析学习(1)补
2009年08月13日, 11:11 下午
原来简单解释过属性定义(Property) ,并且提起了简单的retain,copy,assign的区别。那究竟是有什么区别呢?
assign就不用说了,因为基本上是为简单数据类型准备的,而不是NS对象们。
Retain vs. Copy!!
- copy: 建立一个索引计数为1的对象,然后释放旧对象
- retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
那上面的是什么该死的意思呢?
Copy其实是建立了一个相同的对象,而retain不是:
比如一个NSString对象,地址为0×1111,内容为@”STR”
Copy到另外一个NSString之后,地址为0×2222,内容相同,新的对象retain为1,旧有对象没有变化
retain到另外一个NSString之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1
也就是说,retain是指针拷贝,copy是内容拷贝。哇,比想象的简单多了…
2009年08月12日, 7:49 下午
字符串是程序设计最常用的数据类型之一了。在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的愉快~
2009年08月1日, 6:35 下午
JSON我就不多解释了,需要更多信息的朋友请到json.org上查看。
在iPhone上访问网络内容是很必须的,而一些数据就需要以某种形式储存在web服务器上。比如一个app的目录,内容,索引等等。而xml和json,plist都是比较方便的方式。
-XML在iPhone上是非常好用的,但是对复杂的数据结构使用上就不那么方便了,具体可以参阅苹果的“基于事件的XML”和“基于树的XML”编程向导
-plist是再方便不过了,不过我看最多也就是一个NSDictionary而已,复杂一些的话,数据输入上也会非常非常的麻烦。
-JSON本来是不被苹果支持的,但是有人很Nice的帮我们解决了这个问题:JSON for OBJC http://code.google.com/p/json-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的键值结构信息咯~!!!
2009年08月1日, 2:48 下午
V 在Mac上可以简单的使用一个内建API进行文字读取朗读。很可惜不支持中文…
@interface AppController : NSObject
{
NSSpeechSynthesizer *speechSyn; //创建语音合成器对象
}
//初始化对象
speechSyn = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
//然后就可以直接让这个合成器读取任何NSString了,是不是太简单了?
[speechSyn startSpeakingString:@"This is what I gonna read"];
最后,别忘了release掉它阿~
2009年07月13日, 12:41 下午
N 以下是一个非常简单的视频播放代码,并且可以简单的理解Cocoa中的通告使用方法。
- (void)playMovieAtURL:(NSURL*)theURL //简单的方法,传入一个视频地址
{
MPMoviePlayerController *thePlayer = [[MPMoviePlayerController alloc]
initWithContentURL:theURL]; //初始化播放器
thePlayer.scalingMode = MPMovieScalingModeAspectFill; //下面有详细的缩放解释
//thePlayer.userCanShowTransportConstrols = NO; 这个是苹果文档上的原始代码,是错的...
thePlayer.movieControlMode = MPMovieControlModeDefault; //缺省视频控制
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(myMovieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification thePlayer];
//注册本地类为thePlayer的通告对象,通告方法为“视频播放结束”,
//回应方法为myMovieFinishedCallback
//也就是说,当视频播放结束以后,运行该方法
[thePlayer play]; //播放!
}
- (void)myMovieFinishedCallback:(NSNotification*)aNotification
{
MPMoviePlayerController *thePlayer = [aNotification object];
//从通告中导入这个播放器对象,如果播放器是单独的类成员,那就不用这步咯。
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
thePlayer];
//这步非常非常重要,一定要将被监听对象卸载,
//否则本地对象卸载后,监听对象为nil,软件会崩溃的
[thePlayer release]; //释放视频对象
}
scalingMode缩放模式的四种参数:
-MPMovieScalingModeNone
-不对视频进行缩放
-MPMovieScalingModeAspectFit
-视频缩放到内框,4比3的视频会在左右留下黑框
-MPMovieScalingModeAspectFill
-视频缩放到外框,4比3的视频上下会被削掉一部分
-MPMovieScalingModeFill
-视频被拉伸,失去原始比例
2009年06月24日, 7:52 下午
A 对应64位编程的时候,
对于整数应使用NSInteger和NSUInteger,而非int
对于小数应使用CGFloat,而非float
NSInteger其实是一个自动定义,在32位中为int,而64位中为long。CGFloat的原理类似