Closed NCrusher74 closed 4 years ago
Did you delete the UI test sources without deleting the product? When I try to build the tests, I get this message:
error: Build input file cannot be found: '[...]/Library/Developer/Xcode/DerivedData/AudiobookTagger-fkklszcwpbwduvbwktwklzkhuyfw/Build/Products/Debug/AudiobookTaggerUITests-Runner.app/Contents/PlugIns/AudiobookTaggerUITests.xctest/Contents/MacOS/AudiobookTaggerUITests' (in target 'AudiobookTaggerUITests' from project 'AudiobookTagger')
I... don't remember doing that? Let me see what I can do.
If there are leftovers in DerivedData on your machine, you may have to do Product → Clean Build Folder (⇧⌘K) before you see the same error message I see.
I removed the product. It's building for me, even after cleaning the build folder.
weird, I really don't remember deleting those. But I can see why I would, I don't really intend for this to have an interface.
I have to run out the door to a meeting. I'll be back in a couple of hours to try to fix it if that didn't work.
Is this what you are asking how to do?
// ...
import ID3TagEditor
// ...
enum AudiobookTag {
// ...
var id3Tag: FrameName {
switch self {
case .BookTitle:
return .Title
// ...
}
}
}
Any time you see .something
(with a leading dot) in isolation, it is really a SomeType.something
. It is just that SomeType
can be left out if the compiler can already tell from the context what the omitted type has to be.
let x = SomeType.something // ✓
let y = .something // ✗
let z: SomeType = .something // ✓
func useAny(_ argument: Any) {}
useAny(SomeType.something) // ✓
useAny(.something) // ✗
func useSpecific(_ argument: SomeType) {}
useSpecific(.something) // ✓
let a = [SomeType.something: "..."] // ✓
let b = [.something: "..."] // ✗
let c: [SomeType: String] = [.something: "..."] // ✓
if that didn't work.
It did.
Okay, yes, that is what I was hoping to do.
So, MP42MetadataItemKey<whatever>
is a String
, so my audiobookAuthor
(or whatever) type will need to conform to both FrameName
and String
correct? Or will I need to make FrameName
and String
conform to a whole new protocol before I can consider them to be on equal footing?
(I still haven't actually used custom protocols in practice yet, so I'm sort of guessing here. I've come close to it, but haven't ever actually needed to implement it yet at the end.)
Nevermind. I was being stupid. Instead of making it a computed property that returns FrameName
I can make it a function with a parameter of FrameName
that returns a String.
Despite the lack of new code in evidence here, I actually spent all day yesterday on this, trying and discarding a bunch of different ways to create a common value for the metadata items I'm dealing with.
Surprisingly, it's ID3TagEditor, rather than MP42Foundation, that is presenting a stumbling block.
With MP42Foundation, the item it reads or writes is identified the same way, by the
MP42MetadataKey<whatever>
. And you can pretty much access that from anywhere, not simply in the context of a read or write command. So if you wanted to sayaudiobookAuthor = MP42MetadataKeyArtist
that's pretty much all you need to do.With ID3TagEditor it's a little tougher. There doesn't seem to be a way to access the metadata frames outside the context of a
id3TagEditor.read
orid3TagEditor.write
command, at least not that I can find. Which is making it hard to equate to a simple identifier likeaudiobookAuthor.
So then I tried to make the common factor a
read
orwrite
function. But again, I can't seem to find a way to put them on equal footing.I don't know if I'm going about this the wrong way or what. I just need to find a common way to handle these values so that when I use AudiobookTagger as a package dependency for my apps, I can access the metadata from (or destined for) the tag I want regardless of if I'm dealing with an .mp3 or an .m4b file.