iT邦幫忙

1

iOS APP 開發 OC 第二十天,@class 物件互相引用 重現文字獄燒書,蘇軾冤獄而死。

tags: OC 30 day

創建一個類

如何創建一個書的class?
首先點擊add File的按鈕

創建一個Book的 .h .m 檔案。

第一個任務,為Book這個類別添加以下屬性與方法。

property Type
name NSString
authorName NSString
castKnowledge parameter return
Text void void

如何做到呢?

在.h 檔案裡面加入屬性與方法。

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Book : NSObject

/// 書名
@property(nonatomic,retain)NSString *name;

/// 作者名稱
@property(nonatomic,retain)NSString *authorName;

/// 傳播知識
- (void)castKnowledge;
@end

NS_ASSUME_NONNULL_END

property 的屬性
nonatomic:如果寫nonatomic 這個時候生成的setter方法的代碼就不會加線程安全鎖。特點:不安全,效率高。
retain:生成的setter方法的實現就是標準的MRC內存管理代碼。也就是先判斷新舊對象是否為同一個對象。如果不是release舊的 retain 新的。
參考文章

小技巧:
快速加入註解
快捷键:command+option+/

接著定義method。

#import "Book.h"

@implementation Book

- (void)castKnowledge
{
    NSLog(@"書中自有黃金屋,書中自有顏如玉!");
}

@end

還沒結束!!
我們還要配置MRC的設定
配置dealloc,燒書

#import "Book.h"

/// 釋放
@implementation Book
- (void)dealloc
{
    NSLog(@"書被燒了");
    [self.name release];
    [self.authorName release];
    [super dealloc];
}
/// 傳播知識的方法
- (void)castKnowledge
{
    NSLog(@"書中自有黃金屋,書中自有顏如玉!");
}

@end

接著,創建一個Person,並讓它擁有Book

#import <Foundation/Foundation.h>
#import "Book.h"

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject
@property (nonatomic,copy) NSString *message;
@property (nonatomic,copy) NSString *name;
@property (nonatomic,retain) Book *book;
@end
NS_ASSUME_NONNULL_END

設定MRC
讓他過世

@interface Person()
//@property (nonatomic,copy) NSString *message;
@end
@implementation Person
// 只要這個方法被執行,就代表這個對象被回收了
- (void)dealloc
{
    NSLog(@"名字叫做%@的人去了",self.name);
    [self.name release];
    [self.book release];
    [super dealloc];
}
- (void)sayHi{
    NSLog(@"Hi");
}
@end

在這之後,我想讓書友擁有者這個屬性。
我import Person 到 Book裡面。
然後加入一個property。

#import <Foundation/Foundation.h>
#import "Person.h"

NS_ASSUME_NONNULL_BEGIN

@interface Book : NSObject

/// 書名
@property(nonatomic,retain)NSString *name;

/// 作者名稱
@property(nonatomic,retain)NSString *authorName;

@property(nonatomic,retain)Person *owner;

/// 傳播知識
- (void)castKnowledge;
@end

NS_ASSUME_NONNULL_END

奇怪的是預編譯居然報錯了。

這是什麼情況呢?
當兩個文件相互包含的時候,當Person.h 而 Book.h 包含 Person.h這個時候,就會出現循環引用的問題。就會造成無限遞迴的問題,而導致無法編譯通過。

graph LR;
Person --> Book;
Book --> Person;

解決方法:

其中一邊不要使用#import引入對方的頭文件,而是使用@class 類名;
來標注這是一個類,這樣子就可以在不引入對方頭文件的情況下,告訴編譯器這是一個類。

在.m 文件中再import對方的頭文件,就可以使用了。

@class與#import的區別

#import是將指定的文件內容拷貝到寫指令的地方。
@class 並不會拷貝任何內容。只是告訴編譯器這只是一個類別,這樣編譯才可以知道這是一個類。

相互引用的正確姿勢

在 Person.h 加入了 @class Book

#import <Foundation/Foundation.h>
@class Book;
NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject
@property (nonatomic,copy) NSString *message;
@property (nonatomic,copy) NSString *name;
@property (nonatomic,retain) Book *book;
@end
NS_ASSUME_NONNULL_END

這樣的結果很好,蘇東坡去了,書也燒了

但是有個問題

當我在寫這段code的時候,沒有提示。為什麼呢?
因為你至始至終都沒有引入Book的頭文件,這樣怎麼辦呢?
在Person.m裡面import Book.h


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言