0Pricing
Objective-C iOS Development for Legacy & Enterprise Apps · 课时

弱引用与强引用

区分强引用和弱引用,以防止保留环并有效管理对象生命周期。

弱引用与强引用 是 CoddyKit 上的免费 Objective-C iOS Development for Legacy & Enterprise Apps 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Objective-C iOS Development for Legacy & Enterprise Apps 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Objective-C iOS Development for Legacy & Enterprise Apps 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Understanding Object Lifetimes

In Objective-C, managing an object's lifetime is crucial. This means deciding when an object should exist in memory and when it can be safely removed.

References are how we tell the system that we 'care' about an object and want it to stay alive. There are two main types: strong and weak.

Strong References: The Default

A strong reference is the default type for properties and variables in Objective-C when using ARC (Automatic Reference Counting).

  • It signifies 'ownership' of an object.
  • When an object has at least one strong reference, it cannot be deallocated.
  • It increases the object's retain count, ensuring it stays in memory.

Think of it as holding onto something tightly; as long as you hold it, it won't disappear.

Strong Reference Example

Let's see a strong reference in action. The person1 variable holds a strong reference to our Person object. Notice the dealloc method is called when the object is no longer strongly referenced.

#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
- (void)sayHello;
@end

@implementation Person
- (void)sayHello {
    NSLog(@"Hello, my name is %@", self.name);
}
- (void)dealloc {
    NSLog(@"Person %@ is being deallocated.", self.name);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person1 = [[Person alloc] init];
        person1.name = @"Alice";
        NSLog(@"Person '%@' created.", person1.name);
        [person1 sayHello];
        // person1 goes out of scope at the end of @autoreleasepool
        // The Person object will be deallocated.
    }
    return 0;
}

The Problem: Retain Cycles

While strong references are essential, they can lead to a common memory management issue called a retain cycle (or strong reference cycle).

This happens when two or more objects hold strong references to each other, forming a closed loop. Because each object is strongly referenced by another in the cycle, their retain counts never drop to zero, and they are never deallocated.

Illustrating a Retain Cycle

Imagine a Parent object strongly references a Child object, and that Child object also strongly references its Parent.

  • Parent says: "I own Child."
  • Child says: "I own Parent."

Neither can be released because the other is still holding onto it, even if no other part of your app needs them anymore. This leads to a memory leak.

Introducing Weak References

Weak references (declared with __weak or the weak property attribute) are designed to break retain cycles.

  • They do not increase an object's retain count.
  • They do not signify ownership.
  • Crucially, a weak reference automatically becomes nil when the object it points to is deallocated.

This 'nilling out' behavior is very safe and prevents dangling pointers.

Weak Reference Behavior

Observe how a weak reference behaves. Once the last strong reference to an object is released, the object is deallocated, and any weak references pointing to it automatically become nil.

#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
- (void)dealloc;
@end

@implementation Person
- (void)dealloc {
    NSLog(@"Person %@ is being deallocated.", self.name);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *strongPerson = [[Person alloc] init];
        strongPerson.name = @"Bob";
        
        __weak Person *weakPerson = strongPerson;
        
        NSLog(@"Before nil: strongPerson = %@, weakPerson = %@", strongPerson.name, weakPerson.name);
        
        strongPerson = nil; // Release the strong reference
        NSLog(@"Strong reference set to nil.");
        
        if (weakPerson) {
            NSLog(@"Weak Person still exists: %@", weakPerson.name);
        } else {
            NSLog(@"Weak Person is now nil.");
        }
    }
    return 0;
}

Breaking the Retain Cycle

To break a retain cycle, one of the references in the cycle should be weak. In our Parent-Child example, it's common for the 'child' to have a weak reference to its 'parent'.

This way, the parent owns the child, but the child doesn't own the parent, allowing both to be deallocated properly.

#import <Foundation/Foundation.h>

@interface Parent : NSObject
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) id child; // Strong ref to child
- (void)dealloc;
@end

@interface Child : NSObject
@property (strong, nonatomic) NSString *name;
@property (weak, nonatomic) Parent *parent; // Weak ref to parent
- (void)dealloc;
@end

@implementation Parent
- (void)dealloc {
    NSLog(@"Parent %@ is being deallocated.", self.name);
}
@end

@implementation Child
- (void)dealloc {
    NSLog(@"Child %@ is being deallocated.", self.name);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Parent *myParent = [[Parent alloc] init];
        myParent.name = @"Mom";
        
        Child *myChild = [[Child alloc] init];
        myChild.name = @"Alice";
        
        myParent.child = myChild; // Parent strongly references Child
        myChild.parent = myParent; // Child weakly references Parent
        
        NSLog(@"Parent and Child created. Releasing strong variables...");
        // Both objects will be deallocated as strong references from outside
        // the objects are released and the weak link doesn't prevent deallocation.
    }
    return 0;
}

`__weak` vs. `__unsafe_unretained`

You might encounter __unsafe_unretained, another non-owning reference type. However, always prefer __weak.

  • __weak: Automatically becomes nil when the object is deallocated, preventing crashes.
  • __unsafe_unretained: Does NOT become nil. If the object is deallocated, the reference becomes a dangling pointer, leading to crashes if you try to access it.

__weak is the safer and standard choice in modern Objective-C with ARC.

Check Your Knowledge

Which statement best describes the primary purpose of a weak reference in Objective-C with ARC?

Recap: Strong vs. Weak

We've explored the critical difference between strong and weak references:

  • Strong references: Default, signify ownership, increase retain count, keep objects alive.
  • Weak references: Do not signify ownership, do not increase retain count, automatically become nil, and are essential for breaking retain cycles.

Understanding when to use each is key to preventing memory leaks and writing robust Objective-C code.

常见问题解答

「弱引用与强引用」课时是免费的吗?

是的 — 「弱引用与强引用」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Objective-C iOS Development for Legacy & Enterprise Apps 课程的其余内容,请升级到 CoddyKit PRO。 Objective-C iOS Development for Legacy & Enterprise Apps 课程共包含 4 节课。

「弱引用与强引用」这节课中我会学到什么?

区分强引用和弱引用,以防止保留环并有效管理对象生命周期。 你通过在浏览器中直接运行的动手代码来练习 Objective-C iOS Development for Legacy & Enterprise Apps,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Objective-C iOS Development for Legacy & Enterprise Apps 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Objective-C iOS Development for Legacy & Enterprise Apps 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「弱引用与强引用」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Objective-C iOS Development for Legacy & Enterprise Apps 课中编写并运行代码吗?

能。每节 Objective-C iOS Development for Legacy & Enterprise Apps 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 手动保留与释放(MRR)基础
  2. 自动引用计数(ARC)
  3. 弱引用与强引用
  4. 打破代码块中的保留环
← 返回 Objective-C iOS Development for Legacy & Enterprise Apps