IOS 6 MPMoviePlayerController Rotation Issue - ios6

I have just updated to IOS 6 and now when I run my app the MPMoviePlayerControler shows the video incorrectly. The app is landscape but when the video is displayed in portrait. I have created new .h and .m files which is a child of MPMoviePlayerController. Here are my two files
.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import <MediaPlayer/MediaPlayer.h>
#interface TrashPackPlayer : MPMoviePlayerController
#end
.m
#import "TrashPackPlayer.h"
#implementation TrashPackPlayer
-(id)init{
[super init];
return self;
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
#end
I create the media player like this:
player = [[TrashPackPlayer alloc] initWithContentURL:videoURL];
player.view.frame = CGRectMake(0, 0, sharedInfo.screenSize.width, sharedInfo.screenSize.height);
player.controlStyle = MPMovieControlStyleFullscreen;
player.scalingMode = MPMovieScalingModeAspectFit;
[player play];
[[[CCDirector sharedDirector] openGLView] addSubview:player.view];
Is this correct?
What do I need to do to get this displaying correctly?

Rotations in iOS6 have changed dramatically, check the fourth point at:
http://megawertz.com/blog/2012/9/20/ios-6-and-rotation
The top-most view controller is in charge of setting the allowed orientations, subclassing a view controller is not going to solve your problem.

Related

Throwing a MacOS notification from a minimal standalone Objective-C program?

I'm trying to implement push notifications on MacOS within a C codebase. Ideally, there'd just be one Objective-C file containing (1) a public C function I can call and (2) some Objective-C code I can use to throw a notification. This way, the source files can be compiled and linked seamlessly in the build process.
Toward this end, I've been trying to create a minimal example that can throw notifications with just a single .m file (not an entire XCode project), much like the one discussed in NSUserNotificationCenter not showing notifications. However, two problems:
I still can't get the code to work despite trying the solutions in the aforementioned link. It compiles and runs but does not throw a notification.
If possible, we'd like to switch to the new user notifications API. Not a big deal if this isn't possible for now, though.
Here's what I've tried so far:
#import <Foundation/Foundation.h>
#import <Foundation/NSUserNotification.h>
#interface AppDelegate : NSObject <NSUserNotificationCenterDelegate>
#end
#implementation AppDelegate
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
shouldPresentNotification:(NSUserNotification *)notification {
return YES;
}
- (void)throwNotification {
NSUserNotification *userNotification = [[NSUserNotification alloc] init];
userNotification.title = #"Some title";
userNotification.informativeText = #"Some text";
printf("trying to throw {%s %s}\n", [[userNotification title] UTF8String], [[userNotification informativeText] UTF8String]);
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:userNotification];
}
#end
int main (int argc, const char * argv[]) {
AppDelegate *app = [[AppDelegate alloc] init];
[app throwNotification];
return 0;
}
This is compiled with cc -framework Foundation -o app main.m.
Any insight would be appreciated!
The problem is that in order to display a notification, you need to have a proper bundle identifier.
We're going to take a bit of the code from here, where we wait for the notification to get displayed. We can embed an Info.plist file into the compiled binary, which will accomplish the same thing as the swizzling code in a file called notify.m:
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject<NSUserNotificationCenterDelegate>
#property (nonatomic, assign) BOOL keepRunning;
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
NSApplication *app = [NSApplication sharedApplication];
AppDelegate *appdel = [[AppDelegate alloc] init];
app.delegate = appdel;
NSUserNotificationCenter *nc = [NSUserNotificationCenter defaultUserNotificationCenter];
nc.delegate = appdel;
appdel.keepRunning = TRUE;
NSUserNotification *userNotification = [[NSUserNotification alloc] init];
userNotification.title = #"Some title";
userNotification.informativeText = #"Some text";
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:userNotification];
while (appdel.keepRunning) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
return 0;
}
#implementation AppDelegate
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
shouldPresentNotification:(NSUserNotification *)notification {
return YES;
}
- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification
{
self.keepRunning = NO;
}
#end
I construct an Info.plist file consisting of the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.finder</string>
</dict>
</plist>
Please use an appropriate bundle identifier, as com.apple.finder will cause all these notifications to appear to come from macOS Finder, which might be confusing to users.
I then compile it using:
clang -o notify -framework Cocoa notify.m -Wl,-sectcreate,_\_TEXT,__info_plist,Info.plist
there's a \ in that build line to avoid the markdown parsing of the underscores, but it's not needed for the actual build command line.

