I am building an iOS7 app and I am trying to make use of the new useLayoutToLayoutNavigationTransitions effect. I have 2 UICollectionViewControllers and when I do the following I get the transition effect
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondVC.useLayoutToLayoutNavigationTransitions = YES;
[self.navigationController pushViewController:secondVC animated:YES];
this works fine but what I want to do is make an api call and then in the completion block I want to push onto the nav stack like so
[webAPI getDetailsWithParams:params andCompletionBlock:^(id dict) {
//some work on the result
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondVC.useLayoutToLayoutNavigationTransitions = YES;
[self.navigationController pushViewController:secondVC animated:YES];
} andErrorBlock:^(NSError *error) {
}];
but this crashes every time with the following msg
-[UICollectionView _invalidateLayoutWithContext:]: message sent to deallocated instance 0x17a26400
can anyone tell me what I am doing wrong in this case? How can I get the transition effect when pushing from completion block?
EDIT: by changing it to the following I was able to transition to the second viewcontroller.
MyLayout *layout = [[MyLayout alloc] init];
SecondViewController *expandedVC = [[SecondViewController alloc] initWithCollectionViewLayout:layout];
and I also deleted the nib file that went with the file. nib file just consisted of a collection view and it was the file owners view.
While I can now transition I still do not understand why I could not do the previous nib method with in a block. So I would be grateful if someone could shed some light on it for me.
In order to use UICollectionViewController's useLayoutToLayoutNavigationTransitions to make transitions, the layout of the SecondViewController must be known. However, if you use initWithNibName:bundle: initializer, layout is not internally prepared yet, making your desired transitions impossible. As you mentioned in your edited question, you have to use [UICollectionViewController initWithCollectionViewLayout:] to initialize your second UICollectionViewController. Since your xib file has the same name as your class name, SecondViewController.xib is going to be loaded automatically by UIViewController, superclass of UICollectionViewController.
I think you were making UIKit calls from a thread that wasn't the main thread
Related
Okay so I have my ImagePicker all setup and the ALAssetLibrary setup to get the Picture and Title (if it exists for existing pictures or generic text for a new picture) but now I'm trying to figure out if there's a way I can access this information outside of the block call from the assetForURL method. So here's my code just so I can show what's happening (this is in the viewDidLoad method of a screen that is displayed after a picture selection is made)
__block NSString *documentName;
__block UIImage *docImage;
NSURL *resourceURL = [imageInfo objectForKey:UIImagePickerControllerReferenceURL];
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *asset)
{
ALAssetRepresentation *imageRep = [asset defaultRepresentation];
//Get Image
CGImageRef iref = [imageRep fullResolutionImage];
//If image is null then it's a new picture from Camera
if (iref == NULL) {
docImage = [imageInfo objectForKey:UIImagePickerControllerOriginalImage];
documentName = #"New Picture";
}
else {
docImage = [UIImage imageWithCGImage:iref];
documentName = [imageRep filename];
}
};
// get the asset library and fetch the asset based on the ref url (pass in block above)
ALAssetsLibrary *imageAsset = [[ALAssetsLibrary alloc] init];
[imageAsset assetForURL:resourceURL resultBlock:resultblock failureBlock:nil];
Now I want to be able to use the two variables (documentName and docImage) elsewhere in this ViewController (for example if someone wants to change the name of the document before they save it I want to be able to revert back to the default name) but I can't seem to figure out what I need to do so these variables can be used later. Don't know if this makes much sense or not, so if I need to clarify anything else let me know.
Okay so I figured out that the problem wasn't with the code but with my logic on how I was using it. I was trying to do this on the Modal View that was presented after an image was selected instead of just doing this in the ImagePicker screen and then calling the Modal window inside of the result block code.
In my cocos3d application, i have a UIViewController as rootview controller and from there i'll launch again Cocos3d scenes when use clicking on an option.
Here is my code below to launch scene from this view controller. Issue is, if i open uiviewcontroller and then move to scene by clicking on an option more than twice, then i'm getting error as "OpenGL error 0x0506 in -[EAGLView swapBuffers]
[GL ERROR] Unknown GL error (1286), before drawing HomeOwners3DScene Unnamed:1691. To investigate further, set the preprocessor macro GL_ERROR_TRACING_ENABLED=1 in your project build settings."
[This issue doesn't come first time when i view the scene, it shows properly. But if i go back and click back to show the scene more than twice or more, then it appeared to be blank scene with the below error in xcode]
Code below to move from my viewcontroller to further scenes:
-(void) launchMainScene :(UIViewController *) uiViewCrtller
{
[uiViewCrtller.view removeFromSuperview];
// This must be the first thing we do and must be done before establishing view controller.
if( ! [CCDirector setDirectorType: kCCDirectorTypeDisplayLink] )
[CCDirector setDirectorType: kCCDirectorTypeDefault];
// Default texture format for PNG/BMP/TIFF/JPEG/GIF images.
// It can be RGBA8888, RGBA4444, RGB5_A1, RGB565. You can change anytime.
CCTexture2D.defaultAlphaPixelFormat = kCCTexture2DPixelFormat_RGBA8888;
// Create the view controller for the 3D view.
viewController = [CC3DeviceCameraOverlayUIViewController new];
//viewController.supportedInterfaceOrientations = UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
// Create the CCDirector, set the frame rate, and attach the view.
CCDirector *director = CCDirector.sharedDirector;
//director.runLoopCommon = YES; // Improves display link integration with UIKit
[director setDeviceOrientation:kCCDeviceOrientationPortrait];
director.animationInterval = (1.0f / kAnimationFrameRate);
director.displayFPS = YES;
director.openGLView = viewController.view;
// Enables High Res mode on Retina Displays and maintains low res on all other devices
// This must be done after the GL view is assigned to the director!
[director enableRetinaDisplay: YES];
[director setDepthTest:NO];
// Create the window, make the controller (and its view) the root of the window, and present the window
[window addSubview: viewController.view];
CCDirector.sharedDirector.displayFPS = NO;
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
// Set to YES for Augmented Reality 3D overlay on device camera.
// This must be done after the window is made visible!
viewController.isOverlayingDeviceCamera = NO;
// Create the customized CC3Layer that supports 3D rendering and schedule it for automatic updates.
CC3Layer* cc3Layer = [HomeOwners3DLayer node];
[cc3Layer scheduleUpdate];
// Create the customized 3D scene and attach it to the layer.
// Could also just create this inside the customer layer.
cc3Layer.cc3Scene = [HomeOwners3DScene scene];
// Assign to a generic variable so we can uncomment options below to play with the capabilities
CC3ControllableLayer* mainLayer = cc3Layer;
CCScene *scene = [CCScene node];
[scene addChild: mainLayer];
[[CCDirector sharedDirector] runWithScene: scene];
}
Below Error is throwing in Xcode console when i launch scene and go back viewcontroller and launch scene multiple times with showing blank screen in the scene:
*[This issue doesn't come first time when i view the scene, it shows properly. But if i go back and click back to show the scene more than twice or more, then it appeared to be blank scene with the below error in xcode]*
OpenGL error 0x0506 in -[EAGLView swapBuffers]
[GL ERROR] Unknown GL error (1286), before drawing HomeOwners3DScene Unnamed:1691. To investigate further, set the preprocessor macro GL_ERROR_TRACING_ENABLED=1 in your project build settings.
Please help to solve my problem.
Thank you.
I have a code like this:
MyViewController *myController = [[MyViewController alloc] init];
[self.myNavController pushViewController:myController animated:YES];
[myController release];
In above case, deallc of MyViewController gets called twice resulting in a crash.
If I remove the last line "[myController release];" everything is fine.
Isn't this against the memory management guidelines?
if i understand truly, you must use initWithNibName against init like below:
MyViewController *myController = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
Please try this and reply, best regards.
Are you sure that the MyViewController's dealloc method not release someObj more than once?
You can try to clear away dealloc content,then,run the app again.
I search Google to find a good answer but the most tutorials are shown in previous Xcode Versions...
Also, I don't want to drag-n-drop cells from the Interface Builder, but to control the Table View programmatically (from an NSObject subclass file).
What I currently do is this: 1. Create a file named tableController.h that is a subclass of NSObject.
2. I create an NSObject Object in my Nib File (and set it as a subclass of tableController).
3. I drag a Table View to my window.
4. I CTRL+Drag from the Table View to my tableController.h so to create the outlet "tableView"
5. I create these functions in the interface file:
-(int)numberOfRowsInTableView:(NSTableView *)cocoaTV;
-(id)tableView:(NSTableView *)cocoaTV:objectValueForTableCollumn:(NSTableColumn *)tableCollumn row:(int)row;
6. I implement the functions like this:
-(int)numberOfRowsInTableView:(NSTableView *)cocoaTV{
return 5;
}
-(id)tableView:(NSTableView *)cocoaTV:objectValueForTableCollumn:(NSTableColumn *)tableCollumn row:(int)row{
NSArray *tvArray = [[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
NSString *v = [tvArray objectAtIndex:row];
return v;
}
Then I CTRL+Drag from the Object in the Interface Builder to the Table View to set the dataSource and to set it as delegate.
When I build and Run the App it shows that it has created the 5 Rows but in every cell in every column it says "Table View Cell".
Any help would be appreciated....
-(id)tableView:(NSTableView *)cocoaTV:objectValueForTableCollumn:(NSTableColumn *)tableCollumn row:(int)row is wrong.. i'm not sure how it compiles, to be honest (unless there was an error copy/pasting it). the method should look like:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSArray *tvArray = [[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
NSString *v = [tvArray objectAtIndex:row];
return v;
}
I'm having some trouble understanding how all the "nuts and bolts" of the Master-Detail Application template works using Xcode 4.2 (without MainWindow.xib, as well as other changes). In "AppDelegate" we have the following code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil];
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];
return YES;
}
I see that the window is created programmatically instead of using the MainWindow.xib that was use in previous versions of Xcode in the beginning, as well as instantiating objects for both "Master" and "Detail" view controller classes that are provided with the template and using them for separate UINavigationControllers. Then the splitViewController property is assigned a new allocated UISplitViewController object assigning the detailViewController as the "delegate" and an array is created that contains both UINavigationControllers as "viewControllers." Then the window.rootViewController is assigned this splitViewController object.
The main questions I have are
1) Why do I need two "UINavigationControllers?" Couldn't I just create the "viewController" array using the "master" and "detail" view controllers themselves?"
2) What does it do setting the "detailViewController" as the "delegate?" What actually gets delegated?
3) And finally, if I wanted to push additional items onto the "DetailViewController" stack, would I just use the "DetailViewController" class to push using the "didSelectRow.." method, or would I need to do updates to self.splitViewController.viewControllers property instead?
1) Why do I need two "UINavigationControllers?" Couldn't I just create the "viewController" array using the "master" and "detail" view controllers themselves?"
You don't need. But it's a way. You have the ability to push the masterViewControlleras well as the detailViewController. Look at the layout in Storyboard. With using segue you can change the controllers on each side as you like.
2) What does it do setting the "detailViewController" as the "delegate?" What actually gets delegated?
The UISplitViewget's delegated. The detailViewController will take care of the interface changing in portrait and landscape mode. See UISplitViewDelegate in the documentation.
Showing and Hiding View Controllers
– splitViewController:shouldHideViewController:inOrientation:
– splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
– splitViewController:willShowViewController:invalidatingBarButtonItem:
– splitViewController:popoverController:willPresentViewController:
3) And finally, if I wanted to push additional items onto the "DetailViewController" stack, would I just use the "DetailViewController" class to push using the "didSelectRow.." method, or would I need to do updates to self.splitViewController.viewControllers property instead?
Yes you can push in the masterViewControllerwith the tableView selection. You can push either with the new controller on the masterViewControllerstack by pushing in the
- (void)viewDidAppear:(BOOL)animated
and you can push in any way you like. You don't have to update the self.splitViewController.viewControllers property. Maybe you have to set the delegate to your new detailViewController.