Interface & Implementation
@interface
and @implementation
are the first things you learn about when you start Objective-C:
-
@interface
...@end
-
@implementation
...@end
What you don't learn about until later on, are categories and class extensions.
Categories allow you to extend the behavior of existing classes by adding new class or instance methods. As a convention, categories are defined in their own .{h,m}
files, like so:
MyObject+CategoryName.h
@interface MyObject (CategoryName)
- (void)foo;
- (BOOL)barWithBaz:(NSInteger)baz;
@end
MyObject+CategoryName.m
@implementation MyObject (CategoryName)
- (void)foo {
// ...
}
- (BOOL)barWithBaz:(NSInteger)baz {
return YES;
}
@end
Categories are particularly useful for convenience methods on standard framework classes (just don't go overboard with your utility functions).
Pro Tip: Rather than littering your code with random, arbitrary color values, create an
NSColor
/UIColor
color palette category that defines class methods like+appNameDarkGrayColor
. You can then add a semantic layer on top of that by creating method aliases like+appNameTextColor
, which returns+appNameDarkGrayColor
.
Extensions look like categories, but omit the category name. These are typically declared before an @implementation
to specify a private interface, and even override properties declared in the interface:
@interface MyObject ()
@property (readwrite, nonatomic, strong) NSString *name;
- (void)doSomething;
@end
@implementation MyObject
@synthesize name = _name;
// ...
@end
Properties
Property directives are likewise concepts learned early on:
@property
@synthesize
@dynamic
One interesting note with properties is that as of Xcode 4.4, it is no longer necessary to explicitly synthesize properties. Properties declared in an @interface
are automatically synthesized (with leading underscore ivar name, i.e. @synthesize propertyName = _propertyName
) in the implementation.
Forward Class Declarations
Occasionally, @interface
declarations will reference an external class in a property or as a parameter type. Rather than adding #import
statements for each class, it's good practice to use forward class declarations in the header, and import them in the implementation.
@class
Shorter compile times, less chance of cyclical references; you should definitely get in the habit of doing this if you aren't already.
Instance Variable Visibility
It's a matter of general convention that classes provide state and mutating interfaces through properties and methods, rather than directly exposing ivars.
Although ARC makes working with ivars much safer by taking care of memory management, the aforementioned automatic property synthesis removes the one place where ivars would otherwise be declared.
Nonetheless, in cases where ivars are directly manipulated, there are the following visibility directives:
-
@public
: instance variable can be read and written to directly, using the notationperson->age = 32"
-
@package
: instance variable is public, except outside of the framework in which it is specified (64-bit architectures only) -
@protected
: instance variable is only accessible to its class and derived classes -
@private
: instance variable is only accessible to its class
@interface Person : NSObject {
@public
NSString name;
int age;
@private
int salary;
}
Protocols
There's a distinct point early in an Objective-C programmer's evolution, when she realizes that she can define her own protocols.
The beauty of protocols is that they allow programmers to design contracts that can be adopted outside of a class hierarchy. It's the egalitarian mantra at the heart of the American Dream: that it doesn't matter who you are, or where you come from: anyone can achieve anything if they work hard enough.
...or at least that's idea, right?
-
@protocol
...@end
: Defines a set of methods to be implemented by any class conforming to the protocol, as if they were added to the interface of that class.
Architectural stability and expressiveness without the burden of coupling--protocols are awesome.
Requirement Options
You can further tailor a protocol by specifying methods as required or optional. Optional methods are stubbed in the interface, so as to be auto-completed in Xcode, but do not generate a warning if the method is not implemented. Protocol methods are required by default.
The syntax for @required
and @optional
follows that of the visibility macros:
@protocol CustomControlDelegate
- (void)control:(CustomControl *)control didSucceedWithResult:(id)result;
@optional
- (void)control:(CustomControl *)control didFailWithError:(NSError *)error;
@end
Exception Handling
Objective-C communicates unexpected state primarily through NSError
. Whereas other languages would use exception handling for this, Objective-C relegates exceptions to truly exceptional behavior, including programmer error.
@
directives are used for the traditional convention of try/catch/finally
blocks:
@try{
// attempt to execute the following statements
[self getValue:&value error:&error];
// if an exception is raised, or explicitly thrown...
if (error) {
@throw exception;
}
} @catch(NSException *e) {
// ...handle the exception here
} @finally {
// always execute this at the end of either the @try or @catch block
[self cleanup];
}
Literals
Literals are shorthand notation for specifying fixed values. Literals are more -or-less directly correlated with programmer happiness. By this measure, Objective-C has long been a language of programmer misery.
Object Literals
Until recently, Objective-C only had literals for NSString
. But with the release of the Apple LLVM 4.0 compiler, literals for NSNumber
, NSArray
and NSDictionary
were added, with much rejoicing.
-
@""
: Returns anNSString
object initialized with the Unicode content inside the quotation marks. -
@42
,@3.14
,@YES
,@'Z'
: Returns anNSNumber
object initialized with pertinent class constructor, such that@42
→[NSNumber numberWithInteger:42]
, or@YES
→[NSNumber numberWithBool:YES]
. Supports the use of suffixes to further specify type, like@42U
→[NSNumber numberWithUnsignedInt:42U]
. -
@[]
: Returns anNSArray
object initialized with the comma-delimited list of objects as its contents. For example,@[@"A", @NO, @2.718]
→[NSArray arrayWithObjects:@"A", @NO, @2.718, nil]
(note that sentinelnil
is not required in literal). -
@{}
: Returns anNSDictionary
object initialized with the specified key-value pairs as its contents, in the format:@{@"someKey" : @"theValue"}
. -
@()
: Dynamically evaluates the boxed expression and returns the appropriate object literal based on its value (i.e.NSString
forconst char*
,NSNumber
forint
, etc.). This is also the designated way to use number literals withenum
values.
Objective-C Literals
Selectors and protocols can be passed as method parameters. @selector()
and @protocol()
serve as pseudo-literal directives that return a pointer to a particular selector (SEL
) or protocol (Protocol *
).
-
@selector()
: Returns anSEL
pointer to a selector with the specified name. Used in methods like-performSelector:withObject:
. -
@protocol()
: Returns aProtocol *
pointer to the protocol with the specified name. Used in methods like-conformsToProtocol:
.
C Literals
Literals can also work the other way around, transforming Objective-C objects into C values. These directives in particular allow us to peek underneath the Objective-C veil, to begin to understand what's really going on.
Did you know that all Objective-C classes and objects are just glorified struct
s? Or that the entire identity of an object hinges on a single isa
field in that struct
?
For most of us, at least most of the time, coming into this knowledge is but an academic exercise. But for anyone venturing into low-level optimizations, this is simply the jumping-off point.
-
@encode()
: Returns the type encoding of a type. This type value can be used as the first argument encode inNSCoder -encodeValueOfObjCType:at
. -
@defs()
: Returns the layout of an Objective-C class. For example, to declare a struct with the same fields as anNSObject
, you would simply do:
struct {
@defs(NSObject)
}
Ed. As pointed out by readers @secboffin & @ameaijou,
@defs
is unavailable in the modern Objective-C runtime.
Optimizations
There are some @
compiler directives specifically purposed for providing shortcuts for common optimizations.
-
@autoreleasepool{}
: If your code contains a tight loop that creates lots of temporary objects, you can use the@autorelease
directive to optimize for these short-lived, locally-scoped objects by being more aggressive about how they're deallocated.@autoreleasepool
replaces and improves upon the oldNSAutoreleasePool
, which is significantly slower, and unavailable with ARC. -
@synchronized(){}
: This directive offers a convenient way to guarantee the safe execution of a particular block within a specified context (usuallyself
). Locking in this way is expensive, however, so for classes aiming for a particular level of thread safety, a dedicatedNSLock
property or the use of low-level locking functions likeOSAtomicCompareAndSwap32(3)
are recommended.
Compatibility
In case all of the previous directives were old hat for you, there's a strong likelihood that you didn't know about this one:
-
@compatibility_alias
: Allows existing classes to be aliased by a different name.
For example PSTCollectionView uses @compatibility_alias
to significantly improve the experience of using the backwards-compatible, drop-in replacement for UICollectionView:
// Allows code to just use UICollectionView as if it would be available on iOS SDK 5.
// http://developer.apple. com/legacy/mac/library/#documentation/DeveloperTools/gcc-3. 3/gcc/compatibility_005falias.html
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
@compatibility_alias UICollectionViewController PSTCollectionViewController;
@compatibility_alias UICollectionView PSTCollectionView;
@compatibility_alias UICollectionReusableView PSTCollectionReusableView;
@compatibility_alias UICollectionViewCell PSTCollectionViewCell;
@compatibility_alias UICollectionViewLayout PSTCollectionViewLayout;
@compatibility_alias UICollectionViewFlowLayout PSTCollectionViewFlowLayout;
@compatibility_alias UICollectionViewLayoutAttributes PSTCollectionViewLayoutAttributes;
@protocol UICollectionViewDataSource <PSTCollectionViewDataSource> @end
@protocol UICollectionViewDelegate <PSTCollectionViewDelegate> @end
#endif
Using this clever combination of macros, a developer can develop with UICollectionView
by including PSTCollectionView
--without worrying about the deployment target of the final project. As a drop-in replacement, the same code works more-or-less identically on iOS 6 as it does on iOS 4.3.
So to review:
Interfaces & Implementation
-
@interface
...@end
-
@implementation
...@end
@class
Instance Variable Visibility
@public
@package
@protected
@private
Properties
@property
@synthesize
@dynamic
Protocols
@protocol
@required
@optional
Exception Handling
@try
@catch
@finally
@throw
Object Literals
@""
-
@42
,@3.14
,@YES
,@'Z'
@[]
@{}
@()
Objective-C Literals
@selector()
@protocol()
C Literals
@encode()
@defs()
Optimizations
@autoreleasepool{}
@synchronized{}
Compatibility
@compatibility_alias
Thus concludes this exhaustive rundown of the many faces of @
. It's a versatile, power-packed character, that embodies the underlying design and mechanisms of the language.
相关推荐
使用指令 AT AT 指令是无线终端所使用的一种常用指令,旨在检测和配置 modem/module 的各种参数。下面是使用指令 AT 的一些注意事项和相关知识点: 1. detect modem/module 软件版本:使用 AT+CGMR 指令可以检测 ...
AT指令框架是嵌入式系统,尤其是微控制器(如STM32)与通信模块交互的一种标准方式。在STM32AT项目中,这种框架被设计用于简化STM32微控制器与各种通信模块(如GSM/GPRS、Wi-Fi或蓝牙模块)之间的通信。通过AT指令,...
### AT&T汇编语言指南知识点总结 #### 一、AT&T与Intel汇编语言语法的区别 **1.1 指令大小写** - **Intel格式**:指令使用大写字母。 - **AT&T格式**:指令使用小写字母。 **示例**: - Intel: `MOV AX, EBX` - ...
在PHP编程语言中,`@` 符号,也被称为 "at" 记号,扮演着一个特殊的角色:它是一个错误抑制符。当你在代码中使用 `@` 符号来修饰一个表达式时,PHP将抑制(或者说忽略)该表达式执行过程中产生的任何错误信息。这...
AT1846S是一款高性能的模拟开关集成电路,主要应用于信号路由和系统控制。这款器件在电子设备中扮演着至关重要的角色,允许用户通过软件或硬件控制来打开或关闭特定的信号路径。在这个资料包中,"AT1846S_datasheet_...
AT24Cxx系列是E2PROM(电可擦可编程只读存储器)芯片,主要用于存储小容量数据,常见的如AT24C02,它提供了2K位(256字节)的存储空间。在Linux操作系统中,与这类硬件交互通常需要驱动程序的支持。这篇内容将详细...
AT070TN94是一款广泛应用在工业环境中的电阻式触摸屏控制器,其开发与电源设计对于理解电子设备中人机交互技术至关重要。本压缩包包含了一份关于AT070TN94的详细原理图(SCH),为工程师提供了一份宝贵的参考资料。 ...
AT1846S是一款高性能、高集成度的微控制器,广泛应用于各种嵌入式系统设计。这篇编程指南和数据手册提供了关于AT1846S芯片的详细信息,包括其功能特性、电气规格、引脚配置、接口描述以及编程指南,是开发者理解和...
在讨论AT89C51和AT89S51/52的区别之前,首先需要了解什么是51单片机。51单片机是一种基于Intel MCS-51系列架构的8位单片机,该系列由Intel公司在1980年推出。随着技术的发展,8051架构的单片机也经历了多次升级和...
AT指令是应用在通信协议中的控制命令,常用于嵌入式设备与远程终端之间的交互,如GSM模块、蓝牙模组、Wi-Fi芯片等。这些指令通常以ASCII文本形式发送,以“AT”开头,后面跟着具体的命令或参数,用于配置设备、检查...
SPI接口的EEPROM,如AT25010、AT25020和AT25040,就是这类存储器的典型代表。这些设备通过SPI(Serial Peripheral Interface)总线与STM32进行通信,提供不同容量的存储空间。 1. **STM32 SPI接口**: STM32的SPI...
AT编程与AT命令集是通信领域中的核心技术,尤其在嵌入式系统和物联网(IoT)设备中广泛应用。AT指令,全称为“Attention”,最早由Hayes公司开发,用于控制调制解调器,现在已经成为一种标准接口,使得微控制器、模块...
AT21CS01/AT21CS11是单线串行EEPROM芯片,主要应用于数据存储,尤其是在电子设备中。这些芯片由Atmel公司(现已被Microchip Technology收购)生产,以其高效能和易用性而受到工程师的欢迎。在给定的压缩包中,包含了...
建伍TH K4AT K2AT K4E K2E K2ET 中文使用说明书 本文档是建伍TH K4AT K2AT K4E K2E K2ET 中文使用说明书,旨在指导用户正确使用建伍TH K4AT K2AT K4E K2E K2ET 系列产品。以下是从该文件中提取的相关知识点: 一、...
在阅读了《MG0017_从AT32F415移植到AT32F421_V1.0.1.pdf》文档后,我们可以提炼出关于AT32F415与AT32F421微控制器之间移植过程中的关键知识点,涵盖了硬件移植、外设移植和固件移植的方面。 首先,AT32F415与AT32F...
### 全部通用AT指令集解析 #### 一、引言 AT指令集是一种用于通信设备(如手机、调制解调器等)与计算机或其他终端设备之间进行交互的标准指令集合。通过这些指令,可以实现对设备的功能控制、状态查询等操作。本文...
根据提供的文件信息,AT21CS01/AT21CS11是一款来自Microchip公司的单线I/O供电的串行EEPROM。该芯片主要具有以下特征与知识点: 1. 芯片特性 - AT21CS01和AT21CS11都是带有出厂预设64位唯一序列号的单线I/O供电的1...
在Android系统中,AT(Attention)命令主要用于与硬件模块,如调制解调器或SIM卡进行通信。这些命令遵循Hayes命令集,是通信协议的基础,尤其在GSM、UMTS和LTE网络中广泛使用。AT命令允许设备进行数据传输、网络注册...
该系列包括了AT24C01、AT24C02、AT24C04、AT24C08、AT24C16、AT24C32、AT24C64、AT24C128、AT24C256等多种型号,存储容量从1K位到256K位不等。 #### C语言程序框架分析 ##### 标题 标题明确指出了程序的目标是实现...