Good morning.
I'm having trouble with a UIImagePickerController not showing anything other than white. I have a 320x320 UIImageView, in my main header file:
IBOutlet UIImageView *_cameraView;
Along with:
#property (nonatomic, retain) UIImagePickerController *_cameraPicker;
#property (nonatomic, retain) UIImage *_noCam;
_noCam is an image which is placed in the view if the user has no camera. That works fine.
I'm trying to show (without the standard camera GUI, but that can wait for now) the camera on top of this square view. In my main class I have:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"viewDidAppear did appear too");
//camera view etc
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
//code here to not allow picture taking, probably put up something saying you don'thave a camera on your device
NSLog(#"no cam available");
_noCam = [UIImage imageNamed:#"noCam.png"];
[_cameraView setImage:_noCam];
} else {
//take the shot
_cameraPicker = [[UIImagePickerController alloc] init];
_cameraPicker.delegate = _cameraView;
_cameraPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
NSLog(#"cam is available");
}
}
I'm guessing I have a problem with setting the delegate. _self gives me an error of type:
'from incompatible type 'ViewController *const _strong'
I'm using NSLogs to check the methods are working, it tells me the viewDidLoad and viewDidAppear method were called and that a camera was detected But then I just get the white view.
Any help would be hugely appreciated.
Thanks.
You need to display the picker somehow, you can either use the default GUI:
[self presentModalViewController:_cameraPicker animated:YES];
Or check out the cameraOverlayView of UIImagePickerController.
Related
I have set up my leader board in the Game Center.
How do I make it so when the user clicks the high score button, it takes them right to the specific leader board in the Game Center?
Is there a way to do it without using a specific link in a UIWebView?
I would prefer the Game Center to open outside of the app. My app is tailored for iOS7 and above.
Far far ago, under iOS7, U can't control what's happening inside the GKGameCenterViewController, just this 3 options:
typedef NS_ENUM(NSInteger, GKGameCenterViewControllerState) {
GKGameCenterViewControllerStateDefault = -1,
GKGameCenterViewControllerStateLeaderboards,
GKGameCenterViewControllerStateAchievements,
GKGameCenterViewControllerStateChallenges,
};
U can set this property:
#property (nonatomic, assign) GKGameCenterViewControllerState viewState;
Like this (an example):
- (void)presentLeaderboardsOnViewController:(UIViewController *)viewController {
GKGameCenterViewController *leaderboardViewController = [[GKGameCenterViewController alloc] init];
leaderboardViewController.viewState = GKGameCenterViewControllerStateLeaderboards;
leaderboardViewController.gameCenterDelegate = self;
[viewController presentViewController:leaderboardViewController animated:YES completion:nil];
}
From iOS7 and above u have this property (never try it):
#property (nonatomic, retain) NSString *leaderboardIdentifier __OSX_AVAILABLE_STARTING( __MAC_NA, __IPHONE_7_0); // Showing specified leaderboard
So just set this property, and there u go, u have opened the GKGameCenterViewController with your wanted Leaderboard :)
Good luck!
Edit:
To dismiss the Game Center screen, in your GKGameCenterControllerDelegate add this method:
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController {
[gameCenterViewController dismissViewControllerAnimated:YES completion:^{
}];
}
I have a larger app that should be able to share multiple images.
I implemented this using UIActivityViewController and UIActivityItemProvider to have asynchronous usage of the items (so that i only have to prepare one image at a time and not have to fill the memory with all of them at once to share them).
I was "inspired" by the Apple Airdrop example:
AirdropSample download
However when using my app to share e.g. 9 images (to camera Roll == "Save 9 images") only 4 to 7 images end up being in the camera roll, no error messages whatsoever.
If i repeat it over and over sometimes i get 5 images or 6 seemingly random.
I cannot post my app here, but i modified the above sample in a way that it will also randomly "fail" with delivering all images to the camera Roll...
If you download above sample and replace 4 files with these, it shows the problem:
APLAsyncImageViewController.h:
#import <UIKit/UIKit.h>
#import "APLAsyncImageActivityItemProvider.h"
#interface APLAsyncImageViewController : UIViewController
#end
APLAsyncImageViewController.m:
#import "APLAsyncImageViewController.h"
#import "APLProgressAlertViewController.h"
NSString * const kProgressAlertViewControllerIdentifier = #"APLProgressAlertViewController";
#interface APLAsyncImageViewController ()
#property (strong, nonatomic) UIWindow *alertWindow;
#property (strong, nonatomic) APLProgressAlertViewController *alertViewController;
#property (strong, nonatomic) UIPopoverController *activityPopover;
#property (weak, nonatomic) IBOutlet UIButton *shareImageButton;
- (IBAction)openActivitySheet:(id)sender;
#end
#implementation APLAsyncImageViewController
- (IBAction)openActivitySheet:(id)sender
{
NSMutableArray *itemArray = [[NSMutableArray alloc] init];
for( int i = 0; i < 9;i++)
{
APLAsyncImageActivityItemProvider *aiImageItemProvider = [[APLAsyncImageActivityItemProvider alloc] init];
[itemArray addObject: aiImageItemProvider];
}
//Create an activity view controller with the activity provider item. UIActivityItemProvider (AsyncImageActivityItemProvider's superclass) conforms to the UIActivityItemSource protocol
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:itemArray applicationActivities:nil];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
//iPhone, present activity view controller as is
[self presentViewController:activityViewController animated:YES completion:nil];
}
else
{
//iPad, present the view controller inside a popover
if (![self.activityPopover isPopoverVisible]) {
self.activityPopover = [[UIPopoverController alloc] initWithContentViewController:activityViewController];
[self.activityPopover presentPopoverFromRect:[self.shareImageButton frame] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else
{
//Dismiss if the button is tapped while pop over is visible
[self.activityPopover dismissPopoverAnimated:YES];
}
}
}
#end
APLAsyncImageActivityItemProvider.h:
#import <UIKit/UIKit.h>
#interface APLAsyncImageActivityItemProvider : UIActivityItemProvider
#end
APLAsyncImageActivityItemProvider.m:
#import "APLAsyncImageActivityItemProvider.h"
#import "UIImage+Resize.h"
#implementation APLAsyncImageActivityItemProvider
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
return [[UIImage alloc] init];
}
- (id)item
{
UIImage *image = [UIImage imageNamed:#"Flower.png"];
//CGSize imageSize;
//imageSize.height = 1000;
//imageSize.width = 1000;
//image = [UIImage imageWithImage:image scaledToFitToSize:imageSize];
return image;
}
- (UIImage *)activityViewController:(UIActivityViewController *)activityViewController thumbnailImageForActivityType:(NSString *)activityType suggestedSize:(CGSize)size
{
//The filtered image is the image to display on the other side.
return [[UIImage alloc] init];
}
#end
If you execute the sample like this (Use menu item "Send Image After Preprocessing", press "SHARE" Button) it will often or mostly fail to deliver all 9 images to the camera roll.
IF you uncomment the 4 lines in "APLAsyncImageActivityItemProvider.m" that basically just scale the output image THEN it will work ALWAYS.
Can you tell me why ? I feel that if i know the answer to that riddle i can also fix my app.
Thank you,
Nils
The reason for this issue is pretty simple.
There are limited number of writer threads available to use by the app, so writing too many images simulteneously may fail due to "Write Busy" error. You can verify that by trying to manually write these images using UIImageWriteToSavedPhotosAlbum (or corresponding Asset/Photos framework counterparts).
So, resizing images just hides the real problem because writing a smaller image takes less time.
The problem can be solved by liming the number of writers and/or retrying in case of error.
Also note that -[UIActivityItemProvider item] is a blocking call, but there are no synchronous ways to write to the gallery out of the box. This can be handled with dispatch_semaphore_wait , NSCondition, etc.
Or, in case you're using ReactiveCocoa, by simply calling waitUntilCompleted.
I would go to say that the [UIImage imageWithImage:image scaledToFitToSize:imageSize] image created is GC before saved to camera roll, but I don't know what is going on in that method without the code. That method is not a normal UIImage method, a category maybe?
EDIT
Replace your for loop code adding to your item array with this code, and then uncomment your resize lines, and see if that works.
NSMutableArray *itemArray = [[NSMutableArray alloc] init];
for( int i = 0; i < 9;i++)
{
UIImage *aiImage = [[[APLAsyncImageActivityItemProvider alloc] init] image];
[itemArray addObject:aiImage];
}
I'm having a slight issue here.
I have a basic view which has two UIButtons and two UIImageViews, I would like my users to be able to take two different photos, and these to be attached to their respective UIImageView.
Right now this works fine for the first UIButton/image, but not with a second.
.h
#interface ViewController : UIViewController <UIImagePickerControllerDelegate> {
// First button/imageview
UIImagePickerController *picker;
UIImage *image;
// Second button/imageview
UIImagePickerController *picker2;
UIImage *image2;
}
.m
-(IBAction)TakePhoto
{
picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
[self presentViewController:picker animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
image2 = [info objectForKey:UIImagePickerControllerOriginalImage];
[imageField2 setImage:image2];
[self dismissViewControllerAnimated:YES completion:NULL];
}
This all works great but my question is how can I hook up the second picker to a new imagePickerController method so that my user can take two different photos on this view? I know that if I created a new action with the picker2 information it will still point to the one imagePickerController method, creating a second method and renaming this to suit does not work.
Any advice & help would be greatly appreciated.
Jamie
You don't need two UIImagePickerControllers to do it.
Take a look at takePicture method of UIImagePickerController which programatically initiates still image capture.
You can initiate additional captures after receiving imagePickerController:didFinishPickingMediaWithInfo: delegate callback.
PhotoPicker is a sample project from Apple which does exactly what you are trying to do.
Hope it helps.
I'm working on a simple photo and video capture app right now. The app successfully allows the user to take a photo or video on a button press. However, as soon as you finish taking your photo or video, it gives 2 options: "Retake" and "Use Photo" or "Use Video", depending on which one you're using.
If the user taps "Retake" then it just let's them retake a new photo or video, but when the user taps "Use photo" or "Use video" the screen freezes.
If I exit the frozen app and go look in my camera roll, the photo I just took using the app has successfully been saved. So when you tap the "Use Photo" button it does successfully save to the camera roll despite the fact that the app screen freezes.
I was told by someone that "it freezes because it takes some time to save the photo and it is running on main thread. You can use the ALAssetLibrary to fix the freezing issue."
However, I am not familiar with ALAssetLibrary or the theory of why it would be helpful in this situation. I just skimmed through some of it's documentation and I am still lost.
Any help would be greatly appreciated.
Here is the code that I have so far:
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
#property UIImagePickerController * pickerController;
-(IBAction)showCameraUI;
#end
ViewController.m:
#import "ViewController.h"
#import <MobileCoreServices/MobileCoreServices.h>
#interface ViewController () <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
//The above are the 2 delegates required for creating a media capture/camera app.
- (void)imagePickerController:pickerController didFinishPickingMediaWithInfo:(NSDictionary *)info;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
[UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
NSLog(#"%ld", (long)UIImagePickerControllerSourceTypeCamera);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)showCameraUI{
UIImagePickerController * pickerController = [[UIImagePickerController alloc]init];
pickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerController.delegate = self;
[self presentViewController:pickerController animated:YES completion:nil];
}
- (void)imagePickerController:pickerController didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// saves the photo you just took
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage])
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImageWriteToSavedPhotosAlbum(image,nil,nil,nil);
}
}
- (void)imagePickerControllerDidCancel:pickerController
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
i want to use UIIMagePickerController to record video as i would normally do.
but i want to add a layer (UIView) that needs to be captured within the video overlay.
lets sat i have a star spinning on my view. when i will take the video i will see the star spinning as i am recording and when finish recording the same output will be.
i know this object has a property :
#property (nonatomic, retain) UIView *cameraOverlayView
but i think it needs to manage only the buttons that would not be captured.
what is the normal\recommended approach to manage such a thing?
Generally, you can add your custom overlay view and UIImagePickerController.view as subviews to one view.
User startVideoCapture and stopVideoCapture to do your task.
Sample codes:
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeMovie];
picker.showsCameraControls = NO;
picker.delegate = self;
self.videoPicker = picker;
[self.view addSubview:self.videoPicker.view];
Of course, if you do this, the control of flash lights should be done by yourself.