Programming with Objective-C 学习笔记

这几天把Programming with Objective-C再看了一边,发现有很多以前不明确的地方。现在把一些重要的点记下来,巩固学习效果。

1.Objective-C Classes Are also Objects(OC类也是对象)

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.

The typical use for a class method is as a factory method, which is an alternative to the object allocation and initialization procedure described in Objects Are Created Dynamically (page 34).

类也是特殊的对象,典型的用法是类中的方法被称作工厂方法。

2.Use Pointers to Keep Track of Objects(使用指针记录对象)

Objects normally have a longer life than the simple scope of a method call. In particular, an object often needs to stay alive longer than the original variable that was created to keep track of it, so an object’s memory is allocated and deallocated dynamically.

If you’re used to using terms like the stack and the heap,a local variable is allocated on the stack, while objects are allocated on the heap.

这里针对 local variable(本地变量)和object(对象)的不同点,介绍了两套解释的术语。后面一种比较熟悉,本地变量存放在stack(栈)中,对象存放在heap(堆)中。

3.Objects Are Created Dynamically(对象是被动态创建的)

The NSObject root class provides a class method, alloc, which handles this process for you:

?+ (id)alloc;

Notice that the return type of this method is id. This is a special keyword used in Objective-C to mean “some kind of object.” It is a pointer to an object, like (NSObject *), but is special in that it doesn’t use an asterisk.

The alloc method has one other important task, which is to clear out the memory allocated for the object’s properties by setting them to zero. This avoids the usual problem of memory containing garbage from whatever was stored before, but is not enough to initialize an object completely.

创建对象时,需要调用alloc方法,返回的类型是id,id是一个只想对象的指针,它表示“某一类对象”,但比较特殊的是不需要加星号。

alloc方法另一个作用是讲对象中的属性归零,这避免了内存垃圾产生的影响。

You need to combine a call to alloc with a call to init, another NSObject method:

- (id)init;

The init method is used by a class to make sure its properties have suitable initial values at creation, and is covered in more detail in the next chapter.

init方法用来确保所有参数都被初始化。

4.Objective-C Is a Dynamic Language(OC是一门动态语言)

Because of Objective-C’s dynamic nature, it doesn’t matter what specific class type you use for that pointer—the correct method will always be called on the relevant object when you send it a message.

id someObject = @"Hello, World!";
[someObject removeAllObjects];

OC是动态语言,这里它举了一个例子,someObject是NSString型对象,没有removeAllObjects方法,但编译器没有报错,只会在运行时抛出异常。这说明OC只在运行时确定方法的调用。

5.Most Properties Are Backed by Instance Variables(大部分属性基于实例变量)

For a property called firstName, for example, the synthesized instance variable will be called _firstName.

In general, you should use accessor methods or dot syntax for property access even if you’re accessing an

object’s properties from within its own implementation, in which case you should use self:

The exception to this rule is when writing initialization, deallocation or custom accessor methods, as described later in this section.

比如属性名为firstName,那么综合的实例变量名为_firstName

一般的,通过self.语法获取属性。

也有例外情况,当我们初始化,销毁,或自定义getter/setter方法时,需要直接访问实例变量,如_firstName。

6.Designated Initializer(指定初始化器)

这部分还没有深入学习。

7.Properties Are Atomic by Default(属性默认是原子的)

Propertyatomicityisnotsynonymouswithanobject’sthreadsafety.

Consider an XYZPerson object in which both a person’s first and last names are changed using atomic accessors from one thread. If another thread accesses both names at the same time, the atomic getter methods will return complete strings (without crashing), but there’s no guarantee that those values will be the right names relative to each other. If the first name is accessed before the change, but the last name is accessed after the change, you’ll end up with an inconsistent, mismatched pair of names.

属性设置为atomic不能保证线程安全,这里举了一个XYZPerson对象的例子。

8.Avoid Strong Reference Cycles(避免循环引用)

A common scenario is that the table view has a reference to its delegate and the delegate has a reference back to the table view, as shown in Figure 3-7 (page 59).

举了一个tableview和delegate的例子说明为什么会发生循环引用。

The way to solve this problem is to substitute one of the strong references for a weak reference. A weak reference does not imply ownership or responsibility between two objects, and does not keep an object alive.

为了避免循环应用,可以使用weak修饰符,如

 @property (weak) id delegate;
NSObject * __weak weakVariable;

9.向weak修饰的对象发送消息的标准方法

NSObject *cachedObject = self.someWeakProperty; //1
if (cachedObject) { //2
 [someObject doSomethingImportantWith:cachedObject]; //3
} //4
cachedObject = nil;

10.Copy Properties Maintain Their Own Copies(拷贝类型属性维护自己的副本)

通过例子说明为什么NSString一般使用copy修饰符。

11.Categories and Class Extension(分类和类扩展)

Categories can be used to declare either instance methods or class methods but are not usually suitable for declaring additional properties.

分类可以什么类方法和实例方法,但不能声明属性。

Unlike regular categories, a class extension can add its own properties and instance variables to a class.

类扩展可以增加属性和实例变量。

属性:

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

实例变量:

@interface XYZPerson () {
    id _someCustomInstanceVariable;
}

12.Check that Optional Methods Are Implemented at Runtime(运行时检查可选方法是否被实现)

If a method in a protocol is marked as optional, you must check whether an object implements that method before attempting to call it.

NSString *thisSegmentTitle;
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)])
{
    thisSegmentTitle = [self.dataSource       titleForSegmentAtIndex:index];
}

