object-c

1.In Objective-C, a class is itself an object with an opaque type called Class. Classes can’t have properties defined using the declaration syntax shown earlier for instances, but they can receive messages.

2 Literals Offer a Concise Object-Creation Syntax

some classes allow you to use a more concise, literal syntax to create instances.

You can create an NSString instance, for example, using a special literal notation, like this:

    NSString *someString = @"Hello, World!";

This is effectively the same as allocating and initializing an NSString or using one of its class factory methods:

    NSString *someString = [NSString stringWithCString:"Hello, World!"
                                              encoding:NSUTF8StringEncoding];

The NSNumber class also allows a variety of literals:

    NSNumber *myBOOL = @YES;
    NSNumber *myFloat = @3.14f;
    NSNumber *myInt = @42;
    NSNumber *myLong = @42L;
Objective-C also supports literals to create immutable  NSArray  and  NSDictionary  objects; 
 NSArray *someArray = @[firstObject, secondObject, thirdObject];
 
 
 
 
 NSDictionary *dictionary = @{
                  @"anObject" : someObject,
               @"helloString" : @"Hello, World!",
               @"magicNumber" : @42,
                    @"aValue" : someValue
    };

3. Working with nil

It’s always a good idea to initialize scalar variables at the time you declare them, otherwise their initial values will contain garbage from the previous stack contents:

    BOOL success = NO;
    int magicNumber = 42;

This isn’t necessary for object pointers, because the compiler will automatically set the variable to nil if you don’t specify any other initial value:

    XYZPerson *somePerson;
    // somePerson is automatically set to nil

4.

If you want to use a different name for an accessor method, it’s possible to specify a custom name by adding attributes to the property. In the case of Boolean properties (properties that have a YES or NO value), it’s customary for the getter method to start with the word “is.” The getter method for a property called finished, for example, should be called isFinished.

Again, it’s possible to add an attribute on the property:

@property (getter=isFinished) BOOL finished;

5, Most Properties Are Backed by Instance Variables
Unless you specify otherwise, the synthesized instance variable has the same name as the property, but with an underscore prefix. For a property called  firstName , for example, the synthesized instance variable will be called _firstName .
If you wish to use a different name for the instance variable, you need to direct the compiler to synthesize the variable using the following syntax in your implementation:
@synthesize firstName = ivar_firstName;

In this case, the property will still be called firstName, and be accessible through firstName and setFirstName:accessor methods or dot syntax, but it will be backed by an instance variable called ivar_firstName.

You Can Define Instance Variables without Properties

use strong references for their synthesized instance variables. To declare a weak reference, add an attribute to the property, like this:

@property (weak) id delegate;

If you don’t want a variable to maintain a strong reference, you can declare it as __weak, like this:

    NSObject * __weak weakVariable;

This means that if you use a weak variable in the previous date example:

    NSDate * __weak originalDate = self.lastModificationDate;
    self.lastModificationDate = [NSDate date];
The opposite to  __weak  is  __strong . Again, you don’t need to specify  __strong  explicitly, because it is the default.
Any object that you wish to set for a copy property must support NSCopying, which means that it should conform to the NSCopying protocol.

Categories Add Methods to Existing Classes

Any methods that you declare in a category will be available to all instances of the original class, as well as any subclasses of the original class. At runtime, there’s no difference between a method added by a category and one that is implemented by the original class.
Categories can be used to declare either instance methods or class methods but are not usually suitable for declaring additional properties. It’s valid syntax to include a property declaration in a category interface, but it’s not possible to declare an additional instance variable in a category. This means the compiler won’t synthesize any instance variable, nor will it synthesize any property accessor methods. You can write your own accessor methods in the category implementation, but you won’t be able to keep track of a value for that property unless it’s already stored by the original class.

Class Extensions Extend the Internal Implementation

A class extension bears some similarity to a category, but it can only be added to a class for which you have the source code at compile time (the class is compiled at the same time as the class extension). The methods declared by a class extension are implemented in the  @implementation  block for the original class so you can’t,for example, declare a class extension on a framework class, such as a Cocoa or Cocoa Touch class like NSString.

Unlike regular categories, a class extension can add its own properties and instance variables to a class. If you declare a property in a class extension, like this:

@interface XYZPerson ()
@property NSObject *extraProperty;
@end

the compiler will automatically synthesize the relevant accessor methods, as well as an instance variable, inside the primary class implementation.

If you add any methods in a class extension, these must be implemented in the primary implementation for the class.

It’s also possible to use a class extension to add custom instance variables. These are declared inside braces in the class extension interface:

@interface XYZPerson () {
    id _someCustomInstanceVariable;
}
...
@end

Use Class Extensions to Hide Private Information

@interface XYZPerson : NSObject
...
@property (readonly) NSString *uniqueIdentifier;
- (void)assignUniqueIdentifier;
@end

