learn objetive-c
Objective-C
Objective-C is the primary language used to write Mac software. If you're comfortable with basic object-oriented concepts and the C language, Objective-C will make a lot of sense. If you don't know C, you should read the C Tutorial first.
objective-c 是用于开发mac软件的主要语言。如果你熟悉面向对象思想和c语言,那么objective-c将简单。如果你没学过c,那你应该先去看下c的教程。
Copyright © 2008 Scott Stevenson
1
Calling Methods
To get started as quickly as possible, let's look at some simple examples. The basic syntax for calling a method on an object is this:
为了能够更快的上手,让我们先来看一些简单的例子吧。下面的基本的对象调用函数方法:
[object method];
[object methodWithInput:input];
Methods can return a value:
将返回一个值:
output = [object methodWithOutput];
output = [object methodWithInputAndOutput:input];
You can call methods on classes too, which is how you create objects. In the example below, we call the string method on the NSString class, which returns a new NSString object:
你也可以使用类直接调用方法。实际如在NSString类中直接调用string方法,返回一个NSString的对象:
id myObject = [NSString string];
The id type means that the myObject variable can refer to any kind of object, so the actual class and the methods it implements aren't known when you compile the app.
id类型表示myobject变量能够是任意类型,所以事实上在编译的时候系统并不知道其是什么类型。
在这个例子中,我们可以知道该类型是NSString,所以我们可以改为:
In this example, it's obvious the object type will be an NSString, so we can change the type:
NSString* myString = [NSString string];
This is now an NSString variable, so the compiler will warn us if we try to use a method on this object which NSString doesn't support.
表明是NSSting类型后,如果我们调用了一个NSString没有的方法编译的时候将会直接收到警告。
请注意的是关于对象类型,所有的objective-c对象都是指针类型。Id已被预定义为了一个指针类型,所以并没有警告提示。
Notice that there's a asterisk to the right of the object type. All Objective-C object variables are pointers types. The id type is predefined as a pointer type, so there's no need to add the asterisk.
Nested Messages(内部消息)
In many languages, nested method or function calls look like this:
在许多语言中,内部方法或函数的调用通常像下面这样:
function1 ( function2() );
The result of function2 is passed as input to function1. In Objective-C, nested messages look like this:
方法2的结果将作为参数输入到方法1中。而在objective-c中,内部方法调用如下:
[NSString stringWithFormat:[prefs format]];
Avoid nested nesting more than two message calls on a single line, as it easily gets unreadable.
尽量避免在一行中循环嵌套调用超过2个方法,否则将很难阅读。
Multi-Input Methods
Some methods take multiple input values. In Objective-C, a method name can be split up into several segments. In the header, a multi-input method looks like this:
一些方法需要输入多个参数。在objective-c中,一个方法名被拆分成几部分。在header中,方法定义如下:
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
You call the method like this:
你可以这样调用:
BOOL result = [myData writeToFile:@"/tmp/log.txt" atomically:NO];
These are not just named arguments. The method name is actuallywriteToFile:atomically: in the runtime system.
并不仅仅通过方法名字区分,在系统运行时实际上存在的是writeToFile:atomically:
Accessors(访问器)
All instance variables are private in Objective-C by default, so you should use accessors to get and set values in most cases. There are two syntaxes. This is the traditional 1.x syntax:
在objective-c中所有的实例变量默认都是private的,所以你需要使用访问控制去get set变量。
[photo setCaption:@"Day at the Beach"];
output = [photo caption];
The code on the second line is not reading the instance variable directly. It's actually calling a method named caption. In most cases, you don't add the "get" prefix to getters in Objective-C.
在上面第二行代码中不是直接读取变量。实际上是调用了一个名字为caption的方法。通常情况下你使用getter的时候无需添加get在变量前。无论你如何理解方括号里面的内容,都是调用了一个对象或类的方法。
Whenever you see code inside square brackets, you are sending a message to an object or a class.
Dot Syntax
The dot syntax for getters and setters is new in Objective-C 2.0, which is part of Mac OS X 10.5:
作为mac os x10.5的一部分,新的objective-c2.0中有了点存取语法,如:
photo.caption = @"Day at the Beach";
output = photo.caption;
You can use either style, but choose only one for each project. The dot syntax should only be used setters and getters, not for general purpose methods.
你可以使用其中任何一种风格,但最好只选一种。
3
Creating Objects
There are two main ways to create an object. The first is the one you saw before:
有两种创建对象的方法。一种就是前面的你看到的:
NSString* myString = [NSString string];
This is the more convenient automatic style. In this case, you are creating an autoreleased object, which we'll look at in more detail later. In many cases, though, you need to create an object using the manual style:
这是一种很方便的风格。在这种方法下,对象能够自动释放,后面我们将会详细介绍。然而在更多的情况下,我们需要手动创建一个对象:
NSString* myString = [[NSString alloc] init];
This is a nested method call. The first is the alloc method called on NSString itself. This is a relatively low-level call which reserves memory and instantiates an object.
通过了一个内部方法的调用。首先是调用NSString本身的alloc方法,该方法时底层用于开辟内存和实例化对象用的。
The second piece is a call to init on the new object. The init implementation usually does basic setup, such as creating instance variables. The details of that are unknown to you as a client of the class.
第二是用新生成的object调用了init方法。Init常用于基本的初始化,比如创建一些常量。有些情况下,你可以使用不同的init进行初始化。
In some cases, you may use a different version of init which takes input:
NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];
4
Basic Memory Management(基本的内存管理)
If you're writing an application for Mac OS X, you have the option to enable garbage collection. In general, this means that you don't have to think about memory management until you get to more complex cases.
如果你在写mac os x应用,你就应该选择实现垃圾回收。通常情况下,如果你开发一个要求不高的应用时,无需自行考虑内存管理。然而,你并不会总在一个支持垃圾回收的应用开发环境下工作。有些情况下,你必须理解基本的内存管理。
However, you may not always be working with an environment that supports garbage collection. In that case, you need to know a few basic concepts.
If you create an object using the manual alloc style, you need to releasethe object later. You should not manually release an autoreleased object because your application will crash if you do.
如果你使用alloc创建了一个对象,你就需要在后面自行release掉它。你不能够手动release掉一个声明为autoreleased的对象,否则你的应用将会崩溃。
Here are two examples:
看下面两个例子:
// string1 will be released automatically
NSString* string1 = [NSString string];
// must release this when done
NSString* string2 = [[NSString alloc] init];
[string2 release];
For this tutorial, you can assume that an automatic object will go away at the end of the current function.
There's more to learn about memory management, but it will make more sense after we look at a few more concepts.
5
Designing a Class Interface
The Objective-C syntax for creating a class is very simple. It typically comes in two parts.
创建一个类是比较简单的。通常需要两步。一个是使用.h文件存放变量和公有方法。使用.m文件实现这些公有方法。也用来定义一些private内部方法。
The class interface is usually stored in the ClassName.hfile, and defines instance variables and public methods.
The implementation is in the ClassName.m file and contains the actual code for these methods. It also often defines private methods that aren't available to clients of the class.
下面是一个photo的接口.h
Here's what an interface file looks like. The class is called Photo, so the file is named Photo.h:
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
@end
First, we import Cocoa.h, to pull in all of the basic classes for a Cocoa app. The #import directive automatically guards against including a single file multiple times.
首先,我们导入了cocoa.h。该文件声明了一个photo类,继承自NSObject类型。定义了两个变量caption和photographer。最后,我们使用@end结束声明。
The @interface says that this is a declaration of the class Photo. The colon specifies the superclass, which is NSObject.
Inside the curly brackets, there are two instance variables: caption andphotographer. Both are NSStrings, but they could be any object type, including id.
Finally, the @end symbol ends the class declaration.
Add Methods
Let's add some getters for the instance variables:
让我们先为变量添加getter和setter方法:
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- caption;
- photographer;
@end
Remember, Objective-C methods typically leave out the "get" prefix. A single dash before a method name means it's a instance method. A plus before a method name means it's a class method.
By default, the compiler assumes a method returns an id object, and that all input values are id. The above code is technically correct, but it's unusual. Let's add specific types for the return values:
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- (NSString*) caption;
- (NSString*) photographer;
@end
Now let's add setters:
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- (NSString*) caption;
- (NSString*) photographer;
- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;
@end
Setters don't need to return a value, so we just specify them as void.
Class Implementation
Let's create an implementation, starting with the getters:
让我们来实现方法:
#import "Photo.h"
@implementation Photo
- (NSString*) caption {
return caption;
}
- (NSString*) photographer {
return photographer;
}
@end
This part of the code starts with @implementation and the class name, and has @end, just like the interface. All methods must appear between these two statements.
The getters should look very familiar if you've ever written code, so let's move on to the setters, which need a bit more explanation:
- (void) setCaption: (NSString*)input
{
[caption autorelease];
caption = [input retain];
}
- (void) setPhotographer: (NSString*)input
{
[photographer autorelease];
photographer = [input retain];
}
Each setter deals with two variables. The first is a reference to the existing object, and the second is the new input object. In a garbage collected environment, we could just set the new value directly:
- (void) setCaption: (NSString*)input {
caption = input;
}
But if you can't use garbage collection, you need to release the old object, and retain the new one.
There are actually two ways to free a reference to an object: release andautorelease. The standard release will remove the reference immediately. The autorelease method will release it sometime soon, but it will definitely stay around until the end of the current function (unless you add custom code to specifically change this).
The autorelease method is safer inside a setter because the variables for the new and old values could point to the same object. You wouldn't want to immediately release an object which you're about to retain.
This may seem confusing right now, but it will make more sense as you progress. You don't need to understand it all yet.
Init
We can create an init method to set inital values for our instance variables:
重写init方法:
- (id) init
{
if ( self = [super init] )
{
[self setCaption:@"Default Caption"];
[self setPhotographer:@"Default Photographer"];
}
return self;
}
This is fairly self-explanatory, though the second line may look a bit unusual. This is a single equals sign, which assigns the result of [super init] to self.
This essentially just asks the superclass to do its own initialization. The if statement is verifying that the initialization was successful before trying to set default values.
Dealloc
The dealloc method is called on an object when it is being removed from memory. This is usually the best time to release references to all of your child instance variables:
重写dealloc方法
- (void) dealloc
{
[caption release];
[photographer release];
[super dealloc];
}
On the first two lines, we just send release to each of the instance variables. We don't need to use autorelease here, and the standard release is a bit faster.
The last line is very important. We have to send the message
[super dealloc] to ask the superclass to do its cleanup. If we don't do this, the object will not be removed, which is a memory leak.
The dealloc method is not called on objects if garbage collection is enabled. Instead, you implement the finalize method.
More on Memory Management(更多的内存管理)
Objective-C's memory management system is called reference counting. All you have to do is keep track of your references, and the runtime does the actual freeing of memory.
objective-c的内存管理使用的是引用计数。你必须维护你的引用栈,并在运行时自行释放内存。
In simplest terms, you alloc an object, maybe retain it at some point, then send one release for each alloc/retain you sent. So if you used alloc once and then retain once, you need to release twice.
比如说,你alloc了一个对象,或许也retain了他,然后你需要去release掉每一个你alloc/retain的对象。如果你使用alloc和retain各一次,那你必须release2次。
That's the theory of reference counting. But in practice, there are usually only two reasons to create an object:
只有两种情况你需要去创建一个对象:
- 保证其是一个可用常量
- 在方法里单独使用
1. To keep it as an instance variable
2. To use temporarily for single use inside a functionIn most cases, the setter for an instance variable should justautorelease the old object, and retain the new one. You then just make sure to release it in dealloc as well.
通常,setter一个变量的同时需要去autorelease一个旧对象,和retain新的对象。你需要保证在dealloc的时候释放它。
So the only real work is managing local references inside a function. And there's only one rule: if you create an object with alloc or copy, send it a release or autorelease message at the end of the function. If you create an object any other way, do nothing.Here's the first case, managing an instance variable:
- (void) setTotalAmount: (NSNumber*)input
{
[totalAmount autorelease];
totalAmount = [input retain];
}
- (void) dealloc
{
[totalAmount release];
[super dealloc];
}
Here's the other case, local references. We only need to release the object created with alloc:
NSNumber* value1 = [[NSNumber alloc] initWithFloat:8.75];
NSNumber* value2 = [NSNumber numberWithFloat:14.78];
// only release value1, not value2
[value1 release];
And here's a combo: using a local reference to set an object as an instance variable:
NSNumber* value1 = [[NSNumber alloc] initWithFloat:8.75];
[self setTotal:value1];
NSNumber* value2 = [NSNumber numberWithFloat:14.78];
[self setTotal:value2];
[value1 release];
Notice how the rules for managing local references are exactly the same, regardless of whether you're setting them as instance variables or not. You don't need to think about how the setters are implemented.
If you understand this, you understand 90% of what you will ever need to know about Objective-C memory management.
learn objetive-c的更多相关文章
- Atitit learn by need 需要的时候学与预先学习知识图谱路线图
Atitit learn by need 需要的时候学与预先学习知识图谱路线图 1. 体系化是什么 架构 知识图谱路线图思维导图的重要性11.1. 体系就是架构21.2. 只见树木不见森林21.3. ...
- Python 爬取所有51VOA网站的Learn a words文本及mp3音频
Python 爬取所有51VOA网站的Learn a words文本及mp3音频 #!/usr/bin/env python # -*- coding: utf-8 -*- #Python 爬取所有5 ...
- [转载]VIM 教程:Learn Vim Progressively
文章来源:http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/ Learn Vim Progressively TL ...
- some tips learn from work experience
1.you can't avoid office politics 2.you'll never have a job which you "can't quit" - if yo ...
- Java-集合(没做出来)第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列。 例如: List list = new ArrayList(); list.add(“Hello”); list.add(“World”); list.add(“Learn”); //此时list 为Hello World Learn reverseL
没做出来 第四题 (List)写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列. 例如: List list = new ArrayList(); list.a ...
- Learn RxJava
Learn RxJava http://reactivex.io/documentation/operators.html https://github.com/ReactiveX/RxJava/wi ...
- ANSI Common Lisp Learn
It has been a long time that I haven't dealt with my blog. On one hand I was preparing the exams.On ...
- [Notes] Learn Python2.7 From Python Tutorial
I have planed to learn Python for many times. I have started to learn Python for many times . Howeve ...
- 十分钟入门less(翻译自:Learn lESS in 10 Minutes(or less))
十分钟入门less(翻译自:Learn lESS in 10 Minutes(or less)) 注:本文为翻译文章,因翻译水平有限,难免有缺漏不足之处,可查看原文. 我们知道写css代码是非常枯燥的 ...
- Learning How To Learn
1.Practice 2.memory every week for from working memory to long tern memory 3.sleep 4.running promote ...
随机推荐
- Asp.Net实现FORM认证的一些使用技巧
原文转发:http://www.cnblogs.com/Showshare/archive/2010/07/09/1772886.html 最近因为项目代码重构需要重新整理用户登录和权限控制的部分,现 ...
- maven_修改setting ,改为自己私服或者OSC开源中国 [为解决sqlite-jdbc 在中央仓库找不到]
因为项目要使用到sqlite ,虽然有现成的jar,但是考虑的项目的易用统一管理,决定还是用maven 结果纠结了半天 sqlite-jdbc 在maven默认的仓库根本找不着,于是乎修改 setti ...
- java学习笔记1——window7下JDK环境变量配置图解
1. 首先下载Java安装工具包 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.ht ...
- s3c2440 的 rtc 操作
实时时钟(RTC)其主要功能是电源故障的制度下,使用后备电源,时钟继续.为了不浪费时间信息. s3c2440内部集成了RTC模块,并且用起来也十分简单. 其内部的寄存器BCDSEC,BCDMIN,BC ...
- MyEclipse2014 安装SVN小工具
1.下载svn小工具 下载链接:folderID=2240">http://subclipse.tigris.org/servlets/ProjectDocumentList?fold ...
- 突破IP限制动态替换代理ip。
须要导入的两个jar包 实现的javabean <span style="font-size:18px;">package com.jx.po; public clas ...
- Socket 学习(二)
1对1的发送和接收 Client 端 void ThreadReceive() { try { ...
- 自己编译的openwrt在开机时一直打印jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found...的错误提示
具体的输入信息是这样的. uboot> http Link down: eth0 Ethernet mode (duplex/speed): / Mbps HTTP server is star ...
- c语言内存对齐(1)
在<C陷阱与缺陷>有这样一个例子: #include <stdio.h> int main(void) { int i; char c; ;i<;i++){ scanf( ...
- jQueryRotate 转盘抽奖代码实现
代码如下: 例子兼容IE6,7,8 以及高版本浏览器,如有bug请回复! 1.html结构 <!doctype html> <html lang="en"> ...