Swift pushViewController Works on iPad but not iPhone - ios

I have no idea what is happening but my code stopped working on iPhone but works fine on iPad. (Using Xcode 10 and Swift 4)
I first check for the data and if not set it transfers to the ConfigVC.
Nothing happens on the simulator for any phone settings. I went so far as to reinstall my system software and Xcode.
I use this same approach on other apps and it is fine. For some strange reason it just stopped working on this app.
func dataCheck(){
// make sure the required data is set
if User.getInfo() == nil || Index.getAll() == nil {
let vc = UIStoryboard.init(name: "Config", bundle: Bundle.main).instantiateViewController(withIdentifier: "ConfigVC") as? ConfigVC
self.navigationController?.pushViewController(vc!, animated: true)
}
}
The code shows it just ending.

You're trying to push/present a vc while the current isn't yet loaded inside viewDidLoad so move the call to dataCheck inside viewWillAppear/viewDidAppear

Related

UITabBarController opens and turns into black Screen in iOS13

I have a application flow
first presentviewController -> pushViewController -> PushViewController -> click button action Showing TabBarContorller which in .present(manner)
DispatchQueue.main.async {
let tabBarController = TabBarController.instantiate()
tabBarController.modalPresentationStyle = .overFullScreen
self.present(tabBarController, animated: true)
}
Application works fine in iOS 11. When running on iOS 13 its show black Screen
Well I guess if you present of push and then present I guess this make no difference with the application.
Your Inputs are highlight appreciated
Thanks in advance.

How to debug inconsistent crash to SIGABRT and NSLayoutConstraint constant is not finite! That's illegal. constant:nan

I have looked through all the SO answers and everything seems to point to a divide by zero issue, however, I am not dividing by zero anywhere (at least that I can tell).
Total error I get:
2017-08-17 10:08:49.760586-0500 APP[90643:6605106] * Assertion failure in -[NSLayoutConstraint _setSymbolicConstant:constant:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/Foundation/Foundation-1350/Layout.subproj/NSLayoutConstraint.m:711
2017-08-17 10:08:49.761100-0500 APP[90643:6605106] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSLayoutConstraint constant is not finite! That's illegal. constant:nan firstAnchor: secondAnchor:(null)'
*** First throw call stack:
(0x18ccaafe0 0x18b70c538 0x18ccaaeb4 0x18d743760 0x18d6e4b40 0x18d6e4a04 0x102ac2b7c 0x102ac28c4 0x102abddf4 0x102abe038 0x192df4838 0x192e8f9a4 0x18cba06c0 0x18cb976fc 0x192df4ac0 0x192df45a8 0x19312d080 0x193069594 0x19305b630 0x192dcf28c 0x18cc589a8 0x18cc56630 0x18cc56a7c 0x18cb86da4 0x18e5f1074 0x192e41c9c 0x100038ec8 0x18bb9559c)
libc++abi.dylib: terminating with uncaught exception of type NSException
As it does talk about .width, it seems that a divide by zero might be the issue, though I have triple checked my code and only have one division anywhere in the code:
self.startButton.frame = CGRect(x:self.view.frame.midX - (self.view.frame.midX / 2),y:self.view.frame.midY - 20,width:self.view.frame.midX,height:40)
Which is only there to center the button.
The crash is INCONSISTENT (which is always frustrating!), meaning that I can often repeat the same action and it works fine before a crash (sometimes after 2-3 times, other times, it happens right away...)
Here's the scenario and code around the issue:
I'm in a tabBarController (which has several tabs with all functions working fine) and receive a push notification (various push notifications work fine for setting all actions and pages using this same code).
let vc = currentViewController.storyboard?.instantiateViewController(withIdentifier: "\(rcView)")
if vc != nil {
currentViewController.present(vc!, animated: true, completion: nil)
}
This takes me to a UIViewController that includes a map, directions, various buttons, etc. (again, working great ).
Here is where we see the crash SOMETIMES....
When we click the 'Cancel' button on the controller
let cancelButton = UIButton(type: .system)
cancelButton.addTarget(self, action: #selector(self.cancelIt), for: .touchUpInside)
which goes to the cancelIt function
self.navigationController?.popViewController(animated: true)
self.dismiss(animated: true, completion: nil)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "Home") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = viewController
viewController.selectedIndex = 0
After this cancel, I can send another push notification and SOMETIMES it works, while other times, it crashes.
When it crashes, I get the error listed above and in AppDelegate.swift, a red line highlighting
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
with a "Thread 1: signal SIGABRT" (which I have seen before and usually means a duplicate name on the main storyboard)
I'm pretty sure this is all related to the less-than-elegant (IMHO) way of moving from the tabBarController to the UIViewController, though why is it so inconsistent?
Other ways of doing this switchover are welcome - I did a lot of research on how others do it and this seems to be the most clean, but working 'sometimes' isn't going to make the client happy!
self.dismiss(animated: true) { [weak self] in
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "Home") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = viewController
viewController.selectedIndex = 0
}
Try calling the dismiss with a completion handler. Oh, and why do you pop first and then dismiss? Is your map controller presented or pushed? Maybe you don't need both.
After a bit more searching (and thanks to a tip I saw in a comment of another SO question - sorry, I lost the link...) on how to better read xcode crashes (https://www.raywenderlich.com/10209/my-app-crashed-now-what-part-1), I found the issue to be in the Mapbox software I was using (https://github.com/mapbox/mapbox-navigation-ios) and not in my code at all.....
The issue of inconsistency boiled down to the location changing from the Simulate Location and the push notification coming in as/at the 'destination' point (when the 'current location' and 'destination location' were the same, MapBox software was coming up with a nan).
I fixed that by doing a check for nan (.isNaN) though got another crash a bit later.....
Now, I've updated the SDK and am fighting other issues (one being that we no longer get the voice - another that the Simulate Location seems to not be working..... AARRGGHH!) but at least the particular issue in the question is answered - it was in the library!

UINAvigationController -> setViewControllers causes a crash

I've a very strange situation here - call of the method UINAvigationController -> setViewControllers:animated: causes a crash of the app. It's happining only on iOS 10.3.2 and when I'm building the app in release mode.
I've collected more details. Hope they can help to understand what happens.
The issue appears on iOS 10.3.2 and in release mode only. I’ve checked this on iPhone with 10.3.2 and release build fails but debug works OK. Additionally, I’ve checked previous version of the app from AppStore on iOS 10.3.2 and it’s OK too. Debug and release builds work fine on all of the previous versions of iOS.
The previous version in AppStore was built with older version of Xcode, and now I'm using latest Xcode 8.3.2. I suppose it's system issue, which is related to iOS and Xcode versions.
Regarding sources, it looks like:
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
...
window = UIWindow(frame: UIScreen.main.bounds)
....
let navigationController = UINavigationController(rootViewController: viewController)
window.rootViewController = navigationController
window.makeKeyAndVisible()
}
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
...
continueButton.addTarget(self, action: #selector(navigateForward), for: .touchUpInside)
...
}
func navigateForward(sender: UIButton!) {
let nextController = FinalBuilder.viewController()
navigationController?.setViewControllers([nextController], animated: true)
}
I said before, it works fine in all cases except one :). UINAvigationController -> setViewControllers:animated: is standard iOS method, available from iOS 3.0+ and not deprecated now. There are no hacks or something else what can corrupt the program flow. And it’s usual way to use it.
P.S. There is no debug log or any other message which I can provide you because the app just disappears from the screen with no notification at all.
if its not work , so you can try easy way like
simple creat view controller object and pass in navigation
let nextVC = storyboard?.instantiateViewController(withIdentifier:"ScrollViewController") as! ScrollViewController
self.navigationController?.pushViewController(nextVC, animated: true)
I've found that this behavior appeared after update of RxCocoa from 3.3.1 to 3.4.0. It happens because of the following change in DelegateProxyType.swift : extension ObservableType : func subscribeProxyDataSource:
return Disposables.create { [weak object] in
subscription.dispose()
- unregisterDelegate.dispose()
object?.layoutIfNeeded()
+ unregisterDelegate.dispose()
}
I've posted report to ReactiveX/RxSwift repository. You can check final state there, if you are interested.