@interface XYZPerson ()
@property (readwrite) NSString *uniqueIdentifier;
@end
 
@implementation XYZPerson
...
@end

This means that the compiler will now also synthesize a setter method, so any method inside the XYZPersonimplementation will be able to set the property directly using either the setter or dot syntax.

By declaring the class extension inside the source code file for the XYZPerson implementation, the information stays private to the XYZPerson class. If another type of object tries to set the property, the compiler will generate an error.

Protocols Define Messaging Contracts

A class interface declares the methods and properties associated with that class. A protocol, by contrast, is used to declare methods and properties that are independent of any specific class.

The basic syntax to define a protocol looks like this:

@protocol ProtocolName
// list of methods and properties
@end

Protocols Inherit from Other Protocols

@protocol MyProtocol <NSObject>
...
@end

Protocols Are Used for Anonymity

NSInteger sectionNumber = ...
    id <NSFetchedResultsSectionInfo> sectionInfo =
            [self.fetchedResultsController.sections objectAtIndex:sectionNumber];
    NSInteger numberOfRowsInSection = [sectionInfo numberOfObjects];

Even though you don’t know the class of the sectionInfo object, the NSFetchedResultsSectionInfo protocol dictates that it can respond to the numberOfObjects message.

In order for this anonymousUtility object to be useful, the developer of the framework can publish a protocol that reveals some of its methods. Even though the original class interface isn’t provided, which means the class stays anonymous, the object can still be used in a limited way:

    id <XYZFrameworkUtility> utility = [frameworkObject anonymousUtility];

Represent Other Values Using Instances of the NSValue Class

The NSNumber class is itself a subclass of the basic NSValue class, which provides an object wrapper around a single value or data item. In addition to the basic C scalar types, NSValue can also be used to represent pointers and structures.

The NSValue class offers various factory methods to create a value with a given standard structure, which makes it easy to create an instance to represent, for example, an NSRange, like the example from earlier in the chapter:

    NSString *mainString = @"This is a long string";
    NSRange substringRange = [mainString rangeOfString:@"long"];
    NSValue *rangeValue = [NSValue valueWithRange:substringRange];

It’s also possible to create NSValue objects to represent custom structures. If you have a particular need to use a C structure (rather than an Objective-C object) to store information, like this:

typedef struct {
    int i;
    float f;
} MyIntegerFloatStruct;

you can create an NSValue instance by providing a pointer to the structure as well as an encoded Objective-C type. The @encode() compiler directive is used to create the correct Objective-C type, like this:

    struct MyIntegerFloatStruct aStruct;
    aStruct.i = 42;
    aStruct.f = 3.14;
 
    NSValue *structValue = [NSValue value:&aStruct
                             withObjCType:@encode(MyIntegerFloatStruct)];

The standard C reference operator (&) is used to provide the address of aStruct for the value parameter.

NSDictionary

  NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"];

There’s also an alternative syntax to using objectForKey:, which looks like this:

    NSNumber *storedNumber = dictionary[@"magicNumber"];

If you use fast enumeration with a dictionary, you iterate over the dictionary keys, like this:

    for (NSString *eachKey in dictionary) {
        id object = dictionary[eachKey];
        NSLog(@"Object: %@ for key: %@", object, eachKey);
    }

If you need to keep track of the current index, simply count the iterations as they occur:

    int index = 0;
    for (id eachObject in array) {
        NSLog(@"Object at index %i is: %@", index, eachObject);
        index++;
    }

You cannot mutate a collection during fast enumeration, even if the collection is mutable. If you attempt to add or remove a collected object from within the loop, you’ll generate a runtime exception.

Represent nil with NSNull

It’s not possible to add nil to the collection classes described in this section because nil in Objective-C means “no object.” If you need to represent “no object” in a collection, you can use the NSNull class:

    NSArray *array = @[ @"string", @42, [NSNull null] ];

NSNull is a singleton class, which means that the null method will always return the same instance. This means that you can check whether an object in an array is equal to the shared NSNull instance:

    for (id object in array) {
        if (object == [NSNull null]) {
            NSLog(@"Found a null object");
        }
    }

Most Collections Also Support Enumerator Objects

It’s also possible to enumerate many Cocoa and Cocoa Touch collections by using an NSEnumerator object.

You can ask an NSArray, for example, for an objectEnumerator or a reverseObjectEnumerator. It’s possible to use these objects with fast enumeration, like this:

    for (id eachObject in [array reverseObjectEnumerator]) {
        ...
    }

In this example, the loop will iterate over the collected objects in reverse order, so the last object will be first, and so on.

It’s also possible to iterate through the contents by calling the enumerator’s nextObject method repeatedly, like this:

    id eachObject;
    while ( (eachObject = [enumator nextObject]) ) {
        NSLog(@"Current object is: %@", eachObject);
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值