UICollectionView rearrange cells on rotation

I would like to rearrange UICollectionView cells during the rotation of my device in a similar way this is done in the evernote iPads app for the notes. In the default implementation there is just a fade-in and fade-out of the cells but i would like to have the cells to move around during the rotation.
What would be the recommended way to achieve a similar animation? Do I need to create a custom UICollectionViewLayout?
I managed to get the desired rotation effect by subclassing UICollectionViewFlowLayout and overriding the two methods: initialLayoutAttributesForAppearingItemAtIndexPath and finalLayoutAttributesForDisappearingItemAtIndexPath which are the two points of controls to respectively define the starting/final layout information for an item being inserted into the collection view.
See source code:
.h:
#import "UICollectionView.h"
#interface UITestCollectionViewFlowLayout : UICollectionViewFlowLayout
#end
.m:
#import "UITestCollectionViewFlowLayout.h"
#interface UITestCollectionViewFlowLayout ()
{
BOOL _isRotating;
}
#property (strong, nonatomic) NSIndexPath* lastDissappearingItemIndex;
#end
#implementation UITestCollectionViewFlowLayout
#synthesize lastDissappearingItemIndex = _lastDissappearingItemIndex;
// returns the starting layout information for an item being inserted into the collection view
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
UICollectionViewLayoutAttributes* attributes = (UICollectionViewLayoutAttributes *)[self layoutAttributesForItemAtIndexPath:itemIndexPath];
if (_isRotating) // we want to customize the cells layout only during the rotation event
{
if ([self.lastDissappearingItemIndex isEqual:itemIndexPath])
return nil; // do not animate appearing cell for the one that just dissapear
else
{
attributes.alpha = 0;
// setting the alpha to the new cells that didn't match the ones dissapearing is not enough to not see them so we offset them
attributes.center = CGPointMake(attributes.center.x, attributes.size.height * 2 + attributes.center.y);
}
}
return attributes;
}
// returns the final layout information for an item that is about to be removed from the collection view
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath*)itemIndexPath
{
UICollectionViewLayoutAttributes* attributes = (UICollectionViewLayoutAttributes *)[self layoutAttributesForItemAtIndexPath:itemIndexPath];
if (_isRotating)
{
attributes.alpha = 1.0;
self.lastDissappearingItemIndex = itemIndexPath;
}
return attributes;
}
- (void) viewController:(UIViewController *)viewController didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
_isRotating = NO;
}
- (void) viewController:(UIViewController *)viewController willRotateToInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration
{
_isRotating = YES;
}
Note that i am using a flag that i set from the viewcontroller who create this flowlayout to know when we are actually rotating or not; the reason being that i want this effect to happen only during rotation.
I am interested to hear feedbacks/improvement about this code.

MFMessageComposeViewController not full screen on 4" screen

