Swift Framework gibt die Methodenerweiterung 'mehrdeutige Verwendung von' in lldb zurück


8

Ich habe ein Upgrade auf Xcode 11 und Swift 5 durchgeführt und bin auf ein Problem mit Methodenerweiterungen gestoßen, wenn diese über ein Framework verfügbar gemacht werden. Genauer gesagt, in einem Projekt, das wie folgt strukturiert ist:

-> Main Project
-> Framework created from sources in 'Main Project'
-> Subproject using the above Framework (Sources packaged in the framework are not visible to the sub-project)

Alles wird kompiliert und läuft einwandfrei, aber wenn Debug-Sitzungen für das Teilprojekt ausgeführt werden, werden alle Erweiterungen in 'Framework' zurückgegeben, error: ambiguous use ofwenn sie über die lldb-Befehlszeile aufgerufen werden. Hier ist ein Codebeispiel, um eine Idee zu geben:

Erstellen Sie ein Befehlszeilenprojekt für macOs und fügen Sie ein neues Ziel, 'MagicFramework', und in einer Datei Spells.swift hinzu (stellen Sie sicher, dass die Datei für Main & MagicFramework sichtbar ist).

import Foundation

extension String {
    public func castSpell() -> String {
        return "✨ " + self
    }
}

Erstellen Sie dann ein Unterprojekt 'Wizard' und in einer Datei wizard.swift (nur für Wizard sichtbar):

import Foundation
import MagicFramework


public class Tadaa {

    public func magic(spell:String) -> String {
        return spell.castSpell()
    }
}

Fügen Sie in der Datei main.swift des Assistenten Folgendes hinzu:

import Foundation

let aa = Tadaa().magic(spell: "this is magic")

print(aa)

Sie sollten die folgende Struktur haben:

-> Main project
----> MagicFramework
----> Wizard subproject

Erstellen und führen Sie dann das Sub "Wizard" mit einem Haltepunkt spell.castSpell()in Tadaa. Geben Sie an der lldb-Eingabeaufforderung Folgendes ein:

(lldb)po spell.castSpell()
error: <EXPR>:3:1: error: ambiguous use of 'castSpell()'
spell.castSpell()

Warum?? Dieses Problem trat bei Xcode 10 nicht auf.

Antworten:


7

Meiner bescheidenen Meinung nach kann dies nur ein Fehler sein.

Wenn ich das Beispiel aufstelle, das Sie in Ihrer Frage angeben, kann ich das Problem reproduzieren.

Am Haltepunkt bekomme ich

(lldb) po spell.castSpell()
error: <EXPR>:3:1: error: ambiguous use of 'castSpell()'
spell.castSpell()
^

so wie du es beschrieben hast.

Wenn ich jedoch die Funktion castSpellin lldb nachschlage, erhalte ich:

(lldb) image lookup -vn castSpell
1 match found in /Users/lameyl01/Library/Developer/Xcode/DerivedData/Main-dsjbnoyousgzmrdnqxtxoeyeyzpv/Build/Products/Debug/MagicFramework.framework/Versions/A/MagicFramework:
        Address: MagicFramework[0x0000000000000ab0] (MagicFramework.__TEXT.__text + 0)
        Summary: MagicFramework`(extension in MagicFramework):Swift.String.castSpell() -> Swift.String at Spells.swift:12
         Module: file = "/Users/lameyl01/Library/Developer/Xcode/DerivedData/Main-dsjbnoyousgzmrdnqxtxoeyeyzpv/Build/Products/Debug/MagicFramework.framework/Versions/A/MagicFramework", arch = "x86_64"
    CompileUnit: id = {0x00000000}, file = "/Users/lameyl01/tmp/Main/MagicFramework/Spells.swift", language = "swift"
       Function: id = {0x100000038}, name = "(extension in MagicFramework):Swift.String.castSpell() -> Swift.String", mangled = "$sSS14MagicFrameworkE9castSpellSSyF", range = [0x000000010033fab0-0x000000010033fb21)
       FuncType: id = {0x100000038}, byte-size = 8, decl = Spells.swift:12, compiler_type = "() -> ()"
         Blocks: id = {0x100000038}, range = [0x10033fab0-0x10033fb21)
      LineEntry: [0x000000010033fab0-0x000000010033fabf): /Users/lameyl01/tmp/Main/MagicFramework/Spells.swift:12
         Symbol: id = {0x00000005}, range = [0x000000010033fab0-0x000000010033fb21), name="(extension in MagicFramework):Swift.String.castSpell() -> Swift.String", mangled="$sSS14MagicFrameworkE9castSpellSSyF"
       Variable: id = {0x100000055}, name = "self", type = "Swift.String", location = DW_OP_fbreg(-16), decl = Spells.swift:12

Das bedeutet, dass lldb genau eine Übereinstimmung gefunden hat: Die Erweiterung in der MagicFrameworkBibliothek. Es gibt also keinen Grund, warum dies nicht eindeutig sein sollte.

Der Vollständigkeit halber habe ich auch den Typ der Variablen überprüft, spellwie llbd ihn sieht:

(lldb) frame variable spell
(String) spell = "this is magic"

Zusammenfassend: lldb weiß, dass der Typ String ist. Es weiß, dass castSpellin der Erweiterung eine Funktion definiert ist, und es kennt genau eine Implementierung dieser Funktion. Trotzdem wird die Fehlermeldung angezeigt.

Wenn mir hier also nichts Wesentliches fehlt, muss dies ein lldb-Fehler sein.


Klingt ungefähr richtig :) Vielen Dank für die Details! Wissen Sie, dass es einen Weg gibt, dies zu umgehen?
Alex

1
Sorry Alex, keine Ahnung, wie man das für eine dynamische Bibliothek umgeht. Wenn Sie Ihr MagicFramework jedoch zu einer statischen Bibliothek machen können, sollte dies kein Problem sein (Mach-O-Typ in Build-Einstellungen für das Ziel, stellen Sie sicher, dass Sie Product-> Clean Build Folder ausführen, nachdem Sie diese Einstellung geändert haben)
Lutz

@ Alex und Lutz Danke für diese Frage und Antwort. Ich fand eine schreckliche Arbeit, aber trotzdem eine Arbeit. Ich habe vorübergehend eine Klasse D mit statischen Methoden hinzugefügt, die die Methoden der Erweiterung aufrufen (wobei das Objekt als Parameter verwendet wird) und dann die Erweiterung von dort aus aufrufen. das wird mich durchbringen, bis dies behoben ist.
Aepryus

0

Ich hatte das gleiche Problem mit meiner Erweiterung. In meiner Situation ist dies eine einzelne Funktion, die ich beim Debuggen häufig verwende. Daher habe ich gerade eine globale Funktion erstellt, die in Ihrem Fall nur die Zeichenfolge akzeptiert und diese Erweiterung im Inneren aufruft. Wirklich ähnlich dem, worauf @aepryus im Kommentar zur ersten Antwort hingewiesen hat.

import Foundation

extension String {
    public func castSpell() -> String {
        return "✨ " + self
    }
}

func castSpell(_ string: String) -> String {
    return string.castSpell()
}

Dann benutze es so:

(lldb) po castSpell("this is magic")
"✨ this is magic"

(lldb) 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.