Workspace frameworks don't seem to update

I'm refactoring an app for a new version and moved all of the Model files into a separate Project, which is configured as a Framework project. This project is inside a Workspace, which has another separate project with the Views and Controllers for my app. The project with the Views & Controllers (just V&C for brevity from now on) is an iOS app.


I built the model, and then in the V&C project added the Framework under Project->General->Linked Frameworks & Libraries.


When I redesigned the UI for the new version, I instantiated objects from the Project in some of the view controllers and referred to member methods and properties there.


I have since refactored the code in the Model project and re-built it using a different API.


The V&C project, however, still seems to be trying to refer to the older project, with the older API. I know this because I get build errors in the V&C project that tell me that certain methods don't exist, even though they do exist (I can see them in the code I wrote), and sometimes asks if I want to use a different (no longer extant) property instead.


Each file which refers to the objects in the framework has

import FrameworkName


at the top of the file, underneath any UIKit or Foundation or other imports.


In the Model project using the Model Scheme, I have cleaned and then built the Project for Generic iOS device. In the project for V&C, I have removed the linked Framework under General->Linked Frameworks & Libraries, and then re-added it. I also tried dragging the framework from the project navigator for the Model into the Embedded Binaries of the V&C project. I have done a Clean in the V&C project, and each Build (for the time being, just for Generic iOS devices) shows the same errors where the view controller code shows the correct instance methods being called, but the compiler is complaining that the methods don't exist.


When I select the .framework in the Frameworks folder under the V&C project's project navigator, I see the Full Path appears to point to the correct .framework file, and the last modified time/date is correct (today, since I tried again to build against the Generic iOS device in the Model Scheme, just to make sure I hadn't forgotten to do that!).


I am obviously missing something terribly important, but after several days of Google/StackOverflow/Ray Wenderlich searches and banging my head on the desk, I can't for the life of me figure out what it might be.

Accepted Reply

No, it shouldn't be necessary to do anything extreme to keep it working. Don't overlook the possibility that this time it is just a housekeeping error, like forgetting the "public".


If not, the other thing you can try is deleting the ModuleCache subfolder of the DerivedData folder. I guess it's possible that there's a problem there if a same-named module gets created via two different projects.


Other than that, possibilities for ongoing weird behavior include:


— Build settings for include paths or framework paths having some value that Xcode chose to add, that's dragging in the wrong files.


— References to files that are not using the correct form. For example, your reference to the framework should probably be "relative to build products" rather than, say, absolute.


— Target membership checkboxes, in the File tab of the Utilities inspector. When you're still messing around with what files are in what project, it's easy to add a source file to the wrong target.


If you don't find anything obvious, then you should probably also submit a bug report. Even this is happening because of something you did wrong sometime, Xcode shouldn't be so inscrutable that you can't figure it out. Or there could just be a bug.

Replies

I should note that the new methods are marked as public, so it doesn't appear to be an access control problem (as are the classes).

Try doing this:


1. Open the original project (if you still have it) and do a "Clean Build Folder" (Option + the regular Clean). Close the project.


2. Open the framework project alone (that is, not via the workspace), and do a Clean Build Folder. Close the project.


3. Open the V&C project alone (not via the workspace) and Clean Build Folder. Close the project.


4. Open the workspace, and Clean Build Folder.


At this point, you should have no build results left from anything you did before. Now, open the workspace, choose the V&C app scheme, and build it. Presumably, it will still give errors for unknown functions. When it's done, go to the build transcript (Report navigator, Command-8) and examine the build transcript to see what was built. You should see the framework being built first, then your app. Everything in the transcript should make sense (be what you expect). If not, e.g. if it's building old source files, you can start working backwards to see why.


>> sometimes asks if I want to use a different (no longer extant) property instead


If you go ahead and use the old property, does that source line compile without error? If yes, you can command-click on the property name to go to the definition, and that should give you some clue as to why it's available. If no, there's something wrong with your project indexing, I suppose.