I'm make an iPhone app, in this app the user can send a SMS.
On my iPhone 4 is my screen perfect, but on my iPhone 5 i get a blank box.
iPhone only. iOS 6x
Screenhot (iphone5): http://i.stack.imgur.com/ZOqu1.png
#import "smsview.h"
#interface smsview ()
#end
#implementation smsview
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
[self dismissModalViewControllerAnimated:YES];
if (result == MessageComposeResultCancelled)
NSLog(#"Message cancelled");
else if (result == MessageComposeResultSent)
NSLog(#"Message sent");
else
NSLog(#"Message failed");
}
- (void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
{
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText])
{
controller.body = bodyOfMessage;
controller.recipients = recipients;
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}
}
-(IBAction)Text:(id)sender
{
{
[self sendSMS:#"" recipientList:[NSArray arrayWithObjects:#"+1-234-567-8910", nil]];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Follow these steps if u failed to.
Are you using the latest version of Xcode if not download from here.
You can use the Auto layout feature and create the design the using iPhone 5 screen resolution and it will work for the both 4" and 3.5" devices, but in this case you should have a enough knowledge of layout manager.
Set a 4-inch launch image for your app. This is how you get 1136 px screen height (without it, you will get 960 px with black margins on top and bottom), To adapt your app to the new taller screen, the first thing you do is to change the launch image to: Default-568h#2x.png. Its size should be 1136x640 (HxW). Yep, having the default image in the new screen size is the key to let your app take the whole of new iPhone 5's screen..
Hopefully everything should work if you had set auto resizing masks properly.
If you didn't, adjust your view layouts with proper auto resizing masks or look into Auto Layout if you only want to support iOS 6 going forward.
If there is something you have to do for the larger screen specifically, then it looks like you have to check height of [[UIScreen mainScreen] bounds] (or applicationFrame, but then you need to consider status bar height if it's present) as there seems to be no specific API for that.
for instance:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) {
//iPhone 4 specific
} else {
//iPhone 5 specific
}
Hope this solves your problem.

Zooming UIImageView inside UIScrollView with autolayout

I have a UIImageView embedded inside a UIScrollView, prior to iOS 6 and autolayout I used the following snippet inside the controller's viedDidLoad method to display a scrollable and zoomable image.
self.scrollView.contentSize = self.imageView.image.size;
self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
But now the constraints set in the storyboard are used instead. I've found this question Embed ImageView in ScrollView with Auto Layout on iOS 6 and some others here in SO stating that constraints are loaded/enforced after viewDidLoad, and that moving my previous snippet to viewDidAppear would fix this issue but zooming does not work properly and it seems that the sizes of the scrollView and the imageView are reset to the storyboard's constraint after a pinch-to-zoom gesture.
I'm just guessing, but I think maybe if there's some way to override the scrollView's and imageView's vertical and horizontal space constraints in code that might work.
Anyone else having this issues?
The best solution was proposed by Zsolt in the comments:
http://github.com/evgenyneu/ios-imagescroll check this out. Works perfectly for me.
The solution proposed in this repository is to adjust the minimum and current zoom level before displaying the image:
#interface MyViewController () <UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.delegate = self;
[self initZoom];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self initZoom];
}
// Zoom to show as much image as possible
- (void) initZoom {
float minZoom = MIN(self.view.bounds.size.width / self.imageView.image.size.width,
self.view.bounds.size.height / self.imageView.image.size.height);
if (minZoom > 1) return;
self.scrollView.minimumZoomScale = minZoom;
self.scrollView.zoomScale = minZoom;
}
- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
However sample conatins issue with zooming out. Image is not getting centered. This can be easily fixed by using the custom scroll view class with the following code in it:
#interface MyScrollView : UIScrollView
#end
#implementation MyScrollView
-(void)layoutSubviews
{
[super layoutSubviews];
UIView* v = [self.delegate viewForZoomingInScrollView:self];
CGFloat svw = self.bounds.size.width;
CGFloat svh = self.bounds.size.height;
CGFloat vw = v.frame.size.width;
CGFloat vh = v.frame.size.height;
CGRect f = v.frame;
if (vw < svw)
f.origin.x = (svw - vw) / 2.0;
else
f.origin.x = 0;
if (vh < svh)
f.origin.y = (svh - vh) / 2.0;
else
f.origin.y = 0;
v.frame = f;
}
#end
Solved my problem using the following code sample. The github repository corresponds to the book Programming iOS by Matt Neuburg.
https://github.com/mattneub/Programming-iOS-Book-Examples/blob/11c6c57743b04e6e722b635b87be69fa41a5abaf/ch20p573scrollViewAutoLayout/ch20p573scrollViewAutoLayout/ViewController.m
I also agree with Zsolt's suggestion and link.
But I update the width/height constraints to allow it to handle any size image:
- (void) initZoom
{
for (NSLayoutConstraint *constraint in self.photoImageView.constraints)
{
if (constraint.firstAttribute == NSLayoutAttributeWidth)
constraint.constant = self.photoImageView.image.size.width;
else if (constraint.firstAttribute == NSLayoutAttributeHeight)
constraint.constant = self.photoImageView.image.size.height;
}
float minZoom = MIN(self.scrollView.bounds.size.width / self.photoImageView.image.size.width,
self.scrollView.bounds.size.height / self.photoImageView.image.size.height);
if (minZoom > 1) return;
self.scrollView.minimumZoomScale = minZoom;
self.scrollView.zoomScale = minZoom;
}

UICollectionView Setup Help for Newbie

First, apologies if the answer is quite obvious but I'm brand new to iOS development (like this is the first app I'm trying to program even though it's just for me to play with :P) so the probability that my problem is rather minor is quite high.
Code (zip file containing the xcode project):
http://www.mediafire.com/?p55xw0q2dwwwwvm
I promise there's nothing else in there that's harmful :).
Problem:
I'm following:
http://www.techotopia.com/index.php/An_iPhone_iOS_6_Storyboard-based_Collection_View_Tutorial
I'm attempting to make a UICollectionView to play around with. I got down to the "Testing the Application" section. I put my own spin on a few parts from the guide:
instead of using different pictures, I just use 1 picture with a label at the bottom that just has a number in it. The number is dynamically set. Yes, I could implement it without the array I'm using, but having that array there will be helpful if I extend this project's scope in the future.
I added code in viewDidLoad to set the view layout to a flow layout. This was done again for futureproofing since once I get this working at a basic form I want to play around with formatting which will require me to subclass flowlayout.
The code compiles without errors but nothing shows up on the screen. I've checked the code to the best of my ability for about an hour or two, but nothing I did made any difference. My controller class is a bare bones attempt to just get the collection view to show up on screen, and my cell class is a bare bones cell with just an imageview and label in it.
Thanks for any help that can be given to get this working!
tl;dr
Just look at the bolded stuff. Code provided below for convenience:
MyCollectionViewController.m
#import "MyCollectionViewController.h"
#interface MyCollectionViewController ()
#property (nonatomic, strong) NSMutableArray *dataArray;
#end
#implementation MyCollectionViewController
#synthesize dataArray = _dataArray;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Create data to display
for(int i = 0; i < 50; i++){
[self.dataArray addObject:[NSString stringWithFormat:#"%d", i]];
}
// Configure Layout
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.collectionView setCollectionViewLayout:flowLayout];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark UICollectionViewDataSource
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section
{
return [self.dataArray count];
}
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
int row = [indexPath row];
UIImage* image = [UIImage imageNamed:#"200px-AND_ANSI"];
myCell.cellTitle = [self.dataArray objectAtIndex:row];
myCell.cellImageView.image = image;
myCell.backgroundColor = UIColor.whiteColor;
return myCell;
}
MyCollectionViewcontroller.h
#import <UIKit/UIKit.h>
#import "MyCollectionViewCell.h"
#interface MyCollectionViewController : UICollectionViewController <UICollectionViewDataSource, UICollectionViewDelegate>
#end
MyCollectionViewCell.h
#import <UIKit/UIKit.h>
#interface MyCollectionViewCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UIImageView *cellImageView;
#property (strong, nonatomic) IBOutlet UILabel *cellTitle;
#end
MyCollectionViewCell.m
#import "MyCollectionViewCell.h"
#implementation MyCollectionViewCell
#synthesize cellImageView = _cellimageView;
#synthesize cellTitle = _cellTitle;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
self.dataArray is nowhere allocated/initialized in your code and therefore is equal to nil. Sending messages to nil is allowed, but has no effect, therefore even after
for(int i = 0; i < 50; i++){
[self.dataArray addObject:[NSString stringWithFormat:#"%d", i]];
}
self.dataArray is still nil, and [self.dataArray count] returns 0.
You have to allocate and initialize the array with
self.dataArray = [[NSMutableArray alloc] init];
A proper place is some initXXX method of the view controller. But initWithNibName: is not called if the view controller is instantiated from a storyboard file, you have to use initWithCoder: instead:
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
self.dataArray = [NSMutableArray array];
}
return self;
}

Resources