关于惰性实例化和便捷方法

发布于 2024-12-21 05:18:01 字数 774 浏览 1 评论 0原文

假设您有一个 Singleton Constants 类,您希望在整个应用程序中使用它的实例。

因此,在 someClass 中,我们可以引用 [Constants instance] someCleverConstant];

键入此内容很快就会过时,并且获得实例的快捷方式会很好。

  • someClass 中,我们可以声明 @property (nonatomic,weak, readonly) Constants *constants;
  • 以及实例的 getter
-(常量*) 常量 {
  if(常量 == nil) 
    常量 = [常量实例];
  返回常量;
}

这种方式在 someClass 中,因此我们可以引用 constants.someCleverConstant; 而不是

对此有几个问题:

  • 我所描述的方法是否合理?
  • 声明属性weak是否正确?
  • 我所描述的内容是否存在任何性能问题?直接调用实例实际上会更好吗?
  • 考虑这样一种情况,您有 20 个类,每个类都需要有自己的指向 Constants 实例的指针。那么这个方法行得通吗?

感谢您抽出时间。

Assume you have a Singleton Constants class, instance of which you'd like to use throughout your application.

In someClass, therefore we can reference [Constants instance] someCleverConstant];

Typing this gets old really quick and it would be nice to get a shortcut to the instance.

  • In someClass, we can declare @property (nonatomic, weak, readonly) Constants *constants;
  • And a getter to the instance
-(Constants*) constants {
  if (constants == nil) 
    constants = [Constants instance];
  return constants;
}

This way in someClass, therefore we can reference constants.someCleverConstant; instead

A few questions on this:

  • Is what i described a reasonable approach?
  • Is it correct to declare a property weak?
  • Is there any performance concerns with what i have described? Would it actually be better to call instance directly?
  • Consider a situation where you have 20 classes, each needing it's own pointer to Constants instance. Would this approach work then?

Thank you for your time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

呆橘 2024-12-28 05:18:01

在@vinceburn之后,我将使用以下示例来表示常量,并使用单例来表示更复杂的结构。

// Constants.h
// Replace PSMyApp for something more useful. e.g. company/name initials followed by app/class

// String example
NSString * const PSMyAppString = @"constantString"; 

// Logically related integers
typedef enum {
   PSMyAppRelatedValuesOne = 0,
   PSMyAppRelatedValuesTwo,
   PSMyAppRelatedValuesThree
} PSMyAppRelatedValues;

// Float example
const CGFloat PSMyAppFloat = 0.3f;

// Integer that has no related values
const NSInteger PSMyAppInteger = 2;

我更喜欢这个而不是#define,因为我可以自动完成和编译器检查,并且它更自然地适合Apple在某些UIKit类中的处理方式。

Following @vinceburn I would use the following example for constants and a singleton for more complex structures.

// Constants.h
// Replace PSMyApp for something more useful. e.g. company/name initials followed by app/class

// String example
NSString * const PSMyAppString = @"constantString"; 

// Logically related integers
typedef enum {
   PSMyAppRelatedValuesOne = 0,
   PSMyAppRelatedValuesTwo,
   PSMyAppRelatedValuesThree
} PSMyAppRelatedValues;

// Float example
const CGFloat PSMyAppFloat = 0.3f;

// Integer that has no related values
const NSInteger PSMyAppInteger = 2;

I prefer this over #define as I get auto completion and compiler checking and it fits more naturally with the way Apple does thing in some of the UIKit classes.

慕烟庭风 2024-12-28 05:18:01

仅使用全局变量或函数似乎需要做很多工作。我认为这两种方法都是更合理的方法。

This seems like a lot of work to get around just using a global variable or function. I think either of those is a more reasonable approach.

べ繥欢鉨o。 2024-12-28 05:18:01

您可以只创建一个指向单例的全局指针,例如 [NSApplication sharedApplication]NSApp

想必您已经在

static Constants * defaultInstance = nil;

实现文件的顶部找到了类似的内容。如果删除 static,并在标头中声明该变量(将定义保留在 .m 文件中):

@interface Constants : NSObject
// etc.
@end

extern Constants * defaultInstance;

然后您可以通过名称 defaultInstance (不过,可能想更改该名称)在导入标头的任何文件中(无论如何您都必须这样做)。您必须在程序的早期某个地方调用您的单例设置方法(+instance 或其他),例如 -applicationDidFinishLaunching 以确保之前设置了指针你用它。

  • 我所描述的方法合理吗?

我认为还有其他更好的方法,如上所述和 Paul.s 的回答。

  • 声明属性weak是否正确?

是的,拥有这个指针的类不需要拥有它,因为单例拥有它自己;

  • 我所描述的内容是否存在任何性能问题?直接调用实例实际上会更好吗?

无论哪种方式,[Constants instance]self.constants 您都在发送消息。第一次执行 self.constants 时,您会执行两个操作。不过,这些都不应成为真正的问题。

  • 考虑这样一种情况,您有 20 个类,每个类都需要有自己的指向 Constants 实例的指针。那么这个方法行得通吗?

对我来说,它似乎笨拙且不优雅。

You could just create a global pointer to your singleton, like NSApp for [NSApplication sharedApplication].

Presumably you've already got something like

static Constants * defaultInstance = nil;

at the top of your implementation file. If you remove the static, and declare the variable in your header (keeping the definition in the .m file):

@interface Constants : NSObject
// etc.
@end

extern Constants * defaultInstance;

You can then access the singleton instance via the name defaultInstance (probably want to change that name, though) in any file that imports the header (which you must be doing anyways). You'll have to call your singleton setup method (+instance or whatever) somewhere very early in your program, such as -applicationDidFinishLaunching to be sure that the pointer is set before you use it.

  • Is what I described a reasonable approach?

I think there are other, better approaches, described above and in Paul.s's answer.

  • Is it correct to declare a property weak?

Yes, the class that has this pointer doesn't need to own it, because the singleton owns itself;

  • Is there any performance concerns with what i have described? Would it actually be better to call instance directly?

Either way, [Constants instance] or self.constants you're doing a message send. The first time you do self.constants, you're doing two. None of this should be a real concern, though.

  • Consider a situation where you have 20 classes, each needing it's own pointer to Constants instance. Would this approach work then?

To me, it seems unwieldy and inelegant.

就像说晚安 2024-12-28 05:18:01

对于常量,我更喜欢使用这样的 .h 文件

// ConstanteDef.h
#pragma mark Entity Name Constante
#define kItemInfos @"ItemInfos"
#define kCategorie_DItems @"Categorie_DItems"
#define kCommerce @"Commerce"
#define kListe @"Liste"
#define kListeItem @"ListeItem"
#define kPrixElement @"PrixElement"
#define kTypeDe_CommerceOuListe @"TypeDe_CommerceOuListe"

,而我会使用 Singleton 返回更复杂的元素。
这是我用核心数据简化我的生活而制作的单例,而不是到处重写相同的代码。

@interface CoreDataController : NSObject {

NSManagedObjectContext *leManagedObjectContext;
NSManagedObjectModel *leManagedObjectModel;

@private
Commerce_MO *leCommerceAucun;
}
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;

#pragma mark Objet par Défaut
@property (nonatomic, retain, readonly) Commerce_MO *commerceAucun;

#pragma mark Nouvel Objet
//  new = retain count = 1, celui qui commande est responsable de la mémoire.
- (id)newMOforClass:(Class)uneClasse;   //  Pas le mieux, mais pourrais servir pendant le run time.  Retourne nil si uneClasse ne correspond pas à quelque chose.
- (PrixElement_MO *)newPrixElement;
- (ItemInfos_MO *)newItemInfos;
- (Commerce_MO *)newCommerce;
- (Liste_MO *)newListe;
- (ListeItem_MO *)newListeItem;

#pragma mark Singleton call
+ (CoreDataController *)sharedCoreDataController;
@end

因此,在我的代码中,当我需要创建一个新实体时,我只需要这样做:

CoreDataController *cdc = [CoreDataController sharedCoreDataController];
Liste_MO * = [cdc newListe];

有关单例概念的更多信息,请查看 此处 在 Apple 文档的创建单例部分实例,并仔细查看他们提供的用于创建单例的代码,这应该可以回答您关于它的弱或强链接的询问。
但本质上,严格的单例实现只会在应用程序的整个持续时间内创建该类的一个实例。因此,如果你有 100 个对象指向它,它不会改变你的内存占用,因为只有 1 个单例,但如果你有这 100 个对象,肯定会影响你的内存。

For constant I prefer to use a .h file like this

// ConstanteDef.h
#pragma mark Entity Name Constante
#define kItemInfos @"ItemInfos"
#define kCategorie_DItems @"Categorie_DItems"
#define kCommerce @"Commerce"
#define kListe @"Liste"
#define kListeItem @"ListeItem"
#define kPrixElement @"PrixElement"
#define kTypeDe_CommerceOuListe @"TypeDe_CommerceOuListe"

While I would use the Singleton to return me more complex element.
Here is a singleton that I've made to simplify my live with core data, instead of rewriting the same code everywhere.

@interface CoreDataController : NSObject {

NSManagedObjectContext *leManagedObjectContext;
NSManagedObjectModel *leManagedObjectModel;

@private
Commerce_MO *leCommerceAucun;
}
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;

#pragma mark Objet par Défaut
@property (nonatomic, retain, readonly) Commerce_MO *commerceAucun;

#pragma mark Nouvel Objet
//  new = retain count = 1, celui qui commande est responsable de la mémoire.
- (id)newMOforClass:(Class)uneClasse;   //  Pas le mieux, mais pourrais servir pendant le run time.  Retourne nil si uneClasse ne correspond pas à quelque chose.
- (PrixElement_MO *)newPrixElement;
- (ItemInfos_MO *)newItemInfos;
- (Commerce_MO *)newCommerce;
- (Liste_MO *)newListe;
- (ListeItem_MO *)newListeItem;

#pragma mark Singleton call
+ (CoreDataController *)sharedCoreDataController;
@end

So in my code when I need to create a new entity I just need to do this :

CoreDataController *cdc = [CoreDataController sharedCoreDataController];
Liste_MO * = [cdc newListe];

For more on the Singleton concept, Look HERE in the Apple documentation at the section Creating a Singleton Instance, and look closely at the code they are giving to make a singleton, that should answer your interrogation about weak or strong link to it.
But in essence a strict singleton implementation will only have one instance of that class created for the whole duration of the application. So if you got 100 objects pointing to it doesn't change your memory foot print, there is only 1 singleton, but if you have thoses 100 objects that will definitely impact your memory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文