Objective-C:使用弱引用



我有几个类: BookPublisherAuthorGenre

所以这里是主类 Book.h:

#import "Publisher.h"
#import "Author.h"
#import "Genre.h"
@interface Book : NSObject 
@property (nonatomic, strong) NSString *bookName;
@property (nonatomic, strong) Author *author;
@property (nonatomic, strong) Publisher *publisher;
@property (nonatomic, weak) Genre *genre;
- (instancetype)initWithBookName:(NSString *)name andAuthorName:(NSString *)authorName
      andPublisher:(NSString *)publisherName andGenreName:(__strong NSString *)genreName;
- (NSString *)description;
@end

和他的实施书:

#import "Genre.h"
#import "Book.h"
#import <Foundation/Foundation.h>
@implementation Book 
- (instancetype)initWithBookName:(NSString *)name andAuthorName:(NSString *)authorName
  andPublisher:(NSString *)publisherName andGenreName:(__strong NSString *)genreName{
    self = [super init];
    if (self) {
        _bookName = [name copy];
        _author =  [[Author alloc] initWithAuthorName:authorName];
        _publisher = [[Publisher alloc] initWithPublisherName:publisherName];
        _genre = [[Genre alloc] initWithGenreName:genreName];
    }
    return self;
}
- (instancetype)init {
    return [self initWithBookName:@"unnamed" andAuthorName:@"unnamed" andPublisher:@"unnamed" andGenreName:@"unnamed"];
}
- (NSString *)description {
    return [NSString stringWithFormat: @"Book: %@, Author: %@, Genre: %@", self.bookName, self.author, self.genre];
}
@end

我有委托类 - 流派,所以为了避免强引用周期,BookGenre属性必须是的。

此时,在 Book.m 初始值设定项中:

   _genre = [[Genre alloc] initWithGenreName:genreName];

它将为 nil,因为Genre实例将在分配后立即解除分配。

根据Dan的评论,这是我的Genre.h:

#import <Foundation/Foundation.h>
@class Book;
@interface Genre : NSObject
@property (nonatomic, strong) NSString *genreName;
@property (nonatomic, strong) NSArray <Book *> *books;
- (instancetype)initWithGenreName:(NSString *)name andBooks:(NSArray <Book *>*)books;
- (instancetype)initWithGenreName:(NSString *)name;
- (NSString *)description;
@end

我的问题是"在属性流派中存储流派对象(流派名称 ->流派构造函数 ->流派对象)的最佳方法是什么,如何在不使用构造函数分配给弱属性的情况下存储它?


解决方案:在我的情况下,它是流派的集合,我将我的弱属性引用到我的集合中的一个对象。

Genre * genre1 = [[Genre alloc]initWithGenreName:@"Comedy"];
Genre * genre2 = [[Genre alloc]initWithGenreName:@"Drama"];
Genre * genre3 = [[Genre alloc]initWithGenreName:@"Fantastic"];
Genre * genre4 = [[Genre alloc]initWithGenreName:@"National"];
NSArray <Genre*> *genres = @[genre1, genre2, genre3, genre4];
Book *book1 = [[Book alloc] initWithBookName:@"Book #3!" andAuthorName:@"Grinch Burs" andPublisher:@"Ableton" andGenre:[genres objectAtIndex:0]];

要记住的规则是 - 强属性会增加引用计数,而弱属性不会 - 当引用计数达到 0 时,将解除分配适当的属性。 因此,在流派的情况下 - 在代码中,没有对它的强引用,因此它是解除分配的。 解决方案实际上是让流派由另一个类"拥有"。 这个类将管理流派,创建它们并保持对它们的强引用,也许是例如一系列流派。 您的"强"流派将与初始值设定项一起传入,然后弱引用是正确的方法,防止保留周期,但 Genre 属性已经具有的强属性阻止了 dealloc - 这有意义吗?

在某种程度上,将对象视为需要"所有者"类是有意义的,其中定义了强引用以使它们保持活动状态。 然后,当传递给其他类(如 Book 类)时,这些类具有弱引用,这会阻止您所说的保留周期。 书课不是所有者,而是其他人 - 所以它不会消失。

一种解决方案是使流派属性成为强有力的参考。

如果你真的需要使流派成为一个弱参考,您可以通过将所有流派存储在表中并使用如下所示的静态访问它们来解决此问题:

_genre = [Genre forName:genreName]

然后,静态 forName 方法将在所有流派的表中查找正确的流派。由于将流派存储在表中会保留对象,因此不会在分配时立即释放。

@implementation Genre
static NSDictionary* genres;
+ (void) initGenres {
    // initialize the dictionary and insert all genres 
    // or just initalize the dictionary and insert genres on demand
}
+ (Genre*) forName: (NSString*) genreName {
    if (!genres) {
        [Genre initGenres];
    }
    //lookup the genre in the dictionary and return it
}
@end

弱引用不会创建引用计数。如果只有对对象的弱引用,则将解除分配该对象。这意味着,如果您希望对象保持活动状态,则可以使用强引用,或者使用强引用将其存储在其他地方。

您可以使用弱引用来避免引用循环,以及当前保存在其他位置但可能在某个时间点消失的对象。在您的情况下,使用弱引用是您无法正常工作的。

相关内容

  • 没有找到相关文章

最新更新