ObjectiveC 拾遗

关于Method 

这里引入method specification的概念(我自己弄的,因为不了解官方的名称是什么,如果有人知道,请告诉我)。在C中,一个函数的方法名(区分大小写),也就是说,如果两个函数的方法名相同,即使参数个数或者参数类型不同,那么也认为这两个方法是一样的,从而产生错误(在C语言中是编译时错误),比如下面的代码:

void foo() //valid
{
}

int foo() //Error    1    error C2371: 'foo' : redefinition; different basic types
{
}

void Foo() //valid
{
}

void foo(int a) //Error    1    error C2084: function 'void foo()' already has a body
{
}

C++引入了重载的概念,所以method specification包含方法名、参数个数及其类型。这里就不举例了。下面看Objective-C中method specification。

用习惯了C/C++,理解Objective-C的method specification着实费劲。因为Objective-C中method specification是由方法名加参数名构成的,举例来说:

Tester.h
#import <Foundation/Foundation.h>

@interface Tester : NSObject
{
    
}
- (void) test:(NSString *)msg:(Tester *)sec:(int)third;
- (void) test:(NSString *)msg secondAr0:(Tester *)sec ThirdArg0:(int)third;
- (void) test:(NSString *)msg secondAr:(Tester *)sec ThirdArg: (int)third;
- (void) test:(NSString *)msg;
- (void) test:(NSString *)msg2;
- (void) test0;
//- (void) test:(int *)msg; //Duplicate declaration of method 'test:'
-(void) notImp;
@end


Tester.m
#import "Tester.h"

@implementation Tester
- (void) test:(NSString *)msg :(Tester *)sec :(int)third
{
    NSLog(@"current method is %@",NSStringFromSelector(_cmd));
}
- (void) test:(NSString *)msg secondAr0:(Tester *)sec ThirdArg0:(int)third
{
    NSLog(@"current method is %@",NSStringFromSelector(_cmd));
}
- (void) test:(NSString *)msg secondAr:(Tester *)sec ThirdArg: (int)third
{
    NSLog(@"current method is %@",NSStringFromSelector(_cmd));
}
-(void)test:(NSString *)msg
{
    NSLog(@"current method is %@",NSStringFromSelector(_cmd));
}
-(void)test0
{
    NSLog(@"current method is %@",NSStringFromSelector(_cmd));
}
//- (void) test:(NSString *)msg2 //Duplicate declaration of method 'test:'
//{
//    NSLog(@"current method is %@",NSStringFromSelector(_cmd));
//}

-(void)notImp
{
    NSLog(@"test notImp");
}
@end


main.m
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        id tester = [[Tester alloc] init];
        [tester test:@"" :tester :1];
        [tester test:@""
           secondAr0:tester
           ThirdArg0:1];
        [tester test:@"" 
            secondAr:tester
            ThirdArg:1];
        [tester test:@""];
        [tester test0];
        [tester test:@"" :tester :1];
    }
    return 0;
}

将错误的部分注释后,输出结果如下:

2013-03-01 18:16:03.119 TestSelector[12056:403] current method is test:::
2013-03-01 18:16:03.121 TestSelector[12056:403] current method is test:secondAr0:ThirdArg0:
2013-03-01 18:16:03.122 TestSelector[12056:403] current method is test:secondAr:ThirdArg:
2013-03-01 18:16:03.122 TestSelector[12056:403] current method is test:
2013-03-01 18:16:03.123 TestSelector[12056:403] current method is test0
2013-03-01 18:16:03.123 TestSelector[12056:403] current method is test:::
2013-03-01 18:16:03.124 TestSelector[12056:403] current method is test:

 可以看到,如果给某个参数起名字,那会把这个名字加一个':'作为那方法的specification的一部分,如果不给参数命名,那就只加一个':'。如果参数被命名,那之后调用时也必须指明这个名字。

attribute, to-one relationship , to-many relationship

  • attribute: 比如学生的姓名、年龄等;attribute往往是NSString, NSDate, NSData的实例;
  • to-one relationship: 比较像attribute,不过其类型要复杂一些,比如每个学生有个学校与之关联。to-one relationship往往使用指针实现;
  • sorted to-many relationship: 比如每个playlist都包含若干歌曲,其要么按加入时间排序、要么按名字排序,或者其他的排序方式。其典型的使用NSMutableArray来实现。
  • unsorted to-manay relationship: 比如每个部门都有一些员工,这种情况是没有顺序的。往往使用NSMutableSet实现;

== 和 isEqual 的关系

Imagine you have a pair of one dollar bills. Both bills are “equal”, because you could use either bill to pay for a one dollar item.

They are however not identical. Each bill has a unique serial number that indicates when and where it was made. No two dollar bills have the same serial number. If you told me the serial number of one of the bills, you could put in in a pile with thousands of other bills and I would still be able to uniquely identify that particular bill.

Now imagine the same test with coins instead of dollar bills. While coins do have some slight variation (the year and pressing facility may vary), I can easily aquire a bag of 1000 quarters, all of which are not only equal but identical. There is no way to identity a particular quarter once it has been thrown in a pile of identical quarters.

