原文地址:http://hi.baidu.com/douxinchun/blog/item/e5d385171dfe6304962b43c9.html
objective-c与C++的区别
Objective-C,是在C的基础上,加入面向对象特性扩充而成的编程语言。Objective-C主要应用于Mac OS X和iOS 系统,可以在任何gcc支持的平台上进行编译,因为gcc原生支持Objective-C。
程序例子:
#import<Foundation/Foundation.h>
int main(int argc, char *argv[]){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Hello World!");
[pool drain]; //清空自动释放池,但是没有立即释放。[pool release]释放自动释放池。
return 0;
}
--
C++ 是在C基础上加了class 等新东西而成的编程语言,可以把C看成是C++的一部分。可以用它写面向对象的程序,也可以写以过程为主的程序。C++ 已得到广泛(远比objective-c广泛)应用,用于各种平台。
--
Objective-C 不用“函数调用”,而用互相传递讯息。
Objective-C 类分为Interface和implementation两块。
Objective-C 构建对象 分为两块 alloc (内存分配)以及init(初始化)
Objective-C 协议分为非正式协议和正式协议
与C语言相比要注意的地方
objective-c高级特性
开发工具介绍(cocoa 工具包的功能,框架,源文件组织;XCode使用介绍)
简介:
1. objective-c是C语言的一个扩展集,主要由APPLE公司维护,是MAC系统下的主要开发语言。个人认为,对于用惯了常用的C,JAVA等语言的人来说,objective-c是一中很另类,非主流的语言。
2. 开发 Mac的 UI 程序来说,使用的是 Cocoa 这个框架,cocoa的组成部分有:foundation和application kit框架。
【foundation框架处理用户界面之下的特性,如数据结构和通信机制;application kit框架包含cocoa的高级特性:用户界面元素,打印,颜色,声音管理,applescript等】
与C语言相比要注意的地方:
1. 文件介绍:Objective-C 也使用头文件(header files),后缀为 .h, 但使用 .m(即 message, 其他面向对象编程语言也叫 method),作为源文件的后缀。
在objective-c中使用#import<>,而不使用#include<>,#import可以保证头文件只被包含一次。
2. 与C一致的地方:
数据类型,表达式,各种运算符
循环:for, while, do while, break, continue
分支:if, else, switch
3. NSlog()函数:与printf()类似,想控制台输出信息。但它增加了一些特性,如时间戳等。
【cocoa对起所有的函数,常量和类型名称都添加了NS前缀。】
4. 双引号的前面的@表示这双引号中的字符串应该作为cocoa的NSString元素来处理。
5. 布尔类型BOOL:值为YES,NO;
6. %d表示输出整数
%@表示输出NSString类型
%s表示输出字符串数组(char*);
7. objective-c中的方括号:
1. 用于通知某个对象该做什么。
2. 方括号内第一项是对象,其余部分是你需要对象执行的操作。
3. 在objective-c中通知对象执行某种操作,称为发送消息。(也叫调用方法)
8. 标识符id:是一种泛型,用于表示任何种类的对象。
9. 类声明@interface:
@interface Circle:NSObject //为Circle类定义接口;NSObject表示是父类。
{//以下是数据成员
ShapeColor fillColor;
ShapeRect bounds;
}
//以下是方法声明
-(void) setFillColor: (ShapeColor) fillColor; //前面的短线表明这是方法声明
//短线后面是方法的返回类型
//接着是方法名
//冒号后面是参数,其中(ShapeColor)是参数类型,
fillColor是参数名
-(void) setBounds:(ShapeRect) bounds;
-(void) draw;
//减号就是普通函数
加号就是静态函数
@end //结束声明
objective-c看到@符号,就把它看成是C语言的扩展。
一个类的完整声明如下:
@interface CClassA(Category): CBaseClass<IA,IB...>
//类名(类别名):父类<协议>
10. 类实现@implementation
@implementation
@implementation Circle
-(void) setFillColor: (ShapeColor) c
{
fillColor=c;
}
-(void) draw
{
NSLog(@”drawing a circle at(%d %d %d %d) in %@”, bounds.x,bounds.y,bounds.width,bounds.height,colorName(fillName));
}
@end
隐藏对象self对应于C中的this。
Self->fillcolor来访问成员变量。
11. 调用写好的类和类函数:
//创建新对象,使用缺省初始化函数
Bank *bankDefault = [[Bank alloc] init];
//调用方法:
[bank addAmount: 1];
[bank print];
// 释放对象:
[bankDefault free];
12.
两个参数的方法:
-(void) setTire: (Tire *) tire //声明
atIndex: (int) index;
//使用
[car setTire:tire atIndex:2];
objective-c高级特性:
1. 继承
Objective-c不支持多继承。
Super 关键字:调用该类的父类;
超类:父类的另一种说法。
2.
自定义NSLog()输出:
在类中添加description方法就可以自定义NSLog()如何输出对象。
@implementation Tire
-(NSString *) description
{
Return (@”I am a tire.”);
}
Main()
{
NSLog(@”%@”,tire[0]);
}
3.
Foundation kit:
Cocoa是由两部分框架组成的:foundation kit [包括一些基础类]和 application kit.【包括用户接口对象和高级类】
创建字符串:
NSString *test;
test=[NSString stringWithFormat:@"i'm %d years old!",23];
若在声明方法时在方法前面添加了加号,那就表示把这个方法定义为类方法【这个方法属于类对象,而不是类的实例对象。】
NSArray类:可以存放任意类型的对象.
它有两个限制:
1. 它只能存储objective-c的对象,但不能存储C中的基本数据类型,如int , float, enum, struct等。
2.不能存储nil(对象的零值或NULL值);【因为在创建NSArray时,要在列表结尾添加nil代表列表结束。】
创建NSArray:
NSArray *array;
array=[NSArray arrayWithObjects:@"one",@"two",nil];
NSString, NSMutableString类;
【NSString是不可变的,即一旦创建完成,就不能通过删除字符或添加字符的方式来改变它;
而NSMutableString是可变的。
这两个类就像JAVA中的string与stringBuffer类的区别。】
NSArray, NSMutableArray类;
NSEnumerator枚举;
【
NSEnumerator *emun;
Emun=[array objectEnumerator];
Id thingie;
While(thingie=[enumerator nextObject]){}
】
NSDictionary:字典(关键字及其定义的集合。)【也成为散列表,关联数组】,NSMutableDictionary类;
NSNumber:用来包装基本数据类型,如int ,char, float, bool;【将一个基本类型的数据包装成对象叫做装箱。】
NSValue:它可以包装任何类,NSNumber是它的子类。
NSNull:
在cocoa中看到“CF”字样时,就表示它是苹果公司的Core Foundation 框架相关的内容。
NSAutoreleasePool:自动释放内存池。
4.
内存管理
每个对象都有一个与之关联的引用计数(也叫保留计数)
当使用alloc, new 方法或通过 copy消息(生成接收对象的一个副本)创建一个对象时,对象的引用计数值被设为1;
给对象发retain消息时,增加该值;
发送release消息时,减少该值;
当一个对象的引用计数值变为0时,objective-c会自动向对象发送一条dealloc消息。销毁该对象。
你可以在自己的对象中重写该方法,
使用retainCount消息,可以获取引用计数器的值。
-(id) retain;
-(void) release;
-(unsigned) retainCount;
自动释放池:autorelease pool;
创建:
NSAutoreleasePool *pool;
pool=[[NSAutoreleasePool alloc] init];
销毁:
[pool release];
注意:xcode自动生成的代码,销毁pool池时,使用的是[pool drain],drain方法只是清空释放池,但不销毁pool.所以在自己编写代码时还是使用release.
而且,drain只适用于MAC OS 10.4以上的版本,而release适用于所有版本。
只有在向某个对象发送autorelease消息时,该对象才会添加到NSAutoreleasepool中,才会被自动释放。
如:[car autorelease];
内存管理黄金准则:
只有通过alloc, new和 copy方法创建的对象,才需要程序员负责向该对象发送release或autorelease消息。
而通过其他方法获得的对象,则默认为已经被设置为自动释放,所以不需要程序员做任何操作了。
在objective-c 2.0中有垃圾回收机制,
如果要对某个项目使用垃圾回收:
项目信息--build选项卡--查询"garb",出现“objective-c Garbage Collection”,将其值设置为“required[-fobjc-gc-only]”
启用垃圾回收后,通常的内存管理命令全都变成了空操作指令,不执行任何操作。
开发iphone软件,不能使用垃圾回收。
5.
对象初始化
两种创建新对象的方法:
[类名 new]
[[类名 alloc] init]
这两种方法是等价的,但cocoa的惯例是使用后者。
alloc在为对象分配空间的同时,将这块内存初始化为0;
Init方法:初始化实例变量,使对象处于可用状态。[返回类型为id, 返回的值描述了被初始化的对象]
使用new创建新对象时,系统要完成两个步骤:
1). 为对象分配内存,即对象获得一个用来存放其实例变量的内存块;
2). 自动调用init方法,让该对象处于可用状态。
6.
objective-c 2.0的新特性【只适用于mac os x10.5及以上】
@property :表示声明了对象的属性。【这样就不用再写属性的访问器了。】
(他有copy, retain, readwrite, readonly等属性)
@synthesize:表示“创建该属性的访问器”
点表达式
7.
类别
类别(category)是一种为现有的类添加新方法的方式。
类别的声明:
@interface NSString (NumberConvenience) //类名 (类别名)
-(NSNumber) lengthAsNumber; //扩充方法声明
@end
使用时使用原来的类名,就可以调用他的所有类别中的方法。
类别的局限性:
1. 不能向类中添加新的实例变量;
2. 在类别中的方法若与类中现有的方法重名,则类中的方法不可用,被类别中的新方法取代。
类别的作用:
1. 将类的实现分散到多个文件或框架中;
2. 创建对私有方法的前向引用;
【Cocoa中没有真正的私有方法,则实现私有方法类似功能的方法为:
先在类别中声明方法;然后到现有类的实现中实现该方法。
这样这个类中的其他方法可以使用该方法,而其他外部的类就不会知道该方法的存在了。】
3. 向对象添加非正式协议。
【创建一个NSObject的类别称为创建一个非正式协议。】
委托delegate是一种对象,另一个类的对象会要求委托对象执行它的某些操作。
受委托对象在某个时间(某个事件触发)时,会自动通知委托对象执行委托方法。
选择器:@selector():选择器只是一个方法名称,但它以objective-c运行时使用的特殊方式编码,以快速执行查询。圆括号中的内容是方法名。
所以Car类的setEngine:方法的选择器是:@selector(setEngine:
受委托对象如何知道其委托对象是否能处理它(受委托对象)发送给它(委托对象)的消息?
通过选择器,受委托对象先检查委托对象,询问其是否能响应该选择器。如果能,则向它发送消息。
8.
协议:
正式协议是一个命名的方法列表。
采用协议意味着必须实现该协议的所有方法。否则,编译器会发出警告。
正式协议就像JAVA中的接口一样。
声明协议:
@protocal NSCopying
-(id) copywithzone:(NSZone *) zone; //方法列表
@end
采用协议:
@interface Car:NSObject <NSCopying,NSCoding> //中括号中是要实现的协议列表
{//实例变量列表}
//方法列表
@end
在objective-c 2.0中,有新特性:@optional, @required
9.
AppKit:
创建APPKIT项目:
File—new project—mac os—application—Cocoa application;
IBOutlet与IBAction
这两个都是APPKIT提供的#defines.
IBOutlet没有任何作用,不会对它进行编译。
IBAction定义为void。
这两个是为Interface Builder以及阅读代码的人提供的标记。
.xib文件一般称为.nib文件。
.nib文件是包含被冻结对象的二进制文件。
而.xib文件是XML格式的nib文件。
很多人对String和StringBuffer的区别已经很了解了吧,可能还有人对这两个类的工作原理有些不清楚的地方,复习一下吧,顺便牵出J2SE 5.0里面带来的一个新的字符操作的类StringBuilder。那么这个StringBuilder和StringBuffer 以及我们最早遇见的 String 类有那些区别呢?在不同的场合下我们应该用哪个呢?我讲讲自己对这几个类的一点看法,也希望大家提出意见。
简要的说,String类型和StringBuffer类型的主要性能区别其实在于 String 是不可变的对象,因此在每次对String类型进行改变的时候其实都等同于生成了一个新的 String对象,然后将指针指向新的String对象,所以经常改变内容的字符串最好不要用 String,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的GC就会开始工作,那速度是一定会相当慢的。这里尝试举个不是很恰当的例子:
String Str = “abc”;
For(int i = 0 ; i < 10000 ; i++)
{
Str + = “def”;
}
如果是这样的话,到这个 for 循环完毕后,如果内存中的对象没有被 GC 清理掉的话,内存中一共有上万个了,惊人的数目,而如果这是一个很多人使用的系统,这样的数目就不算很多了,所以大家使用的时候一定要小心。
而如果是使用StringBuffer类则结果就不一样了,每次结果都会对StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer,特别是字符串对象经常改变的情况下。而在某些特别情况下,String 对象的字符串拼接其实是被 JVM 解释成了StringBuffer对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
String Str = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
你会很惊讶的发现,生成 String Str 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个
String Str = “This is only a” + “ simple” + “test”; 其实就是:
String Str = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:
String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;
这时候 JVM 会规规矩矩的按照原来的方式去做, S1 对象的生成速度就不像刚才那么快了,一会儿我们可以来个测试作个验证。
由此我们得到第一步结论:
在大部分情况下 StringBuffer > String
而 StringBuilder 跟他们比又怎么样呢?先简单介绍一下, StringBuilder 是 JDK5.0 中新增加的一个类,它跟 StringBuffer 的区别看下面的介绍:
Java.lang.StringBuffer线程安全的可变字符序列。类似于 String 的字符串缓冲区,但不能修改。可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5.0 开始,为该类增添了一个单个线程使用的等价类,即 StringBuilder 。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
但是如果将 StringBuilder 的实例用于多个线程是不安全的。需要这样的同步,则建议使用 StringBuffer 。
那么下面我们再做一个一般性推导:
在大部分情况下 StringBuilder > StringBuffer
因此,根据这个不等式的传递定理: 在大部分情况下
StringBuilder > StringBuffer > String
====================================================================
String是一个类,但却是不可变的,所以String创建的算是一个字符串常量,StringBuffer和StringBuilder都是可变的。所以每次修改String对象的值都是新建一个对象再指向这个对象。而使用StringBuffer则是对StringBuffer对象本身进行操作。所以在字符串j经常改变的情况下,使用StringBuffer要快得多。
但在某些情况下:
Java代码
String S1 = “Who” + “ is” + “ faster?”;
StringBuffer Stb = new StringBuilder(“Who”).append(“ is”).append(“ faster?”);
Java代码
String S1 = “Who” + “ is” + “ faster?”;
StringBuffer Stb = new StringBuilder(“Who”).append(“ is”).append(“ faster?”);
String S1 = “Who” + “ is” + “ faster?”;
StringBuffer Stb = new StringBuilder(“Who”).append(“ is”).append(“ faster?”);S1的素对会比Stb快得多, 是因为JVM把String对象的拼接解释成了StringBuffer对象的拼接,其实在JVM就是:
Java代码
String S1="Who is faster?";
Java代码
String S1="Who is faster?";
String S1="Who is faster?";
不过如果,字符串是来自其他对象,如:
Java代码
String s1="Who";
String s2=" is";
String s3=" faster?";
String st=s1+s2+s3;
Java代码
String s1="Who";
String s2=" is";
String s3=" faster?";
String st=s1+s2+s3;
String s1="Who";
String s2=" is";
String s3=" faster?";
String st=s1+s2+s3;
这个时候,String的速度就比不上StringBuffer了。
StringBuffer和StringBuilder
在操作字符串对象,StringBuiler是最快的,StringBuffer次之,String最慢。
Java代码
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
ublic final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
Java代码
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
ublic final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
可以看到StringBuffer和StringBuilder都继承继承了同一个抽象类。
Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步, StringBuilder的速度比StringBuffer快。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。两者的方法基本相同。
如果要多次操作字符串,使用StringBuffer和StringBuilder会提高效率,但至少在数量级超过百万时,StringBuilder的速度才会体现出来。
1. iOS开发中使用[[UIApplication sharedApplication] openURL:] 加载其它应用
在iOS开发中,经常需要调用其它App,如拨打电话、发送邮件等。UIApplication:openURL:方法是实现这一目的的最简单方法,该方法一般通过提供的url参数的模式来调用不同的App。
通过openURL方法可以调用如下应用:
调用浏览器(Safari Browser)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http:google.com"]];
调用谷歌地图(Google Maps)
NSString *addressText = @"7 Hanover Square, New York, NY 10004"; addressText = [addressText stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding]; NSString* urlText = [NSString stringWithFormat:@"http://maps.google.com/maps?q=%@", addressText]; [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlText]];
调用邮件客户端(Apple Mail)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://devprograms@apple.com"]];
拨号(Phone Number)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://6463777303"]];
调用短信(SMS)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://466453"]];
调用应用商店(AppStore)
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=291586600&amp;mt=8"]];
2. NSUserDefaults读取和写入自定义对象
NSString *string = [NSString stringWithString @"data is here"]; NSUserDefaults *data = [NSUserDefaults standardUserDefaults]; [data setObject:string forKey:@"key"]; NSString *value; value = [data objectForKey:"key"];
但是并不是所有的东西都能往里放的。NSUserDefaults只支持: NSString, NSNumber, NSDate, NSArray, NSDictionary.
3. protocol 和 delegate 回调函数传值
一、说明
1.协议声明了可以被任何类实现的方法
2.协议不是类,它是定义了一个其他对象可以实现的接口
3.如果在某个类中实现了协议中的某个方法,也就是这个类实现了那个协议。
4.协议经常用来实现委托对象。一个委托对象是一种用来协同或者代表其他对象的特殊对象。
5:委托,就是调用自己定义方法,别的类来实现。
6.新特性说明
@optional预编译指令:表示可以选择实现的方法
@required预编译指令:表示必须强制实现的方法
二、定义
.h
@protocol ContactCtrlDelegate - (void)DismissContactsCtrl; - (void)CallBack:(NSString *)str; //回调传值 @end @interface ContactsCtrl : UIViewController { id <ContactCtrlDelegate> delegate; } @property (nonatomic, assign) id <ContactCtrlDelegate> delegate;
.m
@synthesize delegate;
三、Demo
二级窗口(子窗口)UIViewController subclass
- 1 Textfield
- 1 Button
1、ContactsCtrl.h
#import <UIKit/UIKit.h> //定义协议 @protocol ContactCtrlDelegate - (void)DismissContactsCtrl; //回调关闭窗口 - (void)CallBack:(NSString *)str; //回调传值 @end @interface ContactsCtrl : UIViewController { __weak IBOutlet UITextField *passData; //textfield id <ContactCtrlDelegate> delegate; //开放delegate NSString *passedVal; //从主窗口获取传值 } @property(nonatomic,retain)id <ContactCtrlDelegate> delegate; @property(nonatomic,retain)NSString *passedVal; - (IBAction)cancelBtn:(id)sender; @end
2、ContactsCtrl.m
@implementation ContactsCtrl @synthesize delegate; @synthesize passedVal; - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. passData.text = passedVal; } //调用协议中的方法 - (IBAction)cancelBtn:(id)sender { [delegate CallBack:[NSString stringWithFormat:@"%@",passData.text]]; [delegate DismissContactsCtrl]; }
一级窗口(父窗口)
- 1 Textfield
- 1 Button
3、ViewController.h
#import <UIKit/UIKit.h> #import "ContactsCtrl.h" //引入二级文件 @interface ViewController : UIViewController <ContactCtrlDelegate> { ContactsCtrl *contactsView; //定义 __weak IBOutlet UITextField *textfield; } @property(nonatomic,retain) ContactsCtrl *contactsView; - (IBAction)addContactsView:(id)sender; @end
4、ViewController.m
#import "ViewController.h" @implementation ViewController @synthesize contactsView; - (IBAction)addContactsView:(id)sender { ContactsCtrl *contactView = [[ContactsCtrl alloc] initWithNibName:nil bundle:nil]; self.contactsView = contactView; contactsView.delegate = self; //设置委托 contactsView.passedVal = textfield.text; [self presentModalViewController:contactsView animated:YES]; } //实现ContactCtrlDelegate协议中的方法 - (void)DismissContactsCtrl { [contactsView dismissModalViewControllerAnimated:YES]; } - (void)CallBack:(NSString *)str { textfield.text = str; }
本实例是在:http://www.codeios.com/blog-21-13.html 基础上修改而成。
参考:delegate和protocol