当协议中有可选方法时,需要使用respondsToSelector:方法判断是否实现了可选方法。

13.Objects Use Properties to Keep Track of Blocks(block作为属性存到对象中)

property (copy) void (^blockProperty)(void);

You should specify copy as the property attribute, because a block needs to be copied to keep track of its captured state outside of the original scope. This isn’t something you need to worry about when using Automatic Reference Counting, as it will happen automatically, but it’s best practice for the property attribute to show the resultant behavior. For more information, see Blocks Programming Topics .

解释了为什么block属性要用copy修饰。

14.Use __block Variables to Share Storage(使用__block修饰符共享内存区域)

If you need to be able to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration.

__block int anInteger = 42;
void (^testBlock)(void) = ^{
    NSLog(@"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();

block在捕获作用域外的变量时,默认copy变量的值。如果要改变修改变量,需要用__block修饰。

15.Avoid Strong Reference Cycles when Capturing self(block中调用self时避免循环引用)

- (void)configureBlock {
    XYZBlockKeeper * __weak weakSelf = self;
    self.block = ^{
    [weakSelf doSomething];   // capture the weak reference
} }

block中如果向self对象发送消息,会发生循环引用,给出了标准的解决方法。

时间: 2024-08-26 14:58:33

Programming with Objective-C 学习笔记的相关文章

Objective - C学习笔记:UIView的使用方法

1.1 - (void)layoutSubviews; * 当一个控件的frame发生改变的时候就会自动调用 * 一般在这里布局内部的子控件(设置子控件的frame) * 一定要调用super的layoutSubviews方法 1.2 - (void)didMoveToSuperview; * 当一个控件被添加到父控件中就会调用 1.3 - (void)willMoveToSuperview:(UIView *)newSuperview; * 当一个控件即将被添加到父控件中会调用 @interf

Objective - C 学习笔记:UIPickerView 和 UIDatePicker的基本使用

1.UIPickerView 1.1. UIPickerView的常见属性 // 数据源(用来告诉UIPickerView有多少列多少行) @property(nonatomic,assign) id<UIPickerViewDataSource> dataSource; // 代理(用来告诉UIPickerView每1列的每1行显示什么内容,监听UIPickerView的选择) @property(nonatomic,assign) id<UIPickerViewDelegate>

Objective - C 学习笔记:程序启动原理

1.Info.plist常见的设置 * 建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 * 在旧版本Xcode创建的工程中,这个配置文件的名字就叫“Info.plist” * 项目中其他Plist文件不能带有“Info”这个字眼,不然会被错认为是传说中非常重要的“Info.plist” * 项目中还有一个InfoPlist.strings的文件,跟Info.plist文件的本地化相关

objective - C学习笔记: tableView的刷新

1: 数据刷新的总体步骤 1.1: 修改模型数据 1.2: 刷新表格(刷新界面) 2: 刷新表格的方法 // 全局刷新(每一行都会重新刷新) - (void)reloadData; // 局部刷新(使用前提: 刷新前后, 模型数据的个数不变) - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; // 局部删除(使用前提: 模型数据减少的个

Objective - C学习笔记:控制器的管理

1. 如何创建一个控制器 1.1. 控制器常见的创建方式有以下几种 //1.1.1:通过storyboard创建 //1.1.2:直接创建 YHViewController *viewController = [[YHViewController alloc] init]; //1.1.3:指定xib文件来创建 YHViewController *viewController= [[YHViewController alloc] initWithNibName:@"YHViewControlle

Objective - C 学习笔记:消息机制的原理与使用

1.通知中心(NSNotificationCenter) 1.1.每一个应用程序都有一个通知中心(NSNotificationCenter*)实例,专门负责协助不同对象之间的消息通信 1.2.这就是观察者模式(Observer),任何一个对象都可以向通知中心发布通知(NSNotification*),描述自己在做什么.其他感兴趣的对象(Observer观察者)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知 2.通知(NSNotification) 2.1.一个完整的通知

Objective - C 学习笔记:程序启动的完整过程

1. main函数 2. UIApplicationMain * 创建UIApplication对象 * 创建UIApplication的delegate对象 3.1 delegate代理开始处理(监听)系统事件  (没有storyboard) * 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法 * 在application:didFinishLaunchingWithOptions:中创建UIWindow * 创建和

Objective - C 学习笔记:监听文本框TextField的文字改变

* 一个文本输入框的文字发生改变时,文本输入框会发出一个UITextFieldTextDidChangeNotification通知 * 因此通过监听通知来监听文本输入框的文字改变 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextFieldTextDidChangeNotification object:textField]; // textField

iOS 10 Programming Fundamentals with Swift 学习笔记 0

1,a single statement can be broken into multiple lines ,For example, after an opening parenthesis is a good place: print( "world") 2,Swift is a compiled language, the syntax of message-sending is dot-notation. every noun is an object, and every

CUDA C Programming Guide 在线教程学习笔记 Part 2

? 纹理内存使用 ● 纹理内存使用有两套 API,称为 Object API 和 Reference API .纹理对象(texture object)在运行时被 Object API 创建,同时指定了纹理单元.纹理引用(Tezture Reference)在编译时被 Reference API 创建,但是在运行时才指定纹理单元,并将纹理引用绑定到纹理单元上面去. ● 不同的纹理引用可能绑定到相同或内存上有重叠的的纹理单元上,纹理单元可能是 CUDA 线性内存或CUDA array 的任意部分.