Objects (NSObject, NSView, etc) are like dollar bills, each one is unique but may be equal to others,but not identical. Primitives (int,float,char) are like coins, if they are equal then they are identical.

在Objecitve C中,a==b意思是问,这两个对象是否identical, 而[a isEqual:b]意思是问,这两个对象是否equal。对于object来说,如果a==b为真,那么[a isEqual:b]也为真,但反之就不一定成立。而对于primitive类型而言,则反之也是成立的。

再来看看isEqual和hash的关系,Apple的文档中说hash是返回一个整形,用来在hash table中作为table address。如果两个对象是equal的(用isEqual判断),那么他们就应该具有相同的hash值。如果一个mutable的对象被加入到一个collection中,在此期间,其hash值不能变化。因此 hash值的计算要么就不依赖对象的内部状态,要么就是依赖内部状态,但内部状态在被加入到hash table期间不能被改变。

字符串

Objective C中支持两种字符串:C字符串和NSString字符串。NSString字符串常量前面带有@符号,而C字符串则没有。

// C string 
char *foo; 
// NSString 
NSString *bar; 
foo = "this is a C string"; 
bar = @"this is an NSString";

NSString会被更经常地用到,它们之间可以进行转换,下面是转换的例子:

const char *foo = "Blah blah";
NSString *bar;

//Create an NSString from a C string
bar = [NSString stringWithUTF8String:foo];

//Create a C string from a NSString
foo = [bar UTF8String];

因为NSString可以是Unicode的字符串,所以你要正确的处理C字符串的多字节的字符,通常这有些难且废时。(处理多字节字符问题,你可能还会遇到有些语言是从右向左读这样的问题) 不管怎么样,尽量用NSString代替C字符串

property和synthesize

这是在Objective C 2.0中引入的新关键字。其目的是为了简化Property的实现。以前的时候,要实现一个Property,我们需要声明一个instance variable,然后定义并实现两个accesser,比如下面的代码:

// test.h
@class Test {
    int count;    
}
- (int)count;
-(void)setCount:(int)newCount;


//test.m
- (int)count
{
    return count;
}
-(void)setCount:(int)newCount
{
    count = newCount;
}

使用新的关键字后,就可以使用property代替.h文件中的代码,使用synthesize代替.m中的代码了。新代码如下所示:

//test.h
@property int count;

//test.m
@synthesize count; 

property的使用语法是:@property (参数1,参数2,参数3) 类型 名字;其中()中的参数个数是可选的,其参数有以下3种类型:

读写属性: (readwrite/readonly)
setter语意:(assign/retain/copy)
原子性: (【atomicity】/nonatomic)

被加粗的参数是默认值,也就是这个类别中任何值都没有被指定时使用的值,对于原子性,只有nonatomic关键字,表示不是原子访问的,但它不是默认值。下面对这些值分别介绍一下:

readonly
此标记说明属性是只读的,默认的标记是读写,如果你指定了只读,在@implementation中只需要一个读取器。或者如果你使用@synthesize关键字,也是有读取器方法被解析。而且如果你试图使用点操作符为属性赋值,你将得到一个编译错误。

readwrite
此标记说明属性会被当成读写的,这也是默认属性。设置器和读取器都需要在@implementation中实现。如果使用@synthesize关键字,读取器和设置器都会被解析。

assign
此标记说明设置器直接进行赋值,这也是默认值。在使用垃圾收集的应用程序中,如果你要一个属性使用assign,且这个类符合NSCopying协议,你就要明确指出这个标记,而不是简单地使用默认值,否则的话,你将得到一个编译警告。这再次向编译器说明你确实需要赋值,即使它是可拷贝的。

retain
指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数——译者注)。

copy
它指出,在赋值时使用传入值的一份拷贝。拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议的对象类型有效。更深入的讨论,请参考“复制”部分。

nonatomic
指出访问器不是原子操作,而默认地,访问器是原子操作。这也就是说,在多线程环境下,解析的访问器提供一个对属性的安全访问,从获取器得到的返回值或者通过设置器设置的值可以一次完成,即便是别的线程也正在对其进行访问。如果你不指定nonatomic,在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了nonatomic,那么访问器只是简单地返回这个值。

IBAction and IBOutlet 

IBAction and IBOutlet are macros defined to denote variables and methods that can be referred to in Interface Builder.其定义如下:

#ifndef IBOutlet 
#define IBOutlet 
#endif 
 
#ifndef IBAction 
#define IBAction void 
#endif 

IBAction resolves to "void" and IBOutlet resolves to nothing, but they signify to Xcode and Interface builder that these variables and methods can be used in Interface builder to link UI elements to your code.

If you're not going to be used Interface Builder at all, then you don't need them in your code, but if you are going to use it, then you need to specify IBAction for methods that will be used in IB and IBOutlet for objects that will be used in IB.

看看什么地方可以有IBAction和IBOutlet,在IB中可以将UI上的元素跟File's Owner, Application, First Responder(?), Shared User Defaults(?) , Object, Object Controller, Managed Object Context. 所以这这些类中是可以是使用IBAction和IBOutlet的,其他地方,即使用了,也无法跟UI上的元素进行link。

关于new和alloc init 

 nil, NSNull

原文地址:https://www.cnblogs.com/whyandinside/p/2935230.html