In my application i have integrated Zbar SDK scanner, while scanning usually its working fine but my case is some times didfinishpickingmediawithInfo: delegate method firing twice. Here is my code which is in a singletone class.
-(void)scanProductBarCode
{
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
reader.supportedOrientationsMask = ZBarOrientationMaskLandscape;
else
reader.supportedOrientationsMask = ZBarOrientationMaskPortrait;
ZBarImageScanner *scanner = reader.scanner;
[scanner setSymbology: ZBAR_UPCA config: ZBAR_CFG_ENABLE to: 1];
[scanner setSymbology: ZBAR_CODE39 config: ZBAR_CFG_ADD_CHECK to: 0];
}
#pragma mark - Scanner delegate methods
- (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info
{
id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
break;
barCodeString = [[NSString alloc] initWithString:symbol.data];
if(self.delegate)
[self.delegate getBarcodeString:barCodeString];
[reader dismissModalViewControllerAnimated:YES];
}
See this screen shot:
At background the scanner is still running like this in twice occuring case..
I ran into the same problem. I added a BOOL instance variable to my class named _processing. Then I did this:
- (void)imagePickerController:(UIImagePickerController*)reader didFinishPickingMediaWithInfo:(NSDictionary*)info
{
if (_processing) return;
id<NSFastEnumeration> results = [info objectForKey:ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results) {
_processing = YES;
barCodeString = symbol.data;
if(self.delegate) {
[self.delegate getBarcodeString:barCodeString];
}
break;
}
[reader dismissModalViewControllerAnimated:YES];
}
This ensures that only the first call is processed. You may need to reset _processing if you plan to reuse the view controller more than once.
Since the ZBarReaderViewController scans the image in continuous mode, it could be that the image is scanned twice before you dismiss the ZBarReaderViewController. You may try making the reader (ZBarReaderViewController *reader ) an instance variable of your class, and in the delegate method:
- (void)imagePickerController:(UIImagePickerController*)reader didFinishPickingMediaWithInfo:(NSDictionary*)info
{
// Stop further scanning
[reader.readerView stop];
...
//Continue with processing barcode data.
}
Related
Hi I'm new to iOS development. I want to pick a contact from default contacts app. For that i created an application that lets user to pick a contact from the iPhone default contacts app. For iOS 9+ version, I'm using the following snipped.
- (IBAction)btnAction:(id)sender {
CNContactPickerViewController *contactPicker = [[CNContactPickerViewController alloc] init];
contactPicker.delegate = self;
contactPicker.displayedPropertyKeys = (NSArray *)CNContactGivenNameKey;
[self presentViewController:picker animated:YES completion:nil];
}
-(void) contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact{
NSLog(#"Contact : %#",contact);
}
-(void)contactPickerDidCancel:(CNContactPickerViewController *)picker {
NSLog(#"Cancelled");
}
I also added CNContactPickerDelegate delegate in my uiviewcontroller. When i execute the above code, it opens the contacts app, But when Tap a contact the app becomes blank.
Thanks in advance and can anyone please share your knowledge to use CNContactPickerViewController in Objective-C.
The issue is caused by this code:
contactPicker.displayedPropertyKeys = (NSArray *)CNContactGivenNameKey;
The displayedPropertyKeys expects an NSArray which contains NSString values. In your code, you are trying to type cast an NSString to NSArray and set as the value of this property.
You need to change your code to:
contactPicker.displayedPropertyKeys = #[CNContactGivenNameKey];
#pragma mark - CNContactPickerViewController Delegate method implementation
(void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact
{
NSMutableArray *contactNumberArray = [[NSMutableArray alloc]init];
selectedName=[NSString stringWithFormat:#"%#",contact.givenName];
NSLog(#"%#",selectedName);
NSString *tempString = [NSString stringWithFormat:#"name : %# %# %#\n",contact.givenName, contact.familyName, contact.organizationName];
// // 1. (Phone Numbers)
tempString = [NSString stringWithFormat:#"%#phoneNumbers : ",tempString];
// NSArray*phoneNumber = contact.phoneNumbers;
for (CNLabeledValue *phoneNumber in contact.phoneNumbers)
{
CNPhoneNumber *phone = phoneNumber.value;
tempString = [NSString stringWithFormat:#"%#<%#>",tempString,phone.stringValue];
[contactNumberArray addObject:phone];
selectedPhNumber=[[NSString stringWithFormat:#"%#",phone.stringValue] stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"%#",selectedPhNumber);
}
//2. (Emails)
tempString = [NSString stringWithFormat:#"%#\n Email : ",tempString];
for (CNLabeledValue *email in contact.emailAddresses)
{
selectedEmail=[NSString stringWithFormat:#"%#", email.value];
tempString = [NSString stringWithFormat:#"%#<%#>",tempString,email.value];
[contactNumberArray addObject:email];
NSLog(#"%#",selectedEmail);
}
[self sendRefferelDetailsToServer];
}
-(void)contactPicker:(CNContactPickerViewController *)picker didSelectContacts:(NSArray<CNContact *> *)contacts{
NSLog(#" %#",contacts);
CNContact *contact=[contacts objectAtIndex:0];
NSLog(#"name = %#",contact.givenName);
}
[1]: https://i.stack.imgur.com/9Sp1G.png use above code to for fetch given name from multiple selections,
comment the following line and try again.
//contactPicker.displayedPropertyKeys = (NSArray *)CNContactGivenNameKey;
I'm using Phonegap's implementation to use the video capture and can't seem to get startVideoCapture to work. I'm a novice when it comes to Objective C, so I apologize if I'm off base here. Sounds like startVideoCapture is mainly for custom UI's. Is there something I can do to auto start the video recording (since I'm starting the video interface from another action). Here's a link to the full file:
https://github.com/apache/cordova-plugin-media-capture/blob/master/src/ios/CDVCapture.m
Thanks,
Steve
- (void)captureVideo:(CDVInvokedUrlCommand*)command
{
NSString* callbackId = command.callbackId;
NSDictionary* options = [command.arguments objectAtIndex:0];
NSLog(#"hereeeee");
if ([options isKindOfClass:[NSNull class]]) {
options = [NSDictionary dictionary];
}
// options could contain limit, duration and mode
// taking more than one video (limit) is only supported if provide own controls via cameraOverlayView property
NSNumber* duration = [options objectForKey:#"duration"];
NSString* mediaType = nil;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
// there is a camera, it is available, make sure it can do movies
pickerController = [[CDVImagePicker alloc] init];
NSArray* types = nil;
if ([UIImagePickerController respondsToSelector:#selector(availableMediaTypesForSourceType:)]) {
types = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
// NSLog(#"MediaTypes: %#", [types description]);
if ([types containsObject:(NSString*)kUTTypeMovie]) {
mediaType = (NSString*)kUTTypeMovie;
} else if ([types containsObject:(NSString*)kUTTypeVideo]) {
mediaType = (NSString*)kUTTypeVideo;
}
}
}
if (!mediaType) {
// don't have video camera return error
NSLog(#"Capture.captureVideo: video mode not available.");
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:CAPTURE_NOT_SUPPORTED];
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
pickerController = nil;
} else {
pickerController.delegate = self;
pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
pickerController.allowsEditing = NO;
// iOS 3.0
pickerController.mediaTypes = [NSArray arrayWithObjects:mediaType, nil];
if ([mediaType isEqualToString:(NSString*)kUTTypeMovie]) {
if (duration) {
pickerController.videoMaximumDuration = [duration doubleValue];
}
// NSLog(#"pickerController.videoMaximumDuration = %f", pickerController.videoMaximumDuration);
}
// iOS 4.0
if ([pickerController respondsToSelector:#selector(cameraCaptureMode)]) {
pickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
// pickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
// pickerController.cameraDevice = UIImagePickerControllerCameraDeviceRear;
// pickerController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
}
// CDVImagePicker specific property
pickerController.callbackId = callbackId;
SEL selector = NSSelectorFromString(#"presentViewController:animated:completion:");
if ([self.viewController respondsToSelector:selector]) {
[self.viewController presentViewController:pickerController animated:YES completion:nil];
} else {
// deprecated as of iOS >= 6.0
[self.viewController presentModalViewController:pickerController animated:YES];
}
// Auto start capture
[pickerController startVideoCapture];
}
}
My problem wasn't the use of startVideoRecording, it was when:
[self.viewController presentViewController:pickerController animated:YES completion:^(){
[pickerController startVideoCapture];
}];
Hope this helps someone else.
Thanks,
Steve
Can someone please help me what could the stated error be for?
[NSNull dataUsingEncoding:]: unrecognized selector sent to instance
I am stuck at printer plugin for an iOS application.
I have been struggling to get this app work for sometime now....the watched code may help find the error...
import "APPPrinter.h"
#interface APPPrinter (Private)
- (UIPrintInteractionController*) getPrintController;
- (UIPrintInteractionController*) adjustSettingsForPrintController:(UIPrintInteractionController*)controller;
- (void) loadContent:(NSString*)content intoPrintController:(UIPrintInteractionController*)controller;
- (void) informAboutResult:(int)code callbackId:(NSString*)callbackId;
- (BOOL) isPrintServiceAvailable;
#end
#implementation APPPrinter
// Is printing available.
- (void) isServiceAvailable:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult;
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:[self isPrintServiceAvailable]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
- (void) print:(CDVInvokedUrlCommand*)command
{
if (![self isPrintServiceAvailable])
{
return;
}
NSArray* arguments = [command arguments];
NSString* content = [arguments objectAtIndex:0];
UIPrintInteractionController* controller = [self getPrintController];
[self adjustSettingsForPrintController:controller];
[self loadContent:content intoPrintController:controller];
[self openPrintController:controller];
[self commandDelegate];
}
- (UIPrintInteractionController*) getPrintController
{
return [UIPrintInteractionController sharedPrintController];
}
- (UIPrintInteractionController*) adjustSettingsForPrintController:(UIPrintInteractionController*)controller
{
UIPrintInfo* printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
controller.printInfo = printInfo;
controller.showsPageRange = YES;
return controller;
}
- (void) loadContent:(NSString*)content intoPrintController:(UIPrintInteractionController*)controller
{
// Set the base URL to be the www directory.
NSURL *basEURL = [[NSBundle mainBundle] URLForResource:#"Login" withExtension:#"html"];
// Load page into a webview and use its formatter to print the page
UIWebView* webPage = [[UIWebView alloc] init];
[webPage loadHTMLString:content baseURL:basEURL];
UIViewPrintFormatter* formatter = [webPage viewPrintFormatter];
controller.printFormatter = formatter;
controller.showsPageRange = YES;
}
- (void) openPrintController:(UIPrintInteractionController*)controller
{
[self.commandDelegate runInBackground:^
{
[controller presentAnimated:YES completionHandler:NULL];
}];
[self performSelectorOnMainThread:#selector(openPrintController:) withObject:nil waitUntilDone:NO];
}
- (BOOL) isPrintServiceAvailable
{
Class printController = NSClassFromString(#"UIPrintInteractionController");
if (printController)
{
UIPrintInteractionController* controller = [UIPrintInteractionController sharedPrintController];
return (controller != nil) && [UIPrintInteractionController isPrintingAvailable];
}
return NO;
}
#end
Any help/links on creating and getting Print Plugin to run in my app will also be great.
It means that a message "dataUsingEncoding:" was sent to an instance of NSNull.
Somewhere in your program is an object where you apparently think it is an NSString*, but in reality it is an NSNull*. NSNull objects are used as placeholders in arrays and dictionaries to say "there is no value", because you can't store nil in arrays and dictionaries.
In Xcode, click on "Breakpoints", click on the "+", and add an "Exception breakpoint". Run your program again. This time it will stop in the debugger exactly on the code that tries to call dataUsingEncoding: Find out where the object comes from and fix it.
I am using tab bar in my iOS app. When I tap on the scan tab, i invoked the delegate method to start the camera immediately on scan tab. When I start the camera to scan the QR Code and tap on cancel button before scanning, I get the blank view. How to display the view when camera is dismissed
- (void) openCameraScanner
{
ZBarReaderViewController *reader = [[ZBarReaderViewController alloc] init];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;
reader.showsZBarControls = YES;
ZBarImageScanner *scanner = reader.scanner;
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];
[self presentViewController:reader animated:YES completion:nil];
reader.showsZBarControls = YES;
//reader.cameraOverlayView = [self commonOverlay];
}
- (void) imagePickerController: (UIImagePickerController*) reader
didFinishPickingMediaWithInfo: (NSDictionary*) info
{
// ADD: get the decode results
id<NSFastEnumeration> results =
[info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// EXAMPLE: just grab the first barcode
break;
// EXAMPLE: do something useful with the barcode data
//resultsView.text = symbol.data;
NSString *urlString = symbol.data;
NSURL *url = [NSURL URLWithString:urlString];
NSLog(#"Query after scan = %#", [url query]);
//Extract id from URL which is there in QR Code --- start
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
for(NSString *param in [urlString componentsSeparatedByString:#"&"])
{
NSArray *elements = [param componentsSeparatedByString:#"="];
if([elements count]<2)
continue;
[dictionary setObject:[elements objectAtIndex:1] forKey:[elements objectAtIndex:0]];
NSLog(#"value is == %#", [elements objectAtIndex:1]);
//Extract id from URL which is there in QR Code --- end
if([[elements objectAtIndex:1] intValue])
{
NSUserDefaults *defaultsForAsk = [NSUserDefaults standardUserDefaults];
idToAsk = [NSString stringWithFormat:#"%d",[[elements objectAtIndex:1] intValue]];
[defaultsForAsk setObject:idToAsk forKey:#"IDTOASKVIEW"];
flagToShowView = YES;
listViewCntrl.getFlag = flagToShowView;
[self viewDidLoadForDynamicFields];
}
else if([elements objectAtIndex:1] == [NSNull null])
{
[reader dismissViewControllerAnimated:YES completion:Nil];
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Invalid QR Code scanned" message:#"Please scan Collaborator's QR Code" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[message show];
}
}
image.image =
[info objectForKey: UIImagePickerControllerOriginalImage];
// ADD: dismiss the controller (NB dismiss from the *reader*!)
//[reader dismissViewControllerAnimated:YES completion:nil];
[reader dismissViewControllerAnimated:YES completion:Nil];
}
You can re display the view using -(void)viewWillAppear:(BOOL)animated method of your ViewController class.
I am doing one iOS app in which I have to scan the barcodes . I have used ZBarReaderViewController for scanning the barcodes . Sometimes it is giving the result accurately but sometimes it is giving unknown value like this &7&#,Ac9 .My Image is My code is
-(IBAction)scanBarCode:(id)sender
{
reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;
reader.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height * [UIScreen mainScreen].scale >= 1136)
[reader.readerView setScanCrop:(CGRect){ { 0.25, 0.08 }, { 0.07, 0.84} }];//.25
else
[reader.readerView setScanCrop:(CGRect){ { 0.23, 0.08 }, { 0.09, 0.84} }];
ZBarImageScanner *scanner = reader.scanner;
// TODO: (optional) additional reader configuration here
// EXAMPLE: disable rarely used I2/5 to improve performance
/*[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];*/
//swetha test
[scanner setSymbology: 0
config: ZBAR_CFG_ENABLE
to: 0];
// Enable EAN 13
[scanner setSymbology: ZBAR_EAN13
config: ZBAR_CFG_ENABLE
to: 1];
// Enable UPC-A
[scanner setSymbology: ZBAR_UPCA
config: ZBAR_CFG_ENABLE
to: 1];
// Enable Code 128
[scanner setSymbology: ZBAR_CODE128
config: ZBAR_CFG_ENABLE
to: 1];
[self presentViewController:reader animated:YES completion:nil];
[reader release];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
id<NSFastEnumeration> results =
[info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// EXAMPLE: just grab the first barcode
break;
// EXAMPLE: do something useful with the barcode data
serialnumber.text = symbol.data;
// EXAMPLE: do something useful with the barcode image
//resultImage.image =
//[info objectForKey: UIImagePickerControllerOriginalImage];
// ADD: dismiss the controller (NB dismiss from the *reader*!)
barcodeClicked = 0;
[picker dismissViewControllerAnimated:YES completion:nil];
}
Please let me know if I am not clear . Thanks in advance .
My imagepickerControll function is as follows:
- (void) imagePickerController: (UIImagePickerController*)reader didFinishPickingMediaWithInfo: (NSDictionary*) info {
#try {
id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
for(id obj in results) {
ZBarSymbol *symbol = obj;
serialnumber.text = [symbol data];
}
}
#catch (NSException *ex) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"%#",ex]
delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
barcodeClicked = 0;
[reader dismissViewControllerAnimated:YES completion:nil];
}
I would strongly recommend using try-catch and going through all the results, since it may interpret 2 different barcodes if they are close by, and parsing the object as ZBarSymbol.