MPMediaPickerController shows an empty screen on iOS10

I am trying to port my apps to iOS 10, including the visualization of a MPMediaPickerController by means of the following code:
#IBAction func handleBrowserTapped(_ sender: AnyObject){
let pickerController = MPMediaPickerController(mediaTypes: .music)
pickerController.prompt = NSLocalizedString("Add pieces to queue", comment:"");
pickerController.allowsPickingMultipleItems=true;
pickerController.delegate=MPMusicPlayerControllerSingleton.sharedController();
self.present(pickerController, animated:true, completion:{
MPMusicPlayerControllerSingleton.sharedController().storeQueue()
})
}
Yet all that appears on the screen is a full white screen with no back buttons or other, differently from the previous iOS versions. The block is called and so the picker's presentation seems to succeed. What could be the problem?
Add Key-value to Plist :
<key>NSAppleMusicUsageDescription</key>
<string>$(app Name) uses music</string>
The issue was fixed by the latest beta now asking for an authorisation to access the iTunes library.

iOS: how to delay the launch screen?

When launch an app, the LaunchScreen.xib is removed as soon as all the assets are initialized.
I want to make the launch screen stay for at least 1 sec.
Is there a way to achieve this?
Thank you!
You can create a view controller that uses the LaunchScreen storyboard, present it (not animated) on applicationDidFinishLaunching or applicationWillFinishLaunching, and dismiss it whenever you want.
Keep in mind this is discouraged by Apple because it gives the impression that your app takes a lot longer to launch, which is bad user experience and might cause some of your users to delete your app.
Swift 4 Update
Just write one line of code
Thread.sleep(forTimeInterval: 3.0)
in the method of didfinishLauching.... in appdelegate class.
Example
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Thread.sleep(forTimeInterval: 3.0)
// Override point for customization after application launch.
return true
}
Never sleep on the main thread. Doing this could actually cause iOS to kill your app for taking too long to start up
Thought I chip in my thoughts on this, I wanted to write in comments but it won't allow many lines. I believe many apps developer want to do this (delay the launch screen) is because they want to build a brand presence of the apps/games for their company.
Having said that, launch screen is NOT designed for that, as Rick Maddy explained in the comment section in one of the other answers. Launch screen's purpose is to make users feel the app is instantly running by showing the empty UI while the actual data is loading at the back (willAppear and so on).
So to achieve what many developers want, while being in-line with Apple's HIG, what you can do is:
Display UI template in the launchscreen as intended by Apple HIG.
Upon main screen load, load up another VC that shows "intro" of your brand. Make sure this runs only ONCE (a simple flag in
NSUserDefaults should do the trick).
Users should be allowed to skip this if it is a long "intro".
The same "intro" VC should be available to user by tapping on a "View Intro" button somewhere (maybe in about page).
If you want to go with simple, you can use NSThread:
[NSThread sleepForTimeInterval:(NSTimeInterval)];
You can put this code into the first line of applicationDidFinishLaunching method.
For example, display default.png for 1.0 seconds.
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
[NSThread sleepForTimeInterval:1.0];
}
It will stop splash screen for 1.0 seconds.
Alhamdulellah Solution is find
Only copy and paste this code in AppDelegate Class
Call this SplashScreenTiming() in didFinishLaunchingWithOptions()
private func SplashScreenTiming(){
let LunchScreenVC = UIStoryboard.init(name: "LaunchScreen", bundle: nil)
let rootVc = LunchScreenVC.instantiateViewController(withIdentifier: "splashController")
self.window?.rootViewController = rootVc
self.window?.makeKeyAndVisible()
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(DismissSpalshController), userInfo: nil, repeats: false)
}
#objc func DismissSpalshController(){
let mainVC = UIStoryboard.init(name: "Main", bundle: nil)
let rootvc = mainVC.instantiateViewController(withIdentifier: "SignInVC")
self.window?.rootViewController = rootvc
self.window?.makeKeyAndVisible()
}

Resources