presenting UITableViewController blocks UI - objective-c

i'm trying to present a UITableViewController when a collectionViewCell is tapped. i've done this by using the didSelectItemAtIndexPath. When i press a collectionView Nothing happens and after i've pressed the UI is blocked and i cant do anything. No errors/log messages are shown. Why wont it present the viewController and why no error messages?
UITableViewController interfaceBuilder:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
HomeProfileViewController *hpvc = [storyboard instantiateViewControllerWithIdentifier:#"NavProfile"];
hpvc.idString= [[homesDic objectAtIndex:indexPath.item] objectForKey:#"idString"];
hpvc.imageArray = [[NSMutableArray alloc]init];
hpvc.imageArray = [imageDic objectAtIndex:indexPath.item];
[self presentViewController:hpvc animated:YES completion:nil];
}

My best guess is that storyBoard is taking time to load. Maintain an instance level storyBoard object and do a lazy instantiation at didSelectItemAtIndexPath.
Lazy instantiation code:
- (UIStoryboard *)storyboard: {
if (!_storyboard) {
_storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
}
return _storyboard;
}
And in your didSelectItemAtIndexPath,
UIStoryboard *storyboard = [self storyboard];
Again, this is my best guess. It is only deduced from the given code.

Related

Need help converting this bit of code from Swift to Objective-C

I have an Objective-C app where I need to load another VC class from within the code. I've managed to accomplish this in another Swift app.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "OverrideClass")
self.present(controller, animated: true, completion: nil)
I need help creating an identical function for ObjC. It's basically loading the class of the VC with the storyboard identifier mentioned in the code.
The code is very similar just with a different syntax...
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:NULL];
UIViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"OverrideClass"];
[self presentViewController:controller animated:YES completion:NULL];
Here's the code you provided re-written in Objective-C:
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:NULL];
UIViewController * controller = [storyboard instantiateViewControllerWithIdentifier:#"OverrideClass"];
[self presentViewController:controller animated:YES completion:NULL];

Fires presentedViewController several times

-(void) viewDidAppear:(BOOL)animated {
if (!self.hasPresentedModalMenuView) {
NSLog(#"Firing");
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"highScoresStory" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"highScores"];
[vc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:vc animated:YES completion:nil];
} }
This Keeps Repeating over and over again. I have taken out the code below "Firing", and if I do that, it only fires once. Why does this keep firing? Thank You for any help.

Adding Video as a splash in storyboard ios7

I want to show a video at the beginning of the application start, just like a splash. My whole app will be in Navigation. First, i add the video in a splashViewController and set it in appDelegate as rootView and then simply set the mainViewController as rootView again.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
splashViewController = [[SplashViewController alloc] init];
splashViewController = (SplashViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"SplashViewController"];
self.window.rootViewController = splashViewController;
[NSTimer scheduledTimerWithTimeInterval:9.0 target:self selector:#selector(removeSplashScreen:) userInfo:nil repeats:NO];
return YES;
}
-(void)removeSplashScreen:(id)userInfo
{
[splashViewController removeFromParentViewController];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
mainViewController = [[MainViewController alloc] init];
mainViewController = (MainViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"MainViewController"];
self.window.rootViewController = mainViewController;
}
Now i want to start navigation from this mainViewController. I use storyBoard & add navigation from Editor > Embed in > Navigation Controller in mainViewController. Don't do it programmatically. But i know the way of implementing it using Nib.xib. Here i also put the arrow(The arrow which indicate the starting VC) mark besides of it. But it getting crash when i click a button from mainVC to go next VC. How can i set the navigation here?
If any one have the answer, please share with me. Thanks a lot in Advance.
The scenario of my storyboard:
happy to help you here in two steps
step 1-
your didFinishLaunchingWithOptions code is almost correct , but it does not matter if its working . so let focus on step two.
step 2- in -(void)removeSplashScreen:(id)userInfo
-first line is good , but you even dont need it because you are going to switch the root controller (leave it for now)
- second line (no need to write it)
- third line is really bad , what you doing here is trying to alloc you mainviewcontroller. really you need it with storyboard? no
- you should load you main view controller from storyboard
MainViewController* mainViewController = (MainViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"MainViewController"];
"this line is enough to load your main view controller from storyboard"
-next line is correct
self.window.rootViewController = mainViewController;
code seems to be working now , but still you are missing navigation controller because you have loaded mainviewcontroller from storyboard, not the navigation controller.
- two solution for it
1- load navigation controller in place of mainviewcontroller(give a storyboard id to navigation controller , load it , and make it as root controller) --i will always go with it
2- make a navigation controller with allocating it & make its rootviewcontroller the mainviewcontroller
-----------------working code ---------------
Ok Despite my advice (in the comments), here is how you can achieve this:
Display splash:
//StoryBoard
UIStoryboard *mainStoryboard = [UIStoryboard
storyboardWithName:#"Main" bundle: nil];
//Splash Controller
SplashViewController *splashViewController = [mainStoryboard
instantiateViewControllerWithIdentifier:#"SplashViewController"];
//Show it
[self.window.rootViewController presentViewController:splashViewController
animated:NO completion:nil];
Remove it:
[self dismissViewControllerAnimated:YES completion:nil];
EDIT: Still not working?
Maybe you called it to quick. do this:
viewDidLoad:
[NSTimer scheduledTimerWithTimeInterval:9.0
target:self
selector:#selector(removeSplashScreen:)
userInfo:nil repeats:NO];
function to remove:
-(void)removeSplashScreen:(id)userInfo
{
[self dismissViewControllerAnimated:YES completion:nil];
}
So the solution, according to pawan's given answer is :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
splashViewController = (SplashViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"SplashViewController"];
self.window.rootViewController = splashViewController;
[NSTimer scheduledTimerWithTimeInterval:9.0 target:self selector:#selector(removeSplashScreen:) userInfo:nil repeats:NO];
return YES;
}
-(void)removeSplashScreen:(id)userInfo
{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
mainViewController = [[MainViewController alloc] init];
mainViewController = (MainViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"MainViewController"];
navigationContoller = [[UINavigationController alloc] initWithRootViewController:mainViewController];
self.window.rootViewController = navigationContoller;
}
:)

Storyboard and custom init

I recently tried working with the MainStoryboard.storyboard within Xcode and so far It's going pretty good and I'm wondering why I've never used it before. While playing with some code I bumped into an obstacle and I don't know how to resolve this.
When I alloc and init a new ViewController (with a custom init I declared in the ViewControllers class) I would do something like this:
ViewController *myViewController = [[ViewController alloc] initWithMyCustomData:myCustomData];
Then after that I could do something like:
[self presentViewController:myViewController animated:YES completion:nil];
When I'm working with a storyboard I'm learnt that switching to a standalone ViewController requires an Identifier.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:#"MyViewControllerIdentifier"];
[self presentViewController:myViewController animated:YES completion:nil];
How can I still use my custom initialization for myViewController while making use of a storyboard?
Is it ok to just do something like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
ViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:#"MyViewControllerIdentifier"];
myViewController.customData = myCustomData;
[self presentViewController:myViewController animated:YES completion:nil];
//MyViewController.m
- (id) initWithMyCustomData:(NSString *) data {
if (self = [super init]) {
iVarData = data;
}
return self;
}
I would just create a method which does the custom data loading.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
MyViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:#"MyViewControllerIdentifier"];
[myViewController loadCustomData:myCustomData];
[self presentViewController:myViewController animated:YES completion:nil];
If all your initWithCustomData method does is set one instance variable, you should just set it manually (no custom inits or extra methods required):
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
MyViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:#"MyViewControllerIdentifier"];
myViewController.iVarData = myCustomData;
[self presentViewController:myViewController animated:YES completion:nil];
You can instantiate viewcontroller in -init method.
- (instancetype)init
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
self = [storyboard instantiateViewControllerWithIdentifier:#"MyViewController"];
if(self)
{
//default initialization
}
return self;
}
and the in your custom init method
- (instancetype)initWithImages:(NSArray *)images
{
self = [self init];
if(self)
{
self.images = images;
}
return self;
}
My version:
- (instancetype)initWithData (NSArray *)someData
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
self = [storyboard instantiateViewControllerWithIdentifier:#"MyViewController"];
if(self)
{
//default initialization
}
return self;
}
...one initializer ;)

How to perform Segue in AppDelegate?

I am trying to complete an application on IOS 5.1 with Storyboard. Basically I am doing a dropbox app. Since I am using Dropbox SDK link to Dropbox is handled in AppDelegate.m. User has the option of be able to unlink from a session and link again in different View Controllers. So every time user link and unlinked app has to switch view from Appdelegate to a view controller that is unconnected to rootviewcontroller
In original Dropbox's example Dropbox handled transition like following code
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
[navigationController pushViewController:rootViewController.photoViewController animated:YES];
}
return YES;
}
return NO;
}
But I am using Storyboard with Navigation Controller and any of the following methods are not working I put methods in comments.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
/*UIViewController *viewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:#"MeetingViewController"];
[self.navigationController pushViewController:viewController animated:YES]; */
//[self performSegueWithIdentifier:#"xxxx" sender:self];
/* LoginDropboxViewController *loginController=[[LoginDropboxViewController alloc] initWithNibName:#"LoginDropbox" bundle:nil];
[navigationController pushViewController:loginController animated:YES]; */
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
Here is the storyboard of the app
So how can I switch view in AppDelegate.h ?
Note: If I add a segue and name the segue lets say goToMeeting
[self performSegueWithIdentifier:#"goToMeeting" sender:self];
error I get is : No Visible #interface for 'AppDelegate' declares the selector performSegueWithIdentifier:sender
If you consider pushing view manually rather then segueperform following code most probably will work for you
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
//push view manually
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
LoginDropboxViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:#"LoginDropbox"];
[(UINavigationController*)self.window.rootViewController pushViewController:ivc animated:NO];
}
return YES;
}
// Add whatever other url handling code your app requires here
return NO;
}
You can do it like this:
UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController;
[[[navigationController viewControllers] objectAtIndex:0] performSegueWithIdentifier:#"goToMeeting" sender:self];
This will only work if the index in viewControllers array matches the one of your view controller and if it exists of course. In this case is the first one (in the array and storyboard).
The segue ("goToMeeting") must not be attached to an action. The way you do this is by control-dragging from the file owner icon at the bottom of the storyboard scene to the destination scene. A popup will appear that will ask for an option in “Manual Segue”; pick “Push” as the type. Tap on the little square and make sure you’re in the Attributes Inspector. Give it an identifier which you will use to refer to it in code.
In my case i need to go to dashboard screen from appdelegate using segue, the code as below in objective c.
if([rememberMe isEqualToString:#"YES"]){
//Goto Dashboard
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SWRevealViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"revealVc"];
self.window.rootViewController = vc;
[self.window.rootViewController performSegueWithIdentifier:#"sw_front" sender:self];
[self.window makeKeyAndVisible];
}else{
//Goto login
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LoginViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
Write inside your didFinishLaunchingWithOptions
Hope it helps some one.