簡體   English   中英

Objective-C:使用弱引用

[英]Objective-C: work with weak references

我有幾節課: 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

及其實現Book.m:

#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

我有委托類Genre,因此,為了避免強引用周期, BookGenre屬性必須很弱

此時在Book.m初始化程序中:

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

它將為零,因為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

我的問題是“在屬性流派中存儲流派對象(genreName->流派構造函數->流派對象)的最佳方法是什么?如何在不使用構造函數分配弱屬性的情況下存儲它?”


解決方案:就我而言,這是流派的集合,而我的弱屬性引用是我集合中的一個對象。

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]];

一種解決方案是使體裁屬性成為強引用。

如果您確實需要使流派成為弱引用,則可以通過將所有流派存儲在表中並使用類似以下方式的靜態方式來訪問它們來解決此問題:

_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

要記住的規則是-強屬性增加引用計數,而弱屬性不增加-當引用計數變為0時,將釋放適當的屬性。 因此,就Genre而言-在您的代碼中,由於沒有強引用,因此將其釋放。 解決的方法實際上是讓流派被另一個階級“擁有”。 此類將管理類型,創建它們並對其進行嚴格引用,例如在一系列類型中。 您的“強”類型將與初始化程序一起傳入,然后弱引用是正確的方法,可以防止保留周期,但是通過Genre屬性已經具有的強屬性可以防止取消分配-這樣有意義嗎?

從某種意義上說,將您的對象視為需要一個“所有者”類是有意義的,在該類中定義了使它們保持活動狀態的強引用。 然后,當傳遞給其他類(如Book類)時,這些類的引用很弱,如您所說的那樣會阻止保留周期。 書類不是所有者,但其他人不是-因此它不會消失。

弱引用不會創建引用計數。 如果僅弱引用某個對象,則將釋放該對象。 這意味着,如果要使對象保持活動狀態,可以使用強引用,也可以使用強引用將其存儲在其他位置。

您可以使用弱引用來避免引用周期,也可以避免針對當前處於其他位置但可能在某些時候消失的對象。 就您而言,使用弱引用將使您無法正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM