前面有@objc 的函数和没有@objc 的函数之间的区别

Posted

技术标签:

【中文标题】前面有@objc 的函数和没有@objc 的函数之间的区别【英文标题】:difference between function with @objc in front and function doesn't have @objc 【发布时间】:2022-01-12 04:06:09 【问题描述】:

在我项目的一个视图控制器文件中,有两个函数,一个在viewdidload中调用,另一个由Notification和observers调用。这些函数做同样的事情,我想知道我是否摆脱了其中一个函数,尤其是前面没有使用 @objc 的那个。 (否则会出错)

override func viewDidLoad() 
    super.viewDidLoad()
    configureNotifications()
    displayItems()


func displayItems() 
    fetchLiveEvents  [weak self] in
        self?.applySnapshot(animatingDifferences: true)
    


func configureNotifications() 
    NotificationCenter.default.addObserver(self, selector: #selector(updateExistingItem), name: .updateExistingItem, object: nil)


@objc func updateExistingItem() 
    fetchLiveEvents  [weak self] in
        self.applySnapshot(animatingDifferences: true)
    

由于我使用的是通知慢跑,我无法摆脱 updateExistingItem 函数前面的@objc。但是,updateExistingItem 和 displayItems 正在做一些事情,所以我觉得这有点多余,我想从 viewDidLoad 中删除 displayItems 函数,并在 viewdidLoad 中调用 updateExistingItem(可能会更改名称)。

在 Swift 编程中是否有任何约定可以在 @objc 和普通函数做同样的事情时保持它们?还是只是个人喜好,离开他们两个都没关系?

【问题讨论】:

@objc 的那个用于调用#selector 的函数。 是的,所以我必须使用@objc func updateExistingItem 来调用带有#selector 的函数。而不是在viewdidload 中调用displayItems,当我在viewdidload 中写updateExistingItem() 时,它也可以工作。所以我想知道在不使用选择器的情况下使用@objc 调用函数是否可以。如果这不是理想的调用方式,我会在文件中使用func displayItems@objc func updateExistingItem 在函数前添加@objc(如果可能)没有问题。它只是告诉使用桥接,Objective-C 代码可以调用它。作为“纯粹的 Objective-C 代码”,或者带有 #selector 的底层代码(这是“遗留”的东西,因为 Swift 基于以前的 Objective-C API 和一些机制)。 @Larme 我明白了!所以,我会在我的项目中保留@objc 的那个。非常感谢!! 【参考方案1】:

viewDidLoad 仅在屏幕存在时调用一次,如果您通过推送视图控制器或呈现控制器进入另一个屏幕并返回到该控制器,viewDidLoad 没有触发它永远不会再次调用,直到下一次运行/终止应用程序并再次打开。

因此,当此屏幕出现时,通知会调用您的函数以再次运行。

// just called once 
      override func viewDidLoad() 
        super.viewDidLoad()
        configureNotifications()
        displayItems()
      
// just called every time when you popped a viewController or tap on tab bar items using tabbar controller


        override func viewWillAppear() 
            super.viewDidLoad()
            displayItems()
          

在您的场景中,您可能会通过显示其他屏幕并在那里执行一些功能并调用要在此屏幕上触发的通知来返回此屏幕,因此如果您通过全屏模式演示样式显示屏幕,则不会触发任何内容 这就是为什么调用通知再次开始显示项目的原因

       override func viewDidLoad() 
        super.viewDidLoad()
        configureNotifications()
        displayItems()
    
    

// called once 
    func displayItems() 
        fetchLiveEvents  [weak self] in
            self?.applySnapshot(animatingDifferences: true)
        
    
    

    func configureNotifications() 
        NotificationCenter.default.addObserver(self, selector: #selector(updateExistingItem), name: .updateExistingItem, object: nil)
    
    

// called every time when you trigger notifcation
    @objc func updateExistingItem() 
        fetchLiveEvents  [weak self] in
            self.applySnapshot(animatingDifferences: true)
        
    

【讨论】:

以上是关于前面有@objc 的函数和没有@objc 的函数之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

swift之@objc

inline hook之fishhook objc_msgSend

`objc_autoreleasePoolPush()` 和 `objc_autoreleasePoolPop()` 函数和 `@autoreleasepool` 块

为什么objc_msgSend必须用汇编实现

如何使用其他 objc 函数的变量? (长按并添加按钮)

在 Swift 中使用带有 UnsafeMutableRawPointer 或 UnsafeMutablePointer 参数的 ObjC 函数?