使用 #define 替换代码

4

我在我的iOS应用程序中有一块代码,我必须在每个视图中使用 - 不能将其放在函数/方法中 - 所以我想知道是否有任何方法可以使用 #define 并在需要的地方使用其标识符。以下是示例代码。

我想要用 #define 标识符替换的代码:

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification) 
                                             name:ECSlidingViewTopDidAnchorLeft 
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification) 
                                             name:ECSlidingViewTopDidAnchorRight 
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(_gotECSlidingViewTopDidResetNotification)
                                             name:ECSlidingViewTopDidReset 
                                           object:nil];

所以我想知道如何在ViewDidLoad方法中定义并使用它。

你想要一个 #define 里面包含所有三个还是三个不同的 #define? - Anoop Vaidya
@AnoopVaidya - 万能的。 - itsaboutcode
2
为什么不能将它放在函数或方法中? - Simon
@Simon - 很好的问题。并不是我不能定义这个函数,而是同样的函数会在每个文件中重复出现 - 这有点糟糕 - 然后还有相应的方法来处理这些通知。只是想减少最大代码量。 - itsaboutcode
1
你能不能把函数放在 #define 的位置呢?据我所知,#define 有时候会有些棘手,所以我建议使用一个函数代替它(虽然我很久以前用过 C++)。 - default
@itsaboutcode 为什么每个文件都需要重复呢?你可以在自己的头文件中将其定义为NS_INLINE,然后只需导入即可。 - Simon
4个回答

2

这并不是直接回答你的问题,但作为一名曾经处理过预处理器许多困惑的老C++程序员,我建议不要使用 #define 来解决此问题。

有几个选项...

  1. Define a base class (derived from UIViewController) with your two selectors. The selectors can be overridden in your derived classes.

    @interface YourBaseCass : UIViewController

    • (void)viewDidLoad; // Put your add observer logic here
    • (void)_gotECSlidingViewAnchorRightOrRightrNotification;
    • (void)_gotECSlidingViewTopDidResetNotification;

    @end

    @implementation YourBaseCass

    - (void)viewDidLoad //make sure you call me from the derived class
    {
        [super viewDidLoad]
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification)
                                                     name:ECSlidingViewTopDidAnchorLeft
                                                   object:nil];
    
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification)
                                                     name:ECSlidingViewTopDidAnchorRight
                                                   object:nil];
    
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(_gotECSlidingViewTopDidResetNotification)
                                                     name:ECSlidingViewTopDidReset
                                                   object:nil];
    }
    

    @end

  2. Put your functionality in a global static method (if subclassing isn't your thing). This will be easier to debug.

    • (void)addObserversForObject:(id)object{ [[NSNotificationCenter defaultCenter] addObserver:object selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification) name:ECSlidingViewTopDidAnchorLeft object:nil];

      [[NSNotificationCenter defaultCenter] addObserver:object
                                               selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification)
                                                   name:ECSlidingViewTopDidAnchorRight
                                                 object:nil];
      
      [[NSNotificationCenter defaultCenter] addObserver:object
                                               selector:@selector(_gotECSlidingViewTopDidResetNotification)
                                                   name:ECSlidingViewTopDidReset
                                                 object:nil];
      

      }


抱歉代码格式不佳...我似乎无法使不同区域正确对齐。 - HatAndBeard

1

如果代码确实需要完全像这样,那么这应该可以解决问题。否则,您可以为#define添加参数以更改其中的一些内容。

#define identifier do{ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification) name:ECSlidingViewTopDidAnchorLeft  object:nil];\
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification) name:ECSlidingViewTopDidAnchorRight object:nil];\
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_gotECSlidingViewTopDidResetNotification) name:ECSlidingViewTopDidReset object:nil];\
} while (0);

do while 循环确保它可以在单行 if 语句等中使用。 - Fonix
Fonix的评论:你不能只是在表达式周围添加花括号来做同样的事情吗? - xQuare
我因为某些原因记得有个问题与此有关,但现在想不起来了。也许没有问题,但使用do while对我总是有效的。 - Fonix
即使 { 和 } 作为一个块,也不需要循环或块。您可以像我在答案中所做的那样,在一行中使用所有内容。 - Anoop Vaidya
你的答案仍然被视为代码中的3行,如果你在单行if语句或for循环中使用它,可能会导致错误。在这种情况下可能不会这样使用,但这是一个好的练习。(如果你注意到我仍然需要使用's) - Fonix

1
你可以这样使用:
在每行末尾加上空格后加上 \,这样可以防止编译器检查换行或回车键按下。这使得代码易读。然后你可以在方法中的任何地方使用 MY_NOTIFICATIONS。
#define MY_NOTIFICATIONS [[NSNotificationCenter defaultCenter] addObserver:self \
selector:@selector(_gotECSlidingViewAnchorRightOrRightrNotification) \
name:ECSlidingViewTopDidAnchorLeft \
object:nil]; \
\
[[NSNotificationCenter defaultCenter] addObserver:self \
                                         selector:@selector (_gotECSlidingViewAnchorRightOrRightrNotification) \
                                             name:ECSlidingViewTopDidAnchorRight \
                                           object:nil]; \
\
[[NSNotificationCenter defaultCenter] addObserver:self \
                                         selector:@selector(_gotECSlidingViewTopDidResetNotification) \
                                             name:ECSlidingViewTopDidReset \
                                           object:nil]; \

0
不要过度依赖预处理器。这是一种不好的编程风格,经常会导致微妙的混淆。而且你仍然需要在所有这些文件中 #include 宏。
相反,定义一个类来处理通知。
@interface ECSReceptionist
      - (id) initFor: (id) observer;
@end

这个类可能看起来有点轻量级,但你可以随后为它分配一些职责。例如,接待员还可以自行注册通知并处理一些常规事务。
避免使用预处理器:
- 使你的意图更清晰 - 避免了微妙的语法纠结,保持理智 - 让调试变得更容易 - 提供了进一步重构的机会 - 为单元测试提供了一个测试挂钩

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接