Xcode sees only some of similar extensions of a nested class written in separate files - ios

I'm trying to keep my code as readable as it possible by keeping methods and files as short as I can and using nested classes for namespacing. It works fine except some really strange moment.
I have some class used for namespacing.
class Space { }
All classes used within that one are implemented in their own files as extensions.
extension Space {
class SomeClass {
// implementation
}
}
One of those SomeClasses have a number of quite sophisticated initialisers, so I have split them up to their own files as well and implemented it as follows:
extension Space.SomeClass {
convenience init(fromSomeSource source: SourceClass) {
self.init()
// other implementation
}
}
The problem is that some of those files works just fine, but some of them throwing 'SomeClass' is not a member type of 'Space' and I don't know why.
All of them are pretty similar. The only difference is implementation of an initialiser itself. All files are held in the same place and I have no idea why some of them works fine and some not.
I tried to move code from not working files into files that works fine and that works – Xcode agrees to see the code and said nothing against it. But when the very same code lies in its own file – Xcode or compiler doesn't want to understand that SomeClass is really a member of Space.
I tried to clean the build, including manual dumping of ~/Library/Developer/Xcode/DerivedData folder. Nothing helps.
Surely I can put it all in a single file and it will work fine, but what the reason why it so picky in my case?
I've tried to create a new file and move there all contents from one of the bad ones. It works, but only with certain file names. Some names gives the same error again, but it seems that if name is totally new and not similar to any of the existing ones - it works. Magic?

I've encountered similar issue, it seems like the complier is trying to process the file where you extend the nested class before the one where it's defined. Therefore you have this error saying that that Space has no member SomeClass.
The solution I've found is to go to your target settings, open Build Phases.
There, in Compile Sources section you should put the file where you define the nested class above files where you extend it.
This solution seems to even play well with your observation that when you recreate the file it sometimes compiles, because when you recreate the file its position in Compile Sources changes.

Related

Issue with createM3FromEclipseFile

I'm using a simple method that reads a location and does some stuff;
public void readMyFile(loc file) {
M3 model = createM3FromEclipseFile(file);
println(model);
// do some stuff;
}
The method fails to read a specific location file;
|plugin://rascal_eclipse/src/org/rascalmpl/eclipse/library/lang/java/jdt/m3/Core.rsc|(1019,261,<33,0>,<38,77>): IO("Could not find|project://hsqldb/doc/verbatim/src/org/hsqldb/server/WebServer.java|")
However, this file is present on my disk. All other locations from the hsqldb project or other projects I've used it with, work without any issue. Only this specific file throws an exception.
I can also use createM3FromEclipseProject to read all files in a project. This works without any issues for the hsqldb project. However, in my workflow I prefer to read an individual file via createM3FromEclipseFile.
Is there a difference between createM3FromEclipseFile and createM3FromEclipseProject concerning the info it reads of an individual file?
I can confirm the behavior of createM3FromEclipseFile of the original question; however createM3FromFile works as expected.

iOS - 'MyProject-Swift.h' file not found when running Unit Tests for Swift

I am trying to setup Unit Testing for my project.
It is an existing Objective-C app, that I have recently added one Swift class to. I have setup the 'MyProject-Swift.h' and Swift Bridging files (both 'MyProject' and 'MyProjectTest') and I am able to build and run the app just fine using both Objective-C and Swift code.
However, now I want to run some Unit Tests on the new Swift class.
I setup my test file and it looks like the following:
MySwiftClassTests.swift:
import UIKit
import XCTest
import MyProject
class MySwiftClassTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
XCTAssert(true, "Pass")
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock() {
// Put the code you want to measure the time of here.
}
}
}
I get this error when running the app as Test:
'MyProject-Swift.h' file not found
I am not sure why this happens only when trying to run the Tests.
Any suggestions?
"MyProject-Swift.h" file is generated at following path:
"$(TARGET_TEMP_DIR)/../$(PROJECT_NAME).build/DerivedSources"
I end up adding this to Header Search Paths for my Unit Test target.
Also as #hyouuu pointed out about being the known issue, hopefully Apple will provide some good solution at their end. Until I believe we need to use this above solution.
https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html
Thanks to #gagarwal for figuring this out. In our case the product name has a space, which is collapsed in $PROJECT_NAME, so I had to hard code it. Additionally, by using $CONFIGURATION_TEMP_DIR instead of $TARGET_TEMP_DIR, you can remove the parent directory (../) from the path. So the solution is to add the following to the Header Search Paths in your test target:
"$(CONFIGURATION_TEMP_DIR)/Product Name With Spaces.build/DerivedSources"
Or, if your product does not contain spaces:
"$(CONFIGURATION_TEMP_DIR)/$(PROJECT_NAME).build/DerivedSources"
Saw in the Xcode 6.1 release note, that this is a known issue... sign...
Search for "-swift.h" in the release note https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc6_release_notes.html
Tests written in Objective-C cannot import the Swift generated interfaces header ($(PRODUCT_MODULE_NAME)-Swift.h) for application targets, and therefore cannot be used to test code that requires this header.
Tests for Swift code should be written in Swift. Tests written in Objective-C for framework targets can access the Swift generated interfaces by importing the framework module using #import FrameworkName;. (16931027)
Please see #gagarwal's workaround below which WORKS!
I had a similar issue to yours, I think; here was my setup.
I had an object defined in Swift:
// file Foo.swift
#objc public class Foo {
// ...
}
This class was then used in the initializer of an Objective-C object:
// file Bar.h
#import "MyProject-Swift.h"
#interface Bar: NSObject
- (instancetype)initWithFoo:(Foo *)foo;
#end
This made my unit tests for Bar not compile, since the MyProject-Swift.h header isn't real and the unit test target can't see it. The release note shared by #hyouuu is on point - but I'm not testing a Swift class, I'm testing an Objective-C class!
I was able to fix this by changing the header file for Bar to use a forward class reference instead:
// file Bar.h
#class Foo;
#interface Bar: NSObject
- (instancetype)initWithFoo:(Foo *)foo;
#end
I then included MyProject-Swift.h in Bar.m, and everything worked - my tests of Objective-C objects written in Objective-C compiled properly and continued running, and I could write new tests for Swift objects in Swift.
Hope this helps!
After I tried out everything I could find on the topic, the thing that worked for me was actually running the app although it was still showing the 'ModuleName-Swift.h file not found' error.
It went away and my app works perfectly fine. I guess I should have considered that earlier... The error keeps coming back, but after running the app it always just goes away again. So the issue is not really solved for me, but I can continue working on other topics for now...
A simple
#testable import MyProject
has done the job for me.
Strangely, I was seeing this same error, but only when targeting a device (not the simulator). Before running the test I would see the red exclamation point next to the import statement for "MyProjectNameTests-Swift.h".
However, funny thing is, if I just go ahead and run the test anyway (despite this apparent build error), then during the build phase that happens thereafter, XCode actually does generate the "MyProjectNameTests-Swift.h" file, and the test runs just fine!
So, at least in my case, there was no need for the other solutions here, evidently, although I believe they do work also.
I should also note that I deleted my DerivedData directory prior to this, so maybe that is a step also worth trying.
On one of my clients project they added frameworks directly in the project. I solved the errors like this;
Command 1
option command J
now type the framework name (that gives the error) in the filter
select the framework
option command 1
in Target Membership select your *UITests target
mySwiftClassTests (and any other swift classes you want to use in objective-c) needs to be marked #objc:
#objc class MySwiftClassTests: XCTestCase
I couldn't get it to work by adding that filepath mentioned by other answers, but I realized the file where it was complaining wasn't even being tested. I just had to remove it from the test target using the Right Utilities Side Bar.
Adding a .swift file to that target fixes issue on it.

Expected identifier for every occurance of "(Class)class" in LARSAdController

I'm currently trying to add LARSAdController to my iOS project with no success.
As soon as i import the files via #import "LARSAdController.h" in my AppDelegate.h the build process fails and on every occurance of (Class)class in LARSAdController.h i get the cryptic error "Expected identifier". BTW I'm using cocoapods.
Example:
- (void)registerAdClass:(Class)class;
which seems fine to me...
If i create a blank project and import the files they compile, so the problem must be in some relation to my code. Anyone got an idea what may cause this?
Thanks for any help in advance!
class is a reserved word in C++, so I would imagine that some of your project uses Objective-C++.
To solve this, use #import LARSAdController.h in Objective-C implementation files only, and remove its use from header files. You can use #class to forward-declare any occurrences of whatever classes are defined in LARSAdController.h in header files (this is best-practise anyway).
If you need to use LARSAdController from an Objective-C++ class then this is more complicated and you will need to use an Objective-C proxy object or modify their header files (which isn't ideal).

Xcode 5 weird errors

Something strange is going on with my Xcode 5. All of a sudden I'm getting Undeclared Identifier errors for all the values in my Constants.h file, which is imported in my Prefix.pch file.
Two things are weird here:
This hasn't happened before.
When I do build and run, the build succeeds and the app runs with no problems.
I tried restarting Xcode and the simulator, and even restarting the whole machine. No luck.
What's going on? How can I get rid of these false errors?
EDIT following rmaddy's request. The error is Use of undeclared identifier kOffsetFromTop (for example, there are other similar errors with different constants.)
I don't really want to post my entire constants file, but the constant in question is defined like this:
static int const kOffsetFromTop = 20;
When this happens I normally do the following
Comment out the import from the .pch
Clean all ⌘⌥⇧K
Delete derived data
Build
Then uncomment the import from the .pch and build again. I'm not sure which step is actually sorting the issue but this normally gets me going again.
Multiple points here :
You have a warning, not an error. A warning is just that, it warns you but does not prevent the code to compile. That is just to warning you that something is odd or unexpected, or to tell you that what you wrote may not be actually what you were intended, because the compiler finds it odd or not standard.
You didn't have the warning before probably because it wasn't activated by default in previous versions of Xcode. The latest version of Xcode5 activates more warnings (which is a good thing, as it warns you about more things that could go wrong in your code and encourage you to fix them), hence this new one you have but didn't have before.
As I understand what you describe, tour usage of a constant is incorrect (and that's probably why Xcode emits a warning).
The correct way to declare a constant that you want to be accessible from multiple files is to:
Declare it (define its existence and type) in a header (or in your pch) like this: extern <type> const <name>;
And define it (give it a value) only in one implementation file (like your main.m, your AppDelegate.m, some Constants.m file, whatever) like this: <type> const <name> = <value>
Some details and reminders about constants declaration (also valid in standard C)
You use static <type> const <name> = <value>; in an implementation file only, when the constant is local to the file and does not need to be used by other files. In that case, you declare it typically in the .m file in which you will use it, and other files won't have access to it (which is quite what the static keyword means, actually (making the constant attached/local to the file).
In that matter, you should never declare a constant that way in a header file (and especially not in your .pch file), because header (and pre-compiled header) files will be included multiple times. If you do that, this would declare as many independent constants as the number of implementation files you include your headers into (this has evil side effects especially for pointers/objects, for exemple declaring an NSString* const that way -- for, say, using it as a notification name of error domain -- will create multiple string constants, with the same value but different addresses, which will probably not behave like you will expect)
When you need to declare a constant that you need to use / be accessible from multiple implementation files, so declaring this constant in a header file so that it is known to all implementation fiels that includes this header, you need to only declare it in the header, and not making it static (at this would run against the purpose of having the same constant for all files instead of multiple independent instances of the constant) but instead indicate extern to let the compiler know that its definition (value) is set elsewhere. Hence the solution given above.

Rails 3.2 + CoffeeScript + Namespacing + Separate Files = Confusion

I have one companion script file for a Rails model, that uses code I've broken down into a hierarchy of over a dozen classes, for things like jQuery/Bootstrap UI code, factoring out similarities between different types of dialog, and so on. Let's say I'm working with articles.js.coffee as the "main page script" here.
I can define Coffeescript classes, namespace them as something like window.ourproject.OurUIDialog, and save them in separate, per-class source files such as app/assets/javascripts/OurUIDialog.js.coffee. Restart the Rails server, and that class can be subclassed, e.g., window.ourproject.PostInfoDialog extends window.ourproject.OurUIDialog. As long as PostInfoDialog is in articles.js.coffee (where the instantiation of the PostInfoDialog is), all is well.
But, if I move the subclass (PostInfoDialog) out into a separate file, e.g., PostInfoDialog.js.coffee, then attempting to do anything at all with it within the main articles script produces
Uncaught TypeError: Cannot read property 'prototype' of undefined
Again:
This revolves around a Rails model's companion script file, here called articles.js.coffee;
window.ourproject.OurUIDialog gets picked up whether it's in its own file or in articles.js.coffee
window.ourproject.PostInfoDialog (which extends OurUIDialog) can only be used if it's not in a separate file, even though viewing the generated HTML shows PostInfoDialog being included with all the other script files.
I'm tearing my hair out trying to figure this out, and I didn't have much left to begin with. Any ideas?
Pretty sure that Trevor Burnham answered my question when he answered this one; I just didn't see it the first dozen times I searched. :-P
Thanks to both of you for reading this one, though. :-)

Resources