Xcode: Different targets have different rootViewController? - ios

I've got an app that's functional (in the app store). In the past, we only had one version of our app with one Target in Xcode. Our development cycle is getting a little more complex, so we want to have two Xcode targets: production and development. These two targets would have two different bundle identifiers so we can have the different versions running on the phone at the same time. This is a similar strategy to this: https://www.raywenderlich.com/68613/create-paid-lite-version-iphone-app
I've basically followed the raywenderlich instructions to duplicate my target and set a preprocessor macro. The only change so far is using a different icon.
The "Original" version of the app is the "production" version. The newly duplicated target is the "development" version.
I'm using a storyboard where the LaunchViewController is set as the Is Initial View Controller option.
In the AppDelegate, I have code that gets the root viewcontroller via window?.visibleViewController and sets some information on it:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {
// ...
guard let launchVC = window?.visibleViewController as? LaunchViewController else {
NSLog("visibleViewController is nil or not LaunchViewController")
return
}
NSLog("calling startUserManagerAndLogin - launch")
launchVC.startUserManagerAndLogin()
// ...
return true
}
In the original (production) version of the app, everything continues to work fine. I see the following line in the console, and the app launches correctly:
... Visible View Controller: Optional(<MyApp.LaunchViewController: 0x7f84dea02a00>)
However in the development version of the app. I'm seeing the guard case fail. Here's what I see in the console:
... Visible View Controller: Optional(<UIViewController: 0x7fbd1e509570>)
... visibleViewController is nil or not LaunchViewController
The root view controller is different between the production and development targets. I don't see how the root view controller can be different between two targets unless I explicitly set that (which I didn't).
I checked the project files and the "General -> Deployment Info" is the same between the two targets. I also checked the storyboard, and there's nothing there that specifies different view controllers.
Any ideas what's going on or how I can fix it?
Thanks!

Gah! FFS I figured it out. Turns out there was another log line that I missed that said:
... Unknown class _TtC8MyApp20LaunchViewController in Interface Builder file.
I found this out because I tried instantiating my LaunchViewController by hand (from the storyboard) and got this error as well. I figured out that the module was wrong.
I then found the SO question: XCODE 7.1 Swift 2 Unknown class in Interface Builder file which helped me find that there were some old storyboard elements that didn't have Inherit Module From Target selected. I toggled the checkbox to on, and now it's working. Phew.

Related

Disable RealityKit/ARKit when building in xcode Simulator

Is it possible to disable RealityKit/ARKit/AR when building for xcode Simulator? So that I can style/change non-ar related pages.
I want to change my home page, adding different sections and styling. The home page has nothing to do with ARKit/Reality Kit, but I don't have the physical device with me.
The errors say that various RealityKit/ARKit functions are undefined or don't exist. Like ARView has no member .occlusion.
The home page has no need for AR at all, is it possible to build and run the simulator, or even preview without a physical (AR Enabled) device?
You can use a Conditional Compilation Block, as explained in the Swift Programming Manual:
class SubclassedARView : ARView {
var configuration: ARWorldTrackingConfiguration()
var runOptions: ARSession.RunOptions()
init() {
#if !targetEnvironment(simulator)
// Code here is only compiled when building to a real or generic device.
// This is the place where you should add your RealityKit specific
// code, or at least the code that gives build-time errors in Xcode.
// An example of a problematic method:
session.run(configuration, options: runOptions)
#endif
}
}

How can I set flags that my app will see when it's running under XCTest?

