QR and Barcode scanner code doesn't work Xcode 5.1 - ios

I've done this tutorial http://rdcworld-iphone.blogspot.com.au/2013/03/how-to-use-barcode-scanner-br-and-qr-in.html
I'm using the iPhone simulator on IOS SDK 7.1, Xcode 5.1.1, Mac OSX 10.9.4 and objective c. What is supposed to happen when I run the program is as follows:
1) I click the scan button on the window which first appears
2) I get the option to select an image to scan in the iPhone photo album
3) I select an QR or Barcode
4) It scans the barcode
5) It determines the value and displays that on the screen along with a small version of the scanned image.
What actually happens is it gets up to step 4 fine and the method with scans the image runs to completion (startScanning). However instead of doing step 5 it shows a huge version of the barcode on the screen and the method which preforms step 5 is never called (didFinishPickingMediaWithInfo).
Contents of ViewController.h
//
// ViewController.h
// BarCodeScannerDemo
//
// Created by RDC on 3/11/13.
// Copyright (c) 2013 RDC World. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ZBarSDK.h"
#interface ViewController : UIViewController<ZBarReaderDelegate>
#property (weak, nonatomic) IBOutlet UIImageView *resultImageView;
#property (weak, nonatomic) IBOutlet UITextView *resultTextView;
- (IBAction)startScanning:(id)sender;
#end
Contents of ViewController.m
//
// ViewController.m
// BarCodeScannerDemo
//
// Created by RDC on 3/11/13.
// Copyright (c) 2013 RDC World. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize resultImageView;
#synthesize resultTextView;
#pragma mark - ViewController's LifeCycle methods
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"View did load");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
NSLog(#"Did receive memory warning");
}
#pragma mark - Button click method
- (IBAction)startScanning:(id)sender
{
NSLog(#"Scanning..");
resultTextView.text = #"Scanning..";
//Create a reader
ZBarReaderViewController *codeReader = [ZBarReaderViewController new];
//Setup a delegate to recieve the results
//The delegate implements the ZBarReaderDelegate protocol, which inherits from UIImagePickerControllerDelegate
codeReader.readerDelegate= self;
codeReader.supportedOrientationsMask = ZBarOrientationMaskAll;
ZBarImageScanner *scanner = codeReader.scanner;
[scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to: 0];
[self presentViewController:codeReader animated:YES completion:nil];
NSLog(#"End Start Scanning method");
}
#pragma mark - ZBar's Delegate method
//Called when a barcode is successsfully decoded
//reader is the reader controller instance that read the barcodes
- (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info
{
NSLog(#"Decode results...");
// get the decode results
id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
break;// just grab the first barcode
// showing the result on textview
resultTextView.text = symbol.data;
resultImageView.image = [info objectForKey: UIImagePickerControllerOriginalImage];
// dismiss the controller
[reader dismissViewControllerAnimated:YES completion:nil];
}
-(void) readerControllerDidFailToRead:(ZBarReaderController *)reader withRetry:(BOOL)retry
{
NSLog(#"readerControllerDidFailToRead");
//If retry parameter is NO controller must be dismissed.
if(retry==NO)
reader=nil;
}
#end
Contents of AppDelegate.h
//
// AppDelegate.h
// BarCodeScannerDemo
//
// Created by RDC on 3/11/13.
// Copyright (c) 2013 RDC World. All rights reserved.
//
#import <UIKit/UIKit.h>
#class ViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ViewController *viewController;
#end
Contents of AppDelegate.m
//
// AppDelegate.m
// BarcodeScannerDemo
//
// Created by Airefrig Australia on 18/07/2014.
// Copyright (c) 2014 RDCWorld. All rights reserved.
//
#import "AppDelegate.h"
#import "ViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#end
I have spent many hours trying to find a solution to this and I haven't found anything which has provided a solution. The only person I've seen to have a problem like mine is on the tutorial page comments section but they never got a reply.
Please help!
Edit:
The image that is displayed is rotated at 90 degrees. Also I am new to objective c so if you provide code please explain why the difference should make an effect. I want to improve my knowledge =)
Edit: Solution
Since I can't answer my own question less then 8 hours after asking, here is what I found:
Upon reading the ZBarSDK API reference about ZBarReaderViewController here: http://zbar.sourceforge.net/iphone/sdkdoc/ZBarReaderViewController.html
It says "This is the controller to use for live scanning from the camera feed with automatic capture. For scanning from image files or with manual capture, see ZBarReaderController."
This means that the ZBarReaderViewController object setup in startScanning method is not what is supposed to be there. Well, not for scanning a static image. I'll have to test the original code with an actual device rather than a Mac but it seems ZBarReaderController is what I really want.
The new startScanning method now looks like this:
- (IBAction)startScanning:(id)sender
{
resultTextView.text = #"Scanning..";
//Create a reader
ZBarReaderViewController *codeReader = [ZBarReaderController new];
//Setup a delegate to recieve the results
//The delegate implements the ZBarReaderDelegate protocol, which inherits from UIImagePickerControllerDelegate
codeReader.readerDelegate= self;
[codeReader.scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to: 0];
[self presentViewController:codeReader animated:YES completion:nil];
}
When testing I noted that images with a transparent background (such as the QR code and Barcode images provided on the tutorial site) do not work - you'll get a message saying no code found. You should save them as a jpg file with a white background.
I don't know if there should be anything else done to this since I only renamed an object and deleted a few code lines which gave errors - but the program does run the way I expect it to at the moment. If I have any future issues I'll post a new question.

Try this code.
ZBarReaderViewController *codeReader = [ZBarReaderViewController new];
codeReader.readerDelegate= self;
codeReader.supportedOrientationsMask = ZBarOrientationMaskAll;
[codeReader.scanner setSymbology:ZBAR_I25 config:ZBAR_CFG_ENABLE to:0];
[codeReader.readerView start];
[self presentViewController:codeReader animated:YES completion:nil];
Below is optional =)
[codeReader.readerView setZoom:2];
codeReader.view.frame = self.view.bounds;

Related

How to integrate Chartboost rewarded video with MoPub mediation for iOS

I make the game using Cocos2d-x ver. 3.4. I make the rewarded video with MoPub mediation in this game. I followed this guide on official github wiki.
So, first I incorporated the MoPub iOS SDK and Chartboost SDK in the project.
I set in AppDelegate.h:
#import <UIKit/UIKit.h>
#import "MoPub.h"
#import "MPRewardedVideo.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate, MPRewardedVideoDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, assign) NSInteger coinAmount;
#end
in AppDelegate.mm:
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
…
[self loadRewardedVideo];
return YES;
}
- (void)loadRewardedVideo {
[[MoPub sharedInstance] initializeRewardedVideoWithGlobalMediationSettings:nil delegate:self];
[MPRewardedVideo loadRewardedVideoAdWithAdUnitID:#“[MyAdUnitID]“ withMediationSettings:nil];
}
#pragma mark - MPRewardedVideoDelegate
- (void)rewardedVideoAdShouldRewardForAdUnitID:(NSString *)adUnitID reward:(MPRewardedVideoReward *)reward {
if ([reward.currencyType isEqualToString:#"coin"]) {
if ([reward.amount integerValue] == kMPRewardedVideoRewardCurrencyAmountUnspecified)
{
singleton->addToTotalCoins(10); // for test
} else
{
singleton->addToTotalCoins([reward.amount integerValue]);
}
}
}
This is buttons "showRewardedVideo" handler in RootViewController.mm:
#import "RootViewController.h"
#implementation RootViewController
- (void) showRewardedVideo
{
if ([MPRewardedVideo hasAdAvailableForAdUnitID:#"MyAdUnitID"])
{
[MPRewardedVideo presentRewardedVideoAdForAdUnitID:#"MyAdUnitID" fromViewController:self];
}
else
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Something went wrong"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
}
I set in MoPubSDK->AdNetworkSupport->Chartboost->ChartboostRewardedVideoCustomEvent.m:
- (void)requestRewardedVideoWithCustomEventInfo:(NSDictionary *)info
{
NSString *appId = [info objectForKey:#"MyChartboostAppID"];
NSString *appSignature = [info objectForKey:#"MyChartboostAppSignature"];
…
}
But when I run the application, I get in
- (void)communicatorDidReceiveAdConfiguration:(MPAdConfiguration *)configuration
the _networkType propertie = #"clear"
and get a message
MOPUB: Rewarded video ad is fetching ad network type: clear
The video is not displayed, and I get my alert window from RootViewController.mm -(void)showRewardedVideo method.
Seems MoPub doesn't know about Chartboost. I think, I need define settings in initializeRewardedVideoWithGlobalMediationSettings:nil, but how I should make this? I didn't found info about this.
Please tell me, what else needs to be done. Any help will be appreciated.
I think your problem is using no argument: initializeRewardedVideoWithGlobalMediationSettings:nil in loadRewardedVideo in AppDelegate.mm
In your guide they state that
Mediation settings enable you to pass in third-party network specific settings and can be provided as additional parameters during the rewarded video initialization call
so most probably you need that argument to be non-nil. Also, withMediationSettings should be non-null if you don't want MoPub to choose network by itself. They say it here:
The mediation settings array should contain ad network specific objects for networks that may be loaded for the given ad unit ID

Hard work to deal with state restoration in iOS

How to deal with "Warning: Unable to create restoration in progress marker file."
I have assigned the Restoration Ids to my view controllers in main story board.
I have also assigned Restoration Id to the view controllers created by code.
For example:
#interface BEMenuController ()<UIViewControllerRestoration>
.....
+ (UIViewController *) viewControllerWithRestorationIdentifierPath: (NSArray *)identifierComponents coder:(NSCoder *)coder
{
UIViewController *retViewController = [[BEMenuController alloc] init];
return retViewController;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.restorationIdentifier = #"BEMenuController";
self.restorationClass = [self class];
..........
}
I did as in following link asked
state restoration in iOS
Now the problem is when I run the application I am getting the following warning also:
Unable to create restoration in progress marker file.
Not sure what else need to be done.

TodayWidget viewDidLoad not running

I have recently added a Widget to my application, or have tried to. When I run it the widget shows in the notification center but it appears collapsed. I have confirmed the viewDidLoad is not being called by using NSLog. Any ideas why its not loading? Thanks.
Edit: it seems the problem is the label won't be added I had to create everything in the interface builder.
.h file
#import <UIKit/UIKit.h>
#import <NotificationCenter/NotificationCenter.h>
#interface TodayViewController : UIViewController {
UILabel *lblCurrentLocation;
}
#define SCREEN ([[UIScreen mainScreen] bounds])
#end
.m file
#import "TodayViewController.h"
#interface TodayViewController () <NCWidgetProviding>
#end
#implementation TodayViewController
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
lblCurrentLocation = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
lblCurrentLocation.text = #"Current Location: Unknown";
[self.view addSubview:lblCurrentLocation];
NSLog(#"Set up");
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^) (NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
completionHandler(NCUpdateResultNewData);
}
#end
Happens to me too (a lot). As far as I know there are a lots of troubleshooting while debugging the widget.
Try the following steps :
Stop the widget from running.
Remove the widget from Today view in notification center, by tapping on "Edit" button on the bottom of notification center.
Close the notification center.
Run the widget again.
Please check class name TodayViewController assign to your main interface builder.
In case of Today extension, it is normal that viewDidLoad is not getting called everytime. But, viewWillAppear and viewDidAppear get called everytime. For loading new data, you should put the code in this method:
func widgetPerformUpdate(completionHandler: ((NCUpdateResult) -> Void))
Commonly, in case of today extension, we use above method in place of viewDidLoad for getting and setting data. This method is going to be called whenever new data required.(It commonly called everytime, but if you are switching NotificationCenter frequently, this one only going to called first time). So, depending on your need use required method.
For further details, you can refer: https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/Today.html

How to display Full Screen iad for ipad

I just recently read that full screen iAd only works on iPad. ADInterstitialAd This Class To Use Developing Full Screen iAd. How To Implement Delegate Methodes in ADInterstitialAdDelegate?
You can use this for creating Full screen iAd
in .H file
Import
#import <iAd/iAd.h>
#interface ViewController : UIViewController<ADInterstitialAdDelegate>
{
ADInterstitialAd *interstitial;
}
in. M file
#interface ViewController ()
// Interstitials
- (void)cycleInterstitial;
#implementation ViewController
- (void)cycleInterstitial
{
// Clean up the old interstitial...
interstitial.delegate = nil;
// and create a new interstitial. We set the delegate so that we can be notified of when
interstitial = [[ADInterstitialAd alloc] init];
interstitial.delegate = self;
}
#pragma mark ADInterstitialViewDelegate methods
// When this method is invoked, the application should remove the view from the screen and tear it down.
// The content will be unloaded shortly after this method is called and no new content will be loaded in that view.
// This may occur either when the user dismisses the interstitial view via the dismiss button or
// if the content in the view has expired.
- (void)interstitialAdDidUnload:(ADInterstitialAd *)interstitialAd
{
[self cycleInterstitial];
}
// This method will be invoked when an error has occurred attempting to get advertisement content.
// The ADError enum lists the possible error codes.
- (void)interstitialAd:(ADInterstitialAd *)interstitialAd didFailWithError:(NSError *)error
{
[self cycleInterstitial];
}
// if you want to show iAd while pushing view controller just use
- (IBAction)onSearchClick:(id)sender {
if (interstitial.loaded) {
// [interstitial presentFromViewController:self]; // deprecated in iOS 6.
[self requestInterstitialAdPresentation]; // it will load iAD Full screen mode.
}
// do whatever you want to do.
}
Have a happy coding. Cheers.

Create a log in screen on iOS that will always show on top of all views

EDIT: Check below for solution.
I am working on a login screen for my app and I have it working for the most part except for a few edge cases. Ive set things up so that I have a segue from my UITabBar in the story board that I trigger in the app delegate applicationDidBecomeActive: method. As I said it works fine on all but one edge case I've found so far.
My app uses some modal view controllers, some of which are UIActivityViewControllers if that makes a difference, to enter and edit some core data entities. If one of these modal view controllers is opened when the app goes to the background, it will always show up when the app is reopened and my login doesn't show. I get the following console msg
Warning: Attempt to present <UINavigationController: 0x1d51e320> on <MPTabBarViewController: 0x1d5b4810> which is already presenting <UIActivityViewController: 0x1e38fc40>
Here is my code
- (void) displayLogin{
NSLog(#"%s", __PRETTY_FUNCTION__);
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
NSDate *lastDate = [[NSUserDefaults standardUserDefaults] objectForKey:MPLastCloseDate];
NSTimeInterval timeDiff = [[NSDate date] timeIntervalSinceDate:lastDate];
int seconds = timeDiff;
if ([[NSUserDefaults standardUserDefaults] integerForKey:MPPassCodeDelay] == MPScreenLockAlways || seconds >= 300) {
NSLog(#"Should see login");
[tabBarController performSegueWithIdentifier:#"loginScreen" sender:self];
}
}
I understand exactly what this msg is telling me, the tab bar is already presenting a modal controller so it can't present another one. So my question is this, Is there a better way to implement this so that the login will always show, even over top of the modal views?
Okay here is my current solution
as suggested by Bartu and requested to be shared by Shawn
I have a working singleton loginManager class that requires 1 call in app delegate and 1 call in any view controller that could be called to present as modal. I was unable to figure out how to do this as suggested with a ViewController category, but hey a few includes and method calls aren't so bad. I included it in App-Prefix.pch, so its available everywhere. It is written for ARC, so if you like managing your own memory you'll need to modify the singleton for that. The last caveat, at current you will need to roll your own viewController for the login screen. Just look for the commented section in the implementation with all the stars, and put your own view controller there. Mine is still in my app storyboard, its basically 4 digit pin that checks for a match in the keychain and dismisses itself for the correct pin. I may pull that out of my storyboard and nib it so it could be packaged with the loginManager and let it become my first gitHub project at some future date though.
You can configure it to display login for every time the app opens or after a delay with properties. The delay time is also a property set in seconds. It will also block out your apps UI for the few seconds it takes to get the login displayed with a splash using your apps Default.png. This is also configurable with a property.
I would love to get some feedback on this, and if anyone can tell me how to do a category so the extra call in viewControllers is not needed that would be great! Enjoy!
AppDelegate:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
[self.window makeKeyAndVisible];
// these calls are all optional
[[VHLoginManager loginManager] setShouldBlockUIWithSplashOnResume:NO];
[[VHLoginManager loginManager] setSecondsRequiredToPassBeforeLockDown:1000];
[[VHLoginManager loginManager] setScreenLockRequirment:VHLMScreenLockDelayed];
// this is the only required call to run with defaults - always login and block UI with splash while login loads
[[VHLoginManager loginManager] presentLogin];
}
Any viewController that may presented as modal at some point
- (void)viewDidLoad
{
[super viewDidLoad];
[[VHLoginManager loginManager] registerViewControllerIfModal:self];
}
The loginManager class
header:
// VHLoginManager.h
// Created by Victor Hudson on 5/31/13.
// Copyright (c) 2013 Victor Hudson. All rights reserved.
// Use if you like but be nice and leave my name
#import <Foundation/Foundation.h>
#define VHLMLastCloseDate #"VHLMLastCloseDate"
#define VHLMPassCodeDelay #"VHLMPassCodeDelay"
typedef enum {
VHLMScreenLockAlways = 0,
VHLMScreenLockDelayed = 1,
} VHLMScreenLockRequirement;
#interface VHLoginManager : NSObject
#property (nonatomic) BOOL shouldBlockUIWithSplashOnResume;
// defaults to yes so app contents arent visible before the login screen appears
#property (nonatomic) int secondsRequiredToPassBeforeLockDown;
// defaults to 5 minutes (300)
#pragma mark - Class Methods
+ (VHLoginManager *)loginManager;
// returns the singleton login manager
#pragma mark - Manager Methods
- (void) presentLogin;
// will determine if login should be presented an do so if needed
- (void) registerViewControllerIfModal:(UIViewController *)controller;
// any view controllers that are presented modally should call this with self as controller in viewDidLoad - the pupose of this manager is so login shows even over top of modals
- (void) setScreenLockRequirment:(VHLMScreenLockRequirement) requirement;
// deafaults to always if not adjusted
#end
implementation:
// VHLoginManager.m
// Created by Victor Hudson on 5/31/13.
// Copyright (c) 2013 Victor Hudson. All rights reserved.
// Use if you like but be nice and leave my name
#import "VHLoginManager.h"
static VHLoginManager *loginManager = nil;
#interface VHLoginManager ()
#property (nonatomic, strong) UIViewController *currentModalViewController;
#property (nonatomic) VHLMScreenLockRequirement screenLockrequirement;
#end
#implementation VHLoginManager
#pragma mark - Manager Methods
- (void) presentLogin
{
// NSLog(#"%s", __PRETTY_FUNCTION__);
if ([[NSUserDefaults standardUserDefaults] integerForKey:VHLMPassCodeDelay] == VHLMScreenLockAlways || [self timeSinceLastClose] >= self.secondsRequiredToPassBeforeLockDown) {
//NSLog(#"User should see login");
// determine who the presenting view controller should be
UIViewController *viewController;
if (self.currentModalViewController && self.currentModalViewController.presentingViewController != nil) {
// NSLog(#"We have a modal view controller on top");
viewController = self.currentModalViewController;
} else {
// NSLog(#"We have NO modal view controller on top");
// get the root view controller of the app
viewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
}
//********************************************************************************************************************************************************************************
// *** This is still tied into my app storyboard and should be made into a viewcontroller with nib to be portable with loginManager for now implement and present your own loginViewController
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
UINavigationController *navController = [storyboard instantiateViewControllerWithIdentifier:#"appLoginScreen"];
//********************************************************************************************************************************************************************************
// present the login to user
[viewController presentViewController:navController animated:NO completion:nil];
}
}
- (void) setScreenLockRequirment:(VHLMScreenLockRequirement) requirement
{
_screenLockrequirement = requirement;
[[NSUserDefaults standardUserDefaults] setInteger:self.screenLockrequirement forKey:VHLMPassCodeDelay];
}
- (void) registerViewControllerIfModal:(UIViewController *)controller
{
// NSLog(#"%s", __PRETTY_FUNCTION__);
if (controller.presentingViewController) {
NSLog(#"Registering a modalViewController");
self.currentModalViewController = controller;
}
}
#pragma mark - Private Methods
- (void) timeStampForBackground
{
// NSLog(#"%s", __PRETTY_FUNCTION__);
[[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:VHLMLastCloseDate];
[self setDisplaySplashForBackgroundResume];
}
- (int) timeSinceLastClose
{
return [[NSDate date] timeIntervalSinceDate:[[NSUserDefaults standardUserDefaults] objectForKey:VHLMLastCloseDate]];
}
#pragma mark Splash Screen management
- (void) setDisplaySplashForBackgroundResume
{
// NSLog(#"%s", __PRETTY_FUNCTION__);
if (self.shouldBlockUIWithSplashOnResume) {
// dismiss all keyboards and input views
UIView *topView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
[topView endEditing:YES];
// Don't show a splash screen if the application is in UIApplicationStateInactive (lock/power button press)
UIApplication *application = [UIApplication sharedApplication];
if (application.applicationState == UIApplicationStateBackground) {
UIImageView *splash = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default"]];
splash.frame = application.keyWindow.bounds;
[application.keyWindow addSubview:splash];
}
}
}
- (void) removeSplashScreen
{
// NSLog(#"%s", __PRETTY_FUNCTION__);
if (self.shouldBlockUIWithSplashOnResume) { // we should have a splash image up if true
// so remove it
UIWindow *thewindow = [[UIApplication sharedApplication] keyWindow];
if ([[thewindow subviews] count] > 1) {
[NSThread sleepForTimeInterval:1.0];
[[[thewindow subviews] lastObject] removeFromSuperview];
}
}
}
#pragma mark - Class Management
//prevent additional instances
+ (id)allocWithZone:(NSZone *)zone
{
return [self loginManager];
}
+ (VHLoginManager *)loginManager
{
if (!loginManager) {
//Create The singleton
loginManager = [[super allocWithZone:NULL] init];
}
return loginManager;
}
- (id) init
{
// If we already have an instance of loginManager
if (loginManager) {
//Return The Old One
return loginManager;
}
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(timeStampForBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(removeSplashScreen)
name:UIApplicationDidBecomeActiveNotification
object:nil];
self.shouldBlockUIWithSplashOnResume = YES;
self.secondsRequiredToPassBeforeLockDown = 300;
if (![[NSUserDefaults standardUserDefaults] integerForKey:VHLMPassCodeDelay]) {
[self setScreenLockRequirment:VHLMScreenLockAlways];
}
}
return self;
}
#end
I had the same problem a short time ago, my solution for this problem is to have a reference to any modal view which is currently presented in your app delegate. So, you can know if your tab bar controller is already presenting a modal controller and if it's the case, you can present your login view over your current modal view.
What I did was to have a switch in my appDelegate. when the app started, if the user had not logged in, I created the login view and make it the window's rootViewController. When the user successfully logged in, I used an animation block to set that view's alpha to 0, then created a UITabBarController, populated it, made it the window's rootViewController (with an alpha of 0, then animated it's alpha to 1). Worked really well. Not sure how to do this with storyboards though.
EDIT: now getting familiar with storyboards. So what you would do is not use the Main.storyboard per se (remove it from info.plist), then add a LoginViewController as a view, and have your UITabbarController there too - but nothing is the initial view controller. You obviously have to name each view so you can create it in code, but asking the Storyboard to create such and such a view controller
So in App Delegate, if logged in, instantiate the tab bar controller and add it as the root view controller. If the user has not logged in, create the LoginView and add it as rootview controller. If the user does login, have some method on the LoginViewController so it can ask the delegate to switch to the tab bar controller.

Resources