Thank you for that, those steps have been very helpful.

Went through these steps to Clean Build Folder on each project separately and then the workspace, then rebuilding the app scheme in the workspace. Same errors but command-clicking showed that there was a namespace thing (I think it's a namespace thing anyway); I had an xcdatamodel in which I accidentally used the same Entity names as the classes that were showing errors. Since I don't actually care about CoreData yet (I did, but changed my mind), I deleted the model file and voilà, the errors disappeared.


However, I have noticed that there are still issues with the workspace picking up the changed API—but, at least now, it's only the API that I've changed in the last few minutes, not the earlier changes.


After I got the Core Data stuff removed, it was building fine. I realized that I needed to make a minor change to the API—needed to add a method to one of the classes in the Model—so I made the change, then built the Generic scheme for the Model project … and the V&C project doesn't see the new function.


I went back through the steps you listed—Clean Build Folder for each project by itself, then for the workspace—and then built the Scheme for the Model against Generic, and then tried to build the V&C project (for any scheme, doesn't matter). It doesn't see the new method.


Is it really necessary to delete and then re-add the Framework to the Embedded Binaries every time I make a change to the Framework? It seems to me, perhaps naïvely, that if the V&C (or any) Project has the Framework set in the Embedded Binaries, that it should use whatever one it finds there? Or, at the very least, if I Clean the V&C project it should be trying to grab the Framework, right?

No, it shouldn't be necessary to do anything extreme to keep it working. Don't overlook the possibility that this time it is just a housekeeping error, like forgetting the "public".


If not, the other thing you can try is deleting the ModuleCache subfolder of the DerivedData folder. I guess it's possible that there's a problem there if a same-named module gets created via two different projects.


Other than that, possibilities for ongoing weird behavior include:


— Build settings for include paths or framework paths having some value that Xcode chose to add, that's dragging in the wrong files.


— References to files that are not using the correct form. For example, your reference to the framework should probably be "relative to build products" rather than, say, absolute.


— Target membership checkboxes, in the File tab of the Utilities inspector. When you're still messing around with what files are in what project, it's easy to add a source file to the wrong target.


If you don't find anything obvious, then you should probably also submit a bug report. Even this is happening because of something you did wrong sometime, Xcode shouldn't be so inscrutable that you can't figure it out. Or there could just be a bug.

Thank you for your explanations. I will verify that I made the right access control decision (and actually typed it into the editor!), and then I'll delete the ModuleCache and see if that helps.


Incidentally, am I correct in assuming that "via two different projects" would not include having the Model project present in two different Workspaces—one for iOS, which I am working on now, and a second one for macOS which I will work on after—because it would be creating the same Framework, yes? It seems to me, again possibly naïvely, that because they are the same project they will create only the one instance of the Framework.

If it's an embedded framework, the framework that's copied into the app comes from the build directory of the framework target, so you don't have to worry about it appearing in a different project.


If it's a standalone framework, then it gets referenced directly, and you'd have to make sure you "install" it in different locations for different platforms, to avoid using the wrong version.


Note that if you're using the default build locations, then there's a different build folder for each workspace (and for each project opened separately from an explicit workspace). The build folder settings for a project are not used when the project is opened via a separate workspace, and everything gets properly separated.


If you've chosen to use non-standard build folder settings, then you might see a problem along the lines you described, which is a good reason not to do that.


Note also that the build settings are specified via Workspace Settings or Project Settings on the File menu (with defaults set up in Xcode preferences). These are always per workspace, in spite of what the File menu says — in the case where you open a project directly, there's still a hidden workspace inside the project.

I gotcha, thanks. I have not made any changes to the build locations, I am not familiar enough to go mucking around with that; I am not even sure I have any idea how to go about that right now. So in my case, each workspace should be getting its own copy of the Framework, no biggie.


Thank you again for your insights.