V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
BigDogWang
V2EX  ›  问与答

咨询一个 Swift 语法问题

  •  
  •   BigDogWang · 2021-08-04 18:42:42 +08:00 · 1110 次点击
    这是一个创建于 1207 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 UIApplicationDelegate 里,有很多 application 函数。

    函数名都是 application,但是参数不同

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
    

    我大致能猜到是兼容 oc 的语法?但是我想知道这个是什么特性?没有在文档中找到相关说明

    还有这种:

    func getTimeline(for configuration: Self.Intent, in context: Self.Context, completion: @escaping (Timeline<Self.Entry>) -> Void)
    

    完全不了解其中的 for,in 有什么作用

    10 条回复    2021-08-05 14:27:20 +08:00
    BigDogWang
        1
    BigDogWang  
    OP
       2021-08-04 18:49:11 +08:00
    了解了,叫 外部参数名,真他娘的神奇
    BigDogWang
        2
    BigDogWang  
    OP
       2021-08-04 18:49:30 +08:00
    感觉有点无法理解这种特性
    finab
        3
    finab  
       2021-08-04 18:52:52 +08:00
    这些都是 swift 语法

    application 确实是“兼容” oc 。UIApplicationDelegate 本身就是 oc 写的, 对应到 swift 语法就是这样。
    _ 是省略第一个参数的外部参数名,oc 的方法一般第一个参数没有外部参数名
    外部参数名和局部参数名你应该明白吧?

    第二种其实就是普通参数外部名称,方便调用者知道传啥参数,参数可能有啥作用。
    BigDogWang
        4
    BigDogWang  
    OP
       2021-08-04 19:01:16 +08:00
    @finab 感谢解答,现在都明白了,但是还是没有体会到这个特性的好处。以我目前的了解程度,就是多了一种函数重载的机制。

    可能我再读读文档多用用就能明白深层次的含义了?

    对于 Swift 这样兼容 OC 我也是不太理解。不过我不太了解 iOS 开发。

    OC 可以将参数插入函数名之间,所以表现形式是这样,swift 要进行兼容完全可以将函数名合并起来,参数放到一起呀 😂
    BigDogWang
        5
    BigDogWang  
    OP
       2021-08-04 19:02:19 +08:00
    至于方便调用者查看参数作用,文档加 形参 的命名应该也可以了
    mxT52CRuqR6o5
        6
    mxT52CRuqR6o5  
       2021-08-04 19:02:57 +08:00
    第一个是不是函数重载?(没学过 swift )
    qiuzhifei
        7
    qiuzhifei  
       2021-08-04 19:28:22 +08:00 via Android
    函数重载,与 oc 无关
    agagega
        8
    agagega  
       2021-08-04 21:06:31 +08:00
    就是为了兼容 OC 那味,OC 的方法调用在 Runtime 实现成了消息传递 (objc_msgSend),这个鬼畜的语法也刻意做得跟 C 的函数调用不一样,比如下面这个方法:

    - (void)tableView:(UITableView *)tableView
    commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
    forRowAtIndexPath:(NSIndexPath *)indexPath;

    调用的时候差不多是:

    [self tableView:myTable commitEditingStyle:myStyle forRowAtIndexPath:myPath]

    这个方法(消息)的名字其实叫 tableView:commitEditingStyle:forRowAtIndexPath,也叫 selector,就是把每个带冒号的前缀都连在一起。每个冒号后面的就是消息带的参数。

    Swift 继承了这个概念,但又要维持 C++风格的函数调用语法,所以每个参数默认都是具名的,调用的时候要加上名字和冒号。如果是不需要外部名字的,就在前面加个下划线。当然外部名字和内部名字可以不一样,所以你会看到冒号前面有两个名字的情况。像上面那个方法,在 Swift 里原型就是:

    optional func tableView(_ tableView: UITableView,
    commit editingStyle: UITableViewCell.EditingStyle,
    forRowAt indexPath: IndexPath)

    调用起来就变成了

    self.tableView(myTable, commit: myStyle, forRowAt: myPath)

    因为 OC 的方法实际上是没有所谓的「名字」的,而 Swift 有,所以这些官方 API 就把第一个冒号前面的名字拿来当方法名,而把第一个参数设置成非具名的。
    BigDogWang
        9
    BigDogWang  
    OP
       2021-08-04 21:44:02 +08:00
    @agagega 感谢解答!非常详细,谢谢,明白了
    Yunhao
        10
    Yunhao  
       2021-08-05 14:27:20 +08:00 via iPhone
    这个是 Argument Labels,是 Swift 语言设计中的一个重要特性。这个特性本身并不是为了兼容 Oc,主要目的是增加可读性,可以看一看官方文档,例如 API 设计指南: https://swift.org/documentation/api-design-guidelines,看完你应该会明白这个特性的设计初衷是什么。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2779 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 08:32 · PVG 16:32 · LAX 00:32 · JFK 03:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.