Swift 内存管理是如何工作的?

2024-03-07

具体来说,Swift 内存管理如何使用委托模式与选项一起工作?

由于习惯了用 Objective-C 编写委托模式,我的本能是让委托weak。例如,在 Objective-C 中:

@property (weak) id<FooDelegate> delegate;

然而,在 Swift 中执行此操作并不是那么简单。

如果我们有一个看起来很普通的协议:

protocol FooDelegate {
    func doStuff()
}

我们不能将这种类型的变量声明为弱:

weak var delegate: FooDelegate?

产生错误:

“weak”不能应用于非类类型“FooDelegate”

所以我们要么不使用关键字weak,这允许我们使用structs and enums作为代表,或者我们将协议更改为以下内容:

protocol FooDelegate: class {
    func doStuff()
}

这允许我们使用weak,但不允许我们使用structs or enums.

如果我不让我的协议成为类协议,因此不要使用weak对于我的变量,我正在创建一个保留周期,对吗?

是否有任何可以想象的原因,为什么任何打算用作委托协议的协议不应该是类协议,以便这种类型的变量可以weak?

我主要是问,因为在授权部分Apple 关于 Swift 协议的官方文档 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_415,他们提供了一个非类协议和用作其类的委托的非弱变量的示例:

protocol DiceGameDelegate {
    func gameDidStart(game: DiceGame)
    func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
    func gameDidEnd(game: DiceGame)
}
class SnakesAndLadders: DiceGame {
    let finalSquare = 25
    let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
    var square = 0
    var board: [Int]
    init() {
        board = [Int](count: finalSquare + 1, repeatedValue: 0)
        board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
        board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
    }
    var delegate: DiceGameDelegate?
    func play() {
        square = 0
        delegate?.gameDidStart(self)
        gameLoop: while square != finalSquare {
            let diceRoll = dice.roll()
            delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
            switch square + diceRoll {
            case finalSquare:
                break gameLoop
            case let newSquare where newSquare > finalSquare:
                continue gameLoop
            default:
                square += diceRoll
                square += board[square]
            }
        }
        delegate?.gameDidEnd(self)
    }
}

我们是否应该将此视为 Apple 认为我们应该使用结构体作为委托的暗示?或者这只是一个糟糕的例子,实际上,委托协议应该声明为仅类协议,以便委托对象可以持有对其委托的弱引用?


我们是否应该将此视为 Apple 认为我们应该使用结构体作为委托的暗示?或者这只是一个糟糕的例子,实际上,委托协议应该声明为仅类协议,以便委托对象可以持有对其委托的弱引用?

事情是这样的。在现实生活中的 Cocoa 编程中,委托很可能是一个现有的类。它是一个类,因为它的存在是为了某些只有类才能满足的其他目的 - 因为可可需要它.

例如,通常以 iOS 为例,一个视图控制器需要充当另一个视图控制器的委托,以便在它们之间来回安排消息。视图控制器的所有权由视图控制器层次结构决定,而不是由其他任何东西决定。所以,在 Swift 中,就像在 Objective-C 中一样,你有better做到这一点delegate财产weak,因为如果一个视图控制器突然夺取了另一个视图控制器的内存管理所有权,那将是可怕的!

因此,在 Cocoa 框架的现实世界中,存在不正确的所有权或保留周期的严重危险。这就是问题所在weak解决。但正如你所说,它只适用于课程。

然而,书中的例子是关于一些生活在抽象的人造 Swift 世界中的对象。在那个世界中,只要您不面临循环(保留循环)的危险,就没有理由不使用结构,也没有理由担心内存管理。但那个世界并不是您通常编程的世界!这个世界并不是你的 Objective-C 委托模式所来自和所属的框架 Cocoa 世界。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift 内存管理是如何工作的? 的相关文章

  • Audiokit 修剪音频

    我正在制作音频编辑应用程序 我想修剪我的音频 对于音频编辑 我使用 AudioKit 框架 但我在教程和示例中找不到如何使用此框架修剪音频 异步导出允许设置开始和结束样本 https github com AudioKit AudioKit
  • CIAdditionCompositing 给出不正确的效果

    我正在尝试通过平均其他几个图像来创建图像 为了实现这一点 我首先将每个图像变暗 其系数等于我平均的图像数量 func darkenImage by multiplier CGFloat gt CIImage let divImage CII
  • skView.ignoreSiblingOrder 在 swift 中的重要性/效率?

    这样做有多重要 高效skView ignoreSiblingOrder true初始化场景时 现在 我将其设置为 true 但由于某种原因 当我从 MainMenu 场景启动 GameScene 时 它 会在我的角色之前加载背景 即使背景的
  • 如何在 Swift Playgrounds 中获得弹出对话框

    我想知道如何在 Swift 中弹出一个对话框游乐场 是的 必须在 Playgrounds 中 我尝试了以下代码 直接来自 AppleDevs 站点 然而 无论我如何尝试 self tag always抛出错误 谁能帮我这个 import U
  • CustomNSError 协议有什么作用以及为什么我应该采用它?

    什么是CustomNSError协议的用途以及为什么我应该采用它 Apple提供的文档仅指出 描述错误类型 具体提供域 代码和 用户信息字典 我已经在谷歌上搜索过 但找不到与我的问题相关的任何内容 每种类型都符合Error协议是隐含地桥接的
  • Swift 中的 viewWillLayoutSubviews

    我正在尝试翻译SKScene scene GameScene sceneWithSize skView bounds size 进入 swift 但我收到错误 sceneWithSize 不可用 使用对象构造 SKScene size 我在
  • 二元运算符“/”不能应用于两个(Int)操作数[重复]

    这个问题在这里已经有答案了 我得到了Binary operator cannot be applied to two Int operands当我将以下代码放入 Xcode 中的 Swift Playground 时出错 func sumO
  • xcode 9.0.1 / swift 4,没有使用 Objective-C 选择器 'onClick:forEvent:' 声明的方法 [重复]

    这个问题在这里已经有答案了 I use swift 4为了构建我的 UI 我创建了一个UIButton并想为其添加一个目标 但编译器会抛出警告 No method declared with Objective C selector onC
  • Swift:协议、结构、类

    我开始学习 Swift 语言 但在理解协议 结构和类方面遇到了困难 我来自 Android 方面的编程 所以我相信 Swift 协议基本上是 Java 接口 其中每一个的正确用例是什么 这些类比并不 完全 正确 但这就是我所理解的要点 是的
  • 循环多个 UIAlertController

    在某些情况下 我的应用程序需要显示多个警报消息 错误消息在启动时收集 并且需要一次向用户显示一条 当第一个被确认后 应该呈现下一个 问题在于 显然 它们都试图同时执行 有没有一种聪明的方法可以同步执行此操作 这是一些简单描述我想要做的事情的
  • iOS Swift 和 reloadRowsAtIndexPaths 编译错误

    我与 xCode Swift 陷入僵局并刷新 UITableView 的单行 这条线有效 self tableView reloadData 而这条线没有 self tableView reloadRowsAtIndexPaths curr
  • 在 UITableView 的部分标题文本下方添加一些边距

    我已经设计了标题文本的样式 func tableView tableView UITableView cellForRowAtIndexPath indexPath NSIndexPath gt UITableViewCell let ce
  • 如何将自定义 C 代码放入 SwiftPM 包中?

    我正在尝试将 C 代码打包到 Swift 模块中 我们称之为CModule 一旦我将其放入项目的基本文件夹中 Swift模块 并配置了搜索路径 我可以在 Swift 文件中自动完成工作 并检测错误 警告 问题是 导入时它无法识别该模块 并且
  • 具有动态警报正文的快速本地通知

    所以我可以创建一个像这样的本地通知 var localNotification UILocalNotification localNotification fireDate NSDate timeIntervalSinceNow 7 loc
  • Xcode 错误 - 架构 x86_64 的未定义符号?

    我正在运行 Swift 4 和 Xcode 9 beta 我收到此错误 但我不知道如何解决它 我什至不知道这是什么意思 Undefined symbols for architecture x86 64 T0So22AVCapturePho
  • 删除派生数据文件夹后,Xcode 不断重新创建派生数据文件夹

    自动完成功能在 Xcode 6 中不再起作用 我四处搜索 发现删除派生数据文件夹可以解决此问题 每次我删除它时 它都会回来 然后就不会再自动完成了 有什么建议么 Thanks 没关系 我解决了这个问题 我没有声明需要在类内的方法中使用的变量
  • 如何右对齐 UILabel?

    Remark 实施 myLabel textAlignment right does not解决了我的问题 这不是我所要求的 我想要实现的是让标签对齐右对齐 为了更清楚地说明 这就是如何left对齐外观 就是这样justify对齐外观 if
  • 对成员“buildBlock()”的引用不明确

    我一直在尝试使用 Swift UI 为 iOS 13 制作一个应用程序 但我不断收到这个奇怪的错误 对成员 buildBlock 的引用不明确 无论我做什么 错误都不会消失 我尝试一次对代码段进行注释 以查看哪一部分可能导致了问题 但唯一有
  • 在 swift 中将简单字符串转换为 JSON 字符串

    我知道有一个同标题的问题here https stackoverflow com questions 30825755 convert string to json string in swift 但在那个问题中 他试图将字典转换为 JSO
  • Swift 中的柯里函数

    我想创建一个返回柯里函数的函数 如下所示 func addTwoNumbers a Int b Int gt Int return a b addTwoNumbers 4 b 6 Result 10 var add4 addTwoNumbe

随机推荐