Objective-C language
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.
Calling Methods
[object method];
[object methodWithInput:input];
output = [object methodWithOutput];
output = [object methodWithInputAndOutput:input];
id myObject = [NSString string];
In this example, it's obvious the object type will be an NSString, so we can change the type:
NSString* myString = [NSString string];
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
function1 ( function2() );
[NSString stringWithFormat:[prefs format]];
Multi-Input Methods
-(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
BOOL result = [myData writeToFile:@"/tmp/log.txt" atomically:NO];
Accessors
[photo setCaption:@"Day at the Beach"]; output = [photo caption];
Whenever you see code inside square brackets, you are sending a message to an object or a class.
Dot Syntax
photo.caption = @"Day at the Beach";
output = photo.caption;
Creating Objects
NSString* myString = [NSString string];
NSString* myString = [[NSString alloc] init];
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.
In some cases, you may use a different version of init which takes input:
NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];
Basic Memory Management
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.
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];
There's more to learn about memory management, but it will make more sense after we look at a few more concepts.
Designing a Class Interface
The class interface is usually stored in the ClassName.h file, 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.
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
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 and photographer. Both are NSStrings, but they could be any object type, including id.
Finally, the @end symbol ends the class declaration.
Add Methods
#import <Cocoa/Cocoa.h> @interface Photo : NSObject {
NSString* caption;
NSString* photographer;
} - caption;
- photographer; @end
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
#import <Cocoa/Cocoa.h> @interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- (NSString*) caption;
- (NSString*) photographer; - (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input; @end
Class Implementation
#import "Photo.h" @implementation Photo - (NSString*) caption {
return caption;
} - (NSString*) photographer {
return photographer;
} @end
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];
}
- (void) setCaption: (NSString*)input {
caption = input;
}
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
- (id) init
{
if ( self = [super init] )
{
[self setCaption:@"Default Caption"];
[self setPhotographer:@"Default Photographer"];
}
return self;
}
This essentially just asks the superclass to do its own initialization. The ifstatement is verifying that the initialization was successful before trying to set default values.
Dealloc
- (void) dealloc
{
[caption release];
[photographer release];
[super dealloc];
}
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
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.
1. To keep it as an instance variable
2. To use temporarily for single use inside a function
In most cases, the setter for an instance variable should just autoreleasethe old object, and retain the new one. You then just make sure to release it in dealloc as well.
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];
}
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];
If you understand this, you understand 90% of what you will ever need to know about Objective-C memory management.
Logging
NSLog ( @"The current date and time is: %@", [NSDate date] );
Properties
Properties are a feature in Objective-C that allow us to automatically generate accessors, and also have some other side benefits. Let's convert the Photo class to use properties.
Here's what it looked like before:
#import <Cocoa/Cocoa.h> @interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
- (NSString*) caption;
- (NSString*) photographer; - (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input; @end
#import <Cocoa/Cocoa.h> @interface Photo : NSObject {
NSString* caption;
NSString* photographer;
}
@property (retain) NSString* caption;
@property (retain) NSString* photographer; @end
Now let's take a look at the implementation of the class:
#import "Photo.h" @implementation Photo @synthesize caption;
@synthesize photographer; - (void) dealloc
{
[caption release];
[photographer release];
[super dealloc];
} @end
Accessors will only be generated if they don't already exist, so feel free to specify @synthesize for a property, then implement your custom getter or setter if you want. The compiler will fill in whichever method is missing.
There are many other options for the property declarations, but those are outside of the scope of this tutorial.
Calling Methods on Nil
This technique used by the frameworks in a number of different ways, but the main thing it means to you right now that you usually don't need to check for nil before calling a method on an object. If you call a method on nil that returns an object, you will get nil as a return value.
We can also use this to improve our dealloc method slightly:
- (void) dealloc
{
self.caption = nil;
self.photographer = nil;
[super dealloc];
}
Note that we're using the self.<var> syntax here, which means we're using the setter and picking up the memory management for free. If we just directly set the value like this, there would be a memory leak:
// incorrect. causes a memory leak.
// use self.caption to go through setter
caption = nil;
Categories
This is particularly useful because you can add methods to built-in objects. If you want to add a method to all instances of NSString in your application, you just add a category. There's no need to get everything to use a custom subclass.
For example, if I wanted to add a method to NSString to determine if the contents is a URL, it would look like this:
#import <Cocoa/Cocoa.h> @interface NSString (Utilities)
- (BOOL) isURL;
@end
Here's the implementation. Keep in mind this is not a good implementation of URL detection. We're just trying to get the concept of categories across:
#import "NSString-Utilities.h" @implementation NSString (Utilities) - (BOOL) isURL
{
if ( [self hasPrefix:@"http://"] )
return YES;
else
return NO;
} @end
NSString* string1 = @"http://pixar.com/";
NSString* string2 = @"Pixar"; if ( [string1 isURL] )
NSLog (@"string1 is a URL"); if ( [string2 isURL] )
NSLog (@"string2 is a URL");
Remember, when you make changes to a class using a category, it affects all instances of that class throughout the application.
Objective-C language的更多相关文章
- Automake
Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...
- 第十五次oo作业
作业十五 测试与正确性论证的效果差异 程序的测试需要通过输入特定数据等方式,检查程序是否和预期相同,因为测试不可能穷举,导致了不穷举的测试不可能验证程序是完全正确的,只能验证程序在测试时没有发生错误, ...
- NLP中的预训练语言模型(三)—— XL-Net和Transformer-XL
本篇带来XL-Net和它的基础结构Transformer-XL.在讲解XL-Net之前需要先了解Transformer-XL,Transformer-XL不属于预训练模型范畴,而是Transforme ...
- The Swift Programming Language 中文翻译版(个人翻新随时跟新)
The Swift Programming Language --lkvt 本人在2014年6月3日(北京时间)凌晨起来通过网络观看2014年WWDC 苹果公司的发布会有iOS8以及OS X 10.1 ...
- Artificial Intelligence Language
Artificial Intelligence Language Objective We know, a true AI program should have ability to underst ...
- Objective C静态代码扫描和代码质量管理 OClint + SonarQube
OClint是针对C, C++及Objective C代码的静态扫描分析工具,而SonarQube是一个开源的代码质量管理平台.本文将实现将OClint的扫描结果导入到SonarQube中,已实现对O ...
- C++ vs Objective C
oc Short list of some of the major differences: C++ allows multiple inheritance, Objective-C doesn't ...
- JavaScript Prototype in Plain Language
非常好的文章: http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/ jan. 25 2013 14 ...
- Objective -C Memory Management 内存管理 第一部分
Objective -C Memory Management 内存管理 第一部分 Memory management is part of a more general problem in pr ...
- A Pattern Language for Parallel Application Programming
A Pattern Language for Parallel Application Programming Berna L. Massingill, Timothy G. Mattson, Bev ...
随机推荐
- 洛谷 P4245 [模板]任意模数NTT —— 三模数NTT / 拆系数FFT(MTT)
题目:https://www.luogu.org/problemnew/show/P4245 用三模数NTT做,需要注意时间和细节: 注意各种地方要取模!传入 upt() 里面的数一定要不超过2倍 m ...
- java中约瑟夫环代码实现
问题原型: 传说在很久很久以前,有一架搭载着n个人的飞机出现了故障,迫降在了一个荒岛上.飞机彻底报废后,这些人用飞机的残骸建成了一艘只能容纳一个人乘坐的小船,那么怎么去确定这n个人中哪个人有资格上船呢 ...
- Java创建对象解释
创建对象包括两个步骤,首先为对象声明,然后为对象分配内存. (1)对象声明 格式:类名 对象名: 这里只是声明了对象,但该对象并不能够使用,原因为未分配内存空间. (2)为对象分配内存 格式:new ...
- linux中的调试知识---基础gdb和strace查看系统调用信息,top性能分析,ps进程查看,内存分析工具
1 调试一般分为两种,可以通过在程序中插入打印语句.有点能够显示程序的动态过程,比较容易的检查出源程序中的有关信息.缺点就是效率比较低了,而且需要输入大量无关的数据. 2 借助相关的调试工具. 3 有 ...
- Markdown编写github README.md
Markdown编写github README.md 一.在线编辑器StackEdit Markdown在线编辑器地址 中文:https://www.zybuluo.com/mdeditor 英文:h ...
- LeetCode: 500 Keyboard Row (easy)
题目: Given a List of words, return the words that can be typed using letters of alphabet on only one ...
- 使用you-get下载网页小视频(实际上你可以下载任意你想要的web网页中的内容)
1. 什么是you-get? You-Get是一个小型的命令行实用程序,用于从Web下载媒体内容(视频,音频,图像),如果没有其他方便的方法可以尝试使用you-get. 2.安装you-get 打开命 ...
- P3270 [JLOI2016]成绩比较(拉格朗日插值)
传送门 挺神仙的啊-- 设\(f[i][j]\)为考虑前\(i\)门课程,有\(j\)个人被\(B\)爷碾压的方案数,那么转移为\[f[i][j]=\sum_{k=j}^{n-1}f[i-1][k]\ ...
- 在mpvue框架中使用Vant WeappUI组件库的注意事项
1如何引入组件库 有两种方法 1 npm下载 2 下载代码,下面介绍第二种方法. 在gitHub上, 链接如下 https://github.com/youzan/vant-weapp 首先在自己项目 ...
- JQuery数组遍历 - $.each(),$().each()和forEach()