KIF works like magic, something puzzled me a lot recently. That is how exactly KIF and XCTest works.
It is said in WWDC 2014 & 2013: Test code is injected into the host application as kind of a plugin, so what information can be eavesdrop from main app as a plugin? What is the relationship between Host Application & Plugin??
Using KIF, we can sense the Notifications & URL request, but how that works? My first thought is all context in host application is shared with plugin But why in test, we cannot modify variables in the main app?
For example:
we have two targets:
Magic Project
-- MagicApp
-- MagicUITest <- KIFTest target
Suppose I have a file called MagicClass:
class MagicClass {
static var a = 1
}
Is that possible if I want to modify that variable in MagicUITest?
The problem I faced right now is how can I inject different UIViewController to RootViewController so that I can run KIF test from each individual ViewController and don't need bother going through the login process all the time .. my guess is something like:
in MagicApp:
class AppDelegate : .. , .. {
func application(application: UIApplication, willFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
if MagicClass.a == 1 {
window.rootViewController = AViewController()
} else {
window.rootViewController = BViewController()
}
}
}
in KIFTest's setUp() :
setUp() {
Magic.a = 2
}
But not work ..
One thing is Magic.a = 2 won't change the Magic.a in MagicApp, second is application(..,..,..) function will end before setUp() is called ..
Any idea ?
While you're correct that the exact code you've tried won't work, you'll be able to use a very similar approach.
This code, for example, is cribbed directly from the app I'm working on right now in a class called RootViewController that's (you guessed it) the app's root view controller:
public override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if NSProcessInfo.processInfo().environment["TESTING"] == nil {
loadChildren()
}
}
What it does is looks for an environment variable to decide if it should automatically continue with loading the app, and if it finds the environment variable it waits for the test stack to finish setting up and telling it what portion of the app to load next. (You could do this in your app delegate, too, if it's a really small app.)
You can set the environment variable by editing the scheme in Xcode:
All that said, though: take care when using this strategy. You want your tests to be testing features of your app as they exist in your app, and if showing different screens arbitrarily is a feature of your app, that's probably okay. But if you start writing code that makes your app behave differently when under test, you're not really testing your app anymore, are you?

dyld_fatal_error with Typhoon+Swift+iOS7.x+Plist-bootstrapping

I have very annoying problem with Typhoon Framework version 2.3.0 in Swift project.
I included Typhoon in Podfile as mentiond in tutorial, installed Pods, created bridging header and added #import <Typhoon/Typhoon.h> in this header.
Then I created assembly subclass called ApplicationAssebly :
import Foundation
public class ApplicationAssembly: TyphoonAssembly {
public dynamic func appDelegate() -> AnyObject {
return TyphoonDefinition.withClass(AppDelegate.self) {
(definition) in
definition.injectProperty("myAssembly", with: self)
}
}
}
As you see I want to inject that assembly into AppDelegate.
I have also added TyphoonInitialAssemblies entry in Info.plist file. And in this moment my problems has started. I have tested few combinations resulting in NSException :
Can't resolve assembly for name xxx
This combinations are (typhtest is project/bundle name):
ClassName in Info.plist: ApplicationAssembly, Defines Module property in Build Settings : No
ClassName in Info.plist: ApplicationAssembly, Defines Module property in Build Settings : Yes
ClassName in Info.plist: typhtest.ApplicationAssembly, Defines Module property in Build Settings : No
ClassName in Info.plist: typhtest.ApplicationAssembly, Defines Module property in Build Settings : Yes
I have found this answer on StackOverflow so I've tried the last combination :
ClassName in Info.plist: _TtC8typhtest19ApplicationAssembly, Defines Module property in Build Settings : Yes
This combination doesn't throw NSException but I have dyld_fatal_error, stack trace from iPhone 5s (iOS 7.1) below :
I get slightly different stack trace from iPhone simulator (iOS 7.1) :
What is strange that it works on iOS 8.1 simulator ! Also Typhoon Sample Application for Swift works well on my device.
I also tried to clean any Xcode and project caches and DerivedData directories, I've cleaned project and build folder and rebuilded the project, but it's not working. My Xcode version is 6.1 (6A1052d) and I'm using OSX Yosemite 10.10.1 .
GitHub repository with my code : https://github.com/papcio28/Typhoon-Dyld-Error
Edited 21.11.2014
What is also strange is that if I create the factory manually and inject something also manually, Typhoon works. Steps that I've made are :
Removed TyphoonInitialAssemblies item from Info.plist
Changes AppDelegate.application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool to
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let factory = TyphoonBlockComponentFactory(assemblies: [AppAssembly()])
factory.inject(self)
return true
}
But it doesn't change a fact that I want to use Typhoon without defining factory manually, so the question is still actual.
This issue has been reproduced as a bug and will be resolved ASAP. It was also reproduced in the Typhoon sample app, after pod update, meanwhile a clean checkout works fine. This would suggest that a regression bug has crept in somewhere between 2.2.1 and 2.3.0, however checking this yielded some strange results, so it might not actually be the case. We'll post updates/discoveries to the issue log.
Workaround:
In the meantime, please bootstrap Typhoon by overriding the following method in your AppDelegate:
dynamic func initialFactory() -> TyphoonComponentFactory {
return TyphoonBlockComponentFactory(assemblies:[
ApplicationAssembly(),
AnotherAssemblyIfRequired()])
}
This approach bootstraps Typhoon just like plist-integration, and so provides UIStoryboard integration, UIStateRestoration and so forth. . it was not documented until now, as we thought thought the plist style of staring Typhoon was sufficient and it would be simply confusing to provide too many options. However in this case it works for iOS7.1+Swift+Storyboards while plist does not.
Namespacing:
As for the namespace issue, it should not be necessary to mangle the name in the plist file as you did - Typhoon will detect if implicit namespaces are available and handle this transparently. But, if this is not working currently in iOS7.x, you can add a directive to your assembly as follows:
#objc(ApplicationAssembly)
public class ApplicationAssembly : TyphoonAssembly {
//etc
}
Edit: Fixed in Typhoon 2.3.1:
As of Typhoon 2.3.1, plist bootstrapping can now be used with Swift+iOS7.x

ERROR : perhaps the designated entry point is not set?

Hello EveryOne I am following THIS awesome tutorial but I didn't download stater project because I want to create a different app I have done everything where I want to pop up only CenterViewController with Left side ViewController Both are in ContainerViewController But I got This in my Console:
2014-11-19 14:04:46.838 SlideTable[3612:87749] Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set?
I also tried THIS answer but got same result.
What this error means I have done all the required things as the auther provided at start up project but I didnt found any solution for this.
This is the code for may project.
AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let containerViewController = ContainerViewController()
window!.rootViewController = containerViewController
window!.makeKeyAndVisible()
return true
}
Am I missing something?
I will provide further information if needed.
I have met the same issue and I found the solution:
Select the Main.storyboard;
Open Attributes inspector and click Is Initial View Controller in the View Controller section.
This operation works well for me according to the same error message.
The main controller of you app (the entry point), does it have the the "Is Initial View Controller" checked on the right bar? It will show an arrow next to it.
Update for Xcode 11, and iOS 13.
In addition to elia's answer, you have to change one more attribute in Info.plist file.
In Info.plist file it is needed to change String value for Storyboard Name to the name of your initial file that you want to first appear during launching of the application.
By default value for Storyboard Name is set to "Main", and you need to change it.
You can find that attribute in:
Info.plist -> Application Scene Manifest -> Scene Configuration -> Application Session Role -> Item 0 -> Storyboard Name
I solved this problem by clicking on
Product -> Clean Build Folder
When you use more than one UIStoryboard and want to init your UIViewController except the Main.storyboard for example Intro.storyboard, then you would probably get this error. You must select
YourProject -> TARGETS -> Deployment Info -> Main Interface
In Main Interface, there are several UIStoryboard that you created for your own project. Choose the right one which contains your UIViewController.
I mean
YourProject -> TARGETS -> General -> Deployment Info -> Main Interface.
Not YourProject -> TARGETS -> Deployment Info -> Main Interface.
There exists a compatibility issue between IOS 12 and IOS 13.
So you have to remove the Application Scene Manifest from the info.plist in order for it to function correctly. Also, you have to remove everything related to scenes from the App Delegate.

Xcode 6.0.1 Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1

I am getting this error on archive:
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1
How to solve it?
Please see the screenshot.
This problem occurs when the Swift optimization level is not set to None for Release. Set the value to None and the issue goes away.
Open up your project and click on the projects root directory.
Click the build settings tab.
Search for Swift Compiler - Code Generation and under Optimization Level make sure Release is set to None.
EDIT
After upgrading to Xcode 6.1 these instructions caused other issues when archiving (building for debug/device worked fine). Setting the optimization to Fastest allowed me to archive again. There are apparent issues with Swift compiling still (archiving specifically).
Can't archive working 6.0.1 Swift project in Xcode 6.1 / Segmentation fault: 11
EDIT
I was not able to fund the Build Settings tab, until I read this answer.
how to find the build settings tab
This occurred for me when I had two of the exact same files, and also when I was missing I file I didn't know I had deleted. I clicked on the error message, and just above the error, it shows you what file you have more than 1 of or are missing.
You can click the Product in the navigation and choose the "Clean" button; it will clean all compile error in your project. Then, you can debug for the latest error.
Deleted files reference keep in Build Phase and that's why it gives this error. Remove reference from there as well.
Project> Target > Build Phase
Under this section you will find your deleted files in red colour. Remove these files error will resolve.
I am not sure if it has one solution.
I recommend you to check the differences between your last git commit, and comment on/off the changes.
In my case, my code was
let anArray = ResultDict["ResultSet"] as [[NSDictionary : AnyObject]]
for aDict : NSDictionary in anArray {
let anObject = ObjectType(ObjectDict: aDict)
objectList.addObject(aDict)
}
no warning on the line, i got the same exit 1 compile error
then i changed it to the below it has compiled.
let anArray = ResultDict["ResultSet"] as [[NSDictionary : AnyObject]]
for aDict in anArray {
let anObject = ObjectType(ObjectDict: aDict)
objectList.addObject(aDict)
}
I don't know if this is really an answer, but...
I had the same issue. App worked when building/running, but archiving failed with "...swiftc failed with exit code 1", with no other helpful message at all. Luckily, when I tried to build my app with Nomad's ipa build, I got:
The following build commands failed:
CompileSwift normal arm64 /path/to/erroneous/TableViewController.swift
So I started commenting out sections of that file and tracked the problem down to a tuple assignment.
// MARK: - Table Data
private var tableData: [(sectionName: String, item:ListItem)] = []
private func refreshTableData() {
// let labor = ("Labor", laborListItem) // DOESN'T ARCHIVE
let labor = (sectionName: "Labor", item: laborListItem) // ARCHIVES
tableData = [labor]
tableView.reloadData()
}
So apparently the compiler wanted the elements in thast tuple named (as defined by the type of tableData).. but only for archiving? The Dumb thing is, I use this same pattern in other view controllers, and the compiler seems to be fine with those.
For the record my Code Generation -> Optimization Level was set to None for debug and release.
Hope this helps someone! It took hours to figure this out.
It happened to me when I didn't put the parenthesis at the end of a call of a function:
let var = self.getNextPrimeNumber
solved it by:
let var = self.getNextPrimeNumber()
In my case, it was caused by duplicate files, using the same name, in my project directory. As soon as I removed them, the error was gone.
This happened to me when I used static inline function from swift file
The function looks like this
static inline void openURLInSafari(NSString * _Nonnull urlString) {
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:urlString]];}
I just had the same thing occur. I hunted down the cause to one file that caused the error even when empty. Examining the file, I discovered it had the wrong character set. When I set it to UTF-8, the error vanished. I think that it was decoding it with the wrong character set.
From this I surmise that the error simply indicates that something has happened that the compiler was unprepared for. Sorry that isn't very helpful to most people, but it may help to check your characters sets.
one more case that can lead to this error which just took me hours to track down: a failable initializer that always returns nil.
i had an initializer that looked like this:
init?(object: MyObject) {
if object.importantProperty {
// initialize
}
return nil
}
when what i meant was:
init?(object: MyObject) {
if object.importantProperty {
// initialize
}
else {
return nil
}
}
fixing the initializer made the error go away.
If using Core Data:
I had a Core Data entity for which I created the NSManagedObject subclasses (with Xcode's help). In addition, the entity was configured to generate code automatically (see screenshot), so basically 2 classes existed during runtime. Just switch the option to Manual/None and it won't generate it.
This error occurred for me after I noticed that a few of my .swift files were inexplicably in the wrong directory -- one level above my Xcode project directory. When I noticed this, I moved them into the main project directory and cleaned the project, thinking everything would be fine. However, upon building the project I got the above-mentioned "failed with exit code 1" error. Just above the error message it listed the files I had just moved, indicating that it couldn't find them in the directory where they used to be. In addition to the error message, the files I moved were now showing up as red in the file navigation pane.
For each of the files in question what I did to resolve this was:
- Select the file from the list of files in the Xcode file navigation pane,
- Click on the little page icon in the rightmost pane of Xcode, which opens a file attributes pane,
- Click on the little folder icon underneath where it says "Location" in the file attributes pane,
- Choose the new location for the file,
- RESTART Xcode for the above changes to really do anything.
this error comes from missing files so the compiler couldn't find the files and keep alerting.
Follow these steps to rebuild your app:
Look up for the red and invisible files within workspace
Remove their reference
Re-add files
Re-compile
I experienced this error after performing a git merge. I solved new Xcode warnings and the project can be compiled.
Xcode 7.2.1 is used in my case.
In my way the error was due to UIDevice.currentDevice() in ((UIDevice.currentDevice().systemVersion as NSString).floatValue >= 8.0)
After commenting this all starts work fine.
XCode 7.2
in my case , at your project target Build Setttings, in Other Swift Flags,jsut delete the String "-serialize-debuggin-options"
enter image description here
I had a resolution very similar to RyanM, where with an excess of hubris I tried to assign a variable to the default value of an inner function:
Fails to compile (though does not crash SourceKit):
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
func itemCell(_ indexPath: IndexPath = indexPath) -> UITableViewCell {//...}
Succeeds:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
func itemCell(_ indexPath: IndexPath) -> UITableViewCell {//...}
One possible reason that this can happen is perhaps because you have deleted a file but not removed references to it. This will mess up the pbxproj file. I would check to see if that is the case.
check "Development Pods" Folder all listed Frameworks path.
In my case swift development snapshot was selected instead of xcode 9.2. here are the steps and image.
keep xcode on screen and click on xcode top menu bar.
Than go to toolchains option and check on xcode 9.2. thats it.
Happy Coding!!!
So, I had the above and narrowed it down to a TFS issue with locking the file but only when I pasted or did any other edits besides small copies or manual typing. I noticed the original file would compile, but my edits wouldn't, even though they were syntactic OK. Also related is unable to save document: xcode The document "..." could not be saved
The fix for both was:
Duplicate working version.
Paste fully-merged new code into duplicate.
Copy and paste old file over new one. (I personally just renamed the old one to something else, then pasted duplicate and renamed it, too. Guessing both work since I pasted directly earlier for reverts during tests to see).
Voila. Lazy way to bypass merge-locking issue. Apparently full file-pastes are just fine, while edits aren't. Shared since the other answers don't seem to be as lazy as this. ;)
Note: I am suspecting a non-UTF-8 character made its way somewhere, but pastes worked in older versions so I don't know where, or if relevant.
In my case, the error was the result of missing files that were generated by Xcode. I tried the regular clean Opt+Shift+K and it didn't clean up all the errors. I found a post on the Apple Developer site that recomended going to the Product Menu in Xcode, holding down the opt key, and selecting Clean Build Folder. This appears to be a more comprehensive build as it pops up a modal dialog for you to confirm.
Just go to the "project setting" and click on the "build phaces" after that you will find targets in that u have to delete the test file like my project name "WER" so its showing like this WER&TEST so just delete that and clean ur project and run .........

Resources