I try to create an application that records video and takes images at receiving a message via sockets.
What I do not arrive to do is video recording using AVFoundation.
is that because of the fact that I use a single session ?
Here is my code :
#import "ViewController.h"
#import "Parser.h"
#import "DeviceConfig.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// z-index
_vImage.layer.zPosition = 1;
_toggle.layer.zPosition = 1;
recording = NO;
[self initNetworkCommunication];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"192.168.0.103", 8080, &readStream, &writeStream);
input = (__bridge NSInputStream*) readStream;
output = (__bridge NSOutputStream*) writeStream;
[input setDelegate: self];
[output setDelegate: self];
[input scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[output scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[input open];
[output open];
}
- (void) sendMessage : (NSString*) message {
NSString *response = [NSString stringWithFormat:#"iam:%#", message];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[output write:[data bytes] maxLength:[data length]];
}
- (void) stream : (NSStream*) theStream handleEvent:(NSStreamEvent) streamEvent {
switch(streamEvent) {
case NSStreamEventOpenCompleted:
[self openCamera];
break;
case NSStreamEventHasBytesAvailable:
NSLog(#"kayn");
if(theStream == input) {
uint8_t buffer[1024];
int length;
while([input hasBytesAvailable]) {
length = [input read:buffer maxLength:sizeof(buffer)];
if(length > 0) {
NSString* outputString = [[NSString alloc] initWithBytes:buffer length:length encoding:NSASCIIStringEncoding];
// To split different messages sended in buffer via Socket (in one message)
NSArray *options = [[outputString substringToIndex:[outputString length] - 1] componentsSeparatedByString:#":"];
NSLog(#"%#", options);
if(outputString != nil) {
if([options[1] isEqualToString:#"TAKE_PIC"]) {
[self takePic];
}else if([options[1] isEqualToString:#"PARAMS"]) {
Parser* parser = [[Parser alloc] initWithXMLData: options[2]];
[self changeCameraConfig:[parser getCameraOptions]];
}else if([options[1] isEqualToString:#"REC_VIDEO"]) {
[self recordVideo];
}else{
[self showMessage:#"Unknow order, please contact the administrator."];
}
}
}
}
}
break;
default:
NSLog(#"Unknown event");
}
}
- (void) showMessage : (NSString*) msg {
UIAlertView *helloWorldAlert = [[UIAlertView alloc]
initWithTitle:#"My First App" message:msg delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display the Hello World Message
[helloWorldAlert show];
}
- (void) openCamera {
session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureVideoPreviewLayer* previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.frame = self.liveCameraView.bounds;
[self.liveCameraView.layer addSublayer:previewLayer];
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
[session addInput:deviceInput];
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[_stillImageOutput setOutputSettings:outputSettings];
_videoOutput = [[AVCaptureMovieFileOutput alloc] init];
[session addOutput:_videoOutput];
[session addOutput:_stillImageOutput];
[session startRunning];
}
-(void) changeCameraConfig:(NSMutableDictionary *)config {
[device lockForConfiguration:nil];
DeviceConfig* conf;
for(id key in config) {
conf = [config objectForKey:key];
//[self showMessage:#"ok"];
// Config Torch
if([key isEqualToString:#"torch"]) {
if([[conf curValue] isEqualToString: #"on"]) {
[device setTorchMode:AVCaptureTorchModeOn];
}else{
[device setTorchMode:AVCaptureTorchModeOff];
}
}
// Config Focus
if([key isEqualToString:#"focus_mode"]) {
if([[conf curValue] isEqualToString: #"auto"]) {
[device setFocusMode: AVCaptureFocusModeAutoFocus];
}else if([[conf curValue] isEqualToString: #"continous_auto"]) {
[device setFocusMode: AVCaptureFocusModeContinuousAutoFocus];
}else{
[device setFocusMode: AVCaptureFocusModeLocked];
}
}
// Config Flash
if([key isEqualToString:#"flash"]) {
if([[conf curValue] isEqualToString: #"on"]) {
[device setFlashMode: AVCaptureFlashModeOn];
}else{
[device setFlashMode:AVCaptureFlashModeOff];
}
}
// Config Exposure
if([key isEqualToString:#"white_balance"]) {
if([[conf curValue] isEqualToString: #"auto"]) {
[device setExposureMode: AVCaptureExposureModeAutoExpose];
}else if([[conf curValue] isEqualToString: #"continous_auto"]) {
[device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}else if([[conf curValue] isEqualToString: #"custom"]) {
[device setExposureMode:AVCaptureExposureModeCustom];
}else{
[device setExposureMode:AVCaptureExposureModeLocked];
}
}
// Config White balance
if([key isEqualToString:#"exposure_mode"]) {
if([[conf curValue] isEqualToString: #"auto"]) {
[device setExposureMode: AVCaptureExposureModeAutoExpose];
}else if([[conf curValue] isEqualToString: #"continous_auto"]) {
[device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}else if([[conf curValue] isEqualToString: #"custom"]) {
[device setExposureMode:AVCaptureExposureModeCustom];
}else{
[device setExposureMode:AVCaptureExposureModeLocked];
}
}
}
[device unlockForConfiguration];
}
-(void) takePic {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in _stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
videoConnection = connection;
break;
}
}
if (videoConnection) { break; }
}
NSLog(#"about to request a capture from: %#", _stillImageOutput);
[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{
CFDictionaryRef exifAttachments = CMGetAttachment( imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments)
{
// Do something with the attachments.
NSLog(#"attachements: %#", exifAttachments);
}
else
NSLog(#"no attachments");
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
self.vImage.image = image;
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}];
}
- (AVCaptureDevice *) CameraWithPosition:(AVCaptureDevicePosition) Position
{
NSArray *Devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *Device in Devices)
{
if ([Device position] == Position)
{
return Device;
}
}
return nil;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (IBAction)toggleCam:(id)sender {
AVCaptureDeviceInput* newDeviceInput;
NSError* error;
AVCaptureDevicePosition position = [[deviceInput device] position];
if(position == AVCaptureDevicePositionBack) {
newDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self CameraWithPosition:AVCaptureDevicePositionBack] error:&error];
}else{
newDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self CameraWithPosition:AVCaptureDevicePositionFront] error:&error];
}
if(error != nil) {
[session beginConfiguration]; //We can now change the inputs and output configuration. Use commitConfiguration to end
[session removeInput:deviceInput];
if ([session canAddInput:newDeviceInput])
{
[session addInput:newDeviceInput];
deviceInput = newDeviceInput;
}
else
{
[session addInput:deviceInput];
}
//Set the connection properties again
//[self CameraSetOutputProperties];
[session commitConfiguration];
}
}
-(void) recordVideo {
[self showMessage:#"recording .."];
// If we are not recording
if(!recording) {
recording = YES;
NSString* path = [[NSString alloc] initWithFormat:#"%#%#", NSTemporaryDirectory(), #"output_video.wav"];
NSURL* url = [[NSURL alloc] initFileURLWithPath:path];
NSFileManager* fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:path]) {
NSError* errorMsg;
if ([fileManager removeItemAtPath:path error:&errorMsg] == NO)
{
//Error - handle if requried
}
}
[_videoOutput startRecordingToOutputFileURL:url recordingDelegate:self];
}else{
recording = NO;
[_videoOutput stopRecording];
}
}
-(void) captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error {
BOOL recordedSuccessfully = YES;
if ([error code] != noErr) {
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value) {
recordedSuccessfully = [value boolValue];
}
}
if(recordedSuccessfully) {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if([ALAssetsLibrary authorizationStatus]) {
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
}
}];
}
}else{
[self showMessage:#"Error"];
}
}
}
#end
Related
I wrote an iOS app in Objective-C. Xcode version is 8. It works fine on all devices and iOS versions but when I tried to test this in the iOS device running iOS 11. The “Profile Page” stopped working in the sense that once we navigate to that screen, it becomes touch unresponsive and nothing happens. This page works well with all iOS versions and all device except for those running iOS 11.
Code for Profile page is:
#import "ProfileViewController.h"
#interface ProfileViewController ()
#end
#implementation ProfileViewController
- (void)viewDidLoad
{
[super viewDidLoad];
currentUser = [SingletonClass sharedSingletonClass].settingsDictionary[#"User"];
selectedValues=[NSMutableDictionary dictionary];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
NSMutableDictionary *paramDict=[NSMutableDictionary dictionary];
[paramDict setObject:#"ios" forKey:#"request"];
[paramDict setObject:[NSString stringWithFormat:#"%#",currentUser.user_id] forKey:#"user_id"];
[GeneralWebservices webserviceMainSplashCall:paramDict webserviceName:Webservice_Profile OnCompletion:^(id returnDict, NSError *error) {
if ([returnDict[#"success"] intValue] ==1)
{
[self setProfileData:returnDict[#"data"]];
provinceList=[NSMutableArray arrayWithArray:returnDict[#"provincedata"]];
questions1Array=[NSMutableArray arrayWithArray:returnDict[#"questiondata"]];
}
else
{
[self get_register_data];
[alert show];
}
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}];
}
-(void)setProfileData:(NSMutableDictionary*)dataDict
{
profilePicImageView.imageURL=[NSURL URLWithString:dataDict[#"image_file_thumb"]];
[firstNameLabel setText:dataDict[#"first_name"]];
[lastNameLabel setText:dataDict[#"last_name"]];
[dateOfBirthLabel setText:dataDict[#"user_dob"]];
[postalAddressTextfield setText:dataDict[#"user_address"]];
[mobileTextfield setText:dataDict[#"user_mobile"]];
[question1Textfield setText:dataDict[#"user_answer_1"]];
[question2Textfield setText:dataDict[#"user_answer_2"]];
[LLGButton setTitle:dataDict[#"user_llg"] forState:UIControlStateNormal];
[provinceButton setTitle:dataDict[#"user_province"] forState:UIControlStateNormal];
[districtButton setTitle:dataDict[#"user_district"] forState:UIControlStateNormal];
[villageTextfield setText:dataDict[#"user_village"]];
[question1Button setTitle:dataDict[#"user_question_1"] forState:UIControlStateNormal];
[question2Button setTitle:dataDict[#"user_question_2"] forState:UIControlStateNormal];
[self callforDistrict:#"get_district.php" idForItem:dataDict[#"district_id"]];
[self callforLLG:#"get_llg.php" idForItem:dataDict[#"llg_id"]];
[selectedValues setObject:dataDict[#"user_question_1_id"] forKey:#"user_question_1"];
[selectedValues setObject:dataDict[#"user_question_2_id"] forKey:#"user_question_2"];
[selectedValues setObject:dataDict[#"province_id"] forKey:#"user_province"];
[selectedValues setObject:dataDict[#"district_id"] forKey:#"user_district"];
[selectedValues setObject:dataDict[#"llg_id"] forKey:#"user_llg"];
}
-(void)callforDistrict:(NSString*)serviceName idForItem:(NSString*)idForItem
{
dispatch_async(dispatch_get_main_queue(), ^{
[self getdistdata:idForItem];
});
districList=[NSMutableArray arrayWithArray:returnDict[#"data"]];
{
}
-(void)callforLLG:(NSString*)serviceName idForItem:(NSString*)idForItem
{
dispatch_async(dispatch_get_main_queue(), ^{
[self getIIL:idForItem];
});
}
- (void)viewDidLayoutSubviews
{
[profileScrollView setContentSize:CGSizeMake(self.view.frame.size.width, 700)];
}
- (IBAction)uploadPictureButtonTap:(UIButton *)sender
{
UIActionSheet *popup = [[UIActionSheet alloc] initWithTitle:#"Select option" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:
#"Open Gallery",
#"Take Photo",
nil];
popup.tag = 1;
[popup showInView:[UIApplication sharedApplication].keyWindow];
}
- (IBAction)provinceButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
NSMutableArray *provinceNames=[NSMutableArray array];
for (NSMutableDictionary*pro in provinceList)
{
[provinceNames addObject:pro[#"province_name"]];
}
LGActionSheet *sheet=[[LGActionSheet alloc] initWithTitle:#"Select Province" buttonTitles:provinceNames cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil];
sheet.tagOfSheet=2;
sheet.heightMax=300;
sheet.delegate=self;
[sheet showAnimated:YES completionHandler:nil];
}
- (IBAction)districtButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
NSMutableArray *names=[NSMutableArray array];
for (NSMutableDictionary*pro in districList)
{
[names addObject:pro[#"district_name"]];
}
LGActionSheet *sheet=[[LGActionSheet alloc] initWithTitle:#"Select District" buttonTitles:names cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil];
sheet.heightMax=200;
sheet.tagOfSheet=3;
sheet.delegate=self;
[sheet showAnimated:YES completionHandler:nil];
}
- (IBAction)LLGButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
NSMutableArray *names=[NSMutableArray array];
for (NSMutableDictionary*pro in llgList)
{
[names addObject:pro[#"llg_name"]];
}
LGActionSheet *sheet=[[LGActionSheet alloc] initWithTitle:#"Select LLG" buttonTitles:names cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil];
sheet.heightMax=200;
sheet.tagOfSheet=4;
sheet.delegate=self;
[sheet showAnimated:YES completionHandler:nil];
}
- (IBAction)villageButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
}
- (IBAction)question1ButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
NSMutableArray *ques1=[NSMutableArray array];
for (NSMutableDictionary*pro in questions1Array)
{
[ques1 addObject:pro[#"question_name"]];
}
LGActionSheet *sheet=[[LGActionSheet alloc] initWithTitle:#"Select Question 1" buttonTitles:ques1 cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil];
sheet.tagOfSheet=5;
sheet.heightMax=300;
sheet.delegate=self;
[sheet showAnimated:YES completionHandler:nil];
}
- (IBAction)question2ButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
NSMutableArray *ques2=[NSMutableArray array];
for (NSMutableDictionary*pro in questions1Array)
{
[ques2 addObject:pro[#"question_name"]];
}
LGActionSheet *sheet=[[LGActionSheet alloc] initWithTitle:#"Select Question 2" buttonTitles:ques2 cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil];
sheet.tagOfSheet=6;
sheet.heightMax=300;
sheet.delegate=self;
[sheet showAnimated:YES completionHandler:nil];
}
- (IBAction)updateButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[selectedValues setObject:#"ios" forKey:#"request"];
[selectedValues setObject:[NSString stringWithFormat:#"%#",currentUser.user_id] forKey:#"user_id"];
[selectedValues setObject:postalAddressTextfield.text forKey:#"address"];
[selectedValues setObject:mobileTextfield.text forKey:#"user_mobile"];
[selectedValues setObject:question1Textfield.text forKey:#"user_answer_1"];
[selectedValues setObject:villageTextfield.text forKey:#"user_village"];
[GeneralWebservices webserviceCallWithData:selectedValues webserviceName:Webservice_ProfileUpdate dataToPost:imageData imageName:imageName OnCompletion:^(id returnDict, NSError *error) {
if ([returnDict[#"success"] intValue] == 1)
{
UIAlertView* alert = [[UIAlertView alloc] init];
[alert setTitle:#"Updated Successfully"];
[alert addButtonWithTitle:#"OK"];
[alert show];
}
else
{
UIAlertView* alert = [[UIAlertView alloc] init];
[alert setTitle:#"Updated Successfully"];
[alert addButtonWithTitle:#"OK"];
[alert show];
}
[MBProgressHUD hideAllHUDsForView:self.view animated:NO];
}];
}
- (IBAction)saveButtonTap:(UIButton *)sender
{
[self.view endEditing:YES];
}
- (void)actionSheet:(LGActionSheet *)actionSheet buttonPressedWithTitle:(NSString *)title index:(NSUInteger)index
{
dispatch_async(dispatch_get_main_queue(), ^{
if (actionSheet.tagOfSheet==2)
{
[selectedValues setObject:provinceList[index][#"province_id"] forKey:#"user_province"];
[provinceButton setTitle:provinceList[index][#"province_name"] forState:UIControlStateNormal];
[districList removeAllObjects];
[llgList removeAllObjects];
[districtButton setTitle:#"District *" forState:UIControlStateNormal];
[LLGButton setTitle:#"LLG *" forState:UIControlStateNormal];
[selectedValues removeObjectForKey:#"district"];
[selectedValues removeObjectForKey:#"llg"];
[self callforDistrict:#"get_district.php" idForItem:provinceList[index][#"province_id"]];
}
else if(actionSheet.tagOfSheet==3)
{
[selectedValues setObject:districList[index][#"id"] forKey:#"user_district"];
[districtButton setTitle:districList[index][#"district_name"] forState:UIControlStateNormal];
[llgList removeAllObjects];
[LLGButton setTitle:#"LLG *" forState:UIControlStateNormal];
[selectedValues removeObjectForKey:#"llg"];
[self callforLLG:#"get_llg.php" idForItem:districList[index][#"id"]];
}
else if(actionSheet.tagOfSheet==4)
{
[selectedValues setObject:llgList[index][#"id"] forKey:#"user_llg"];
[LLGButton setTitle:llgList[index][#"llg_name"] forState:UIControlStateNormal];
}
else if(actionSheet.tagOfSheet==5)
{
[selectedValues setObject:questions1Array[index][#"question_id"] forKey:#"user_question_1"];
[question1Button setTitle:questions1Array[index][#"question_name"] forState:UIControlStateNormal];
}
else if(actionSheet.tagOfSheet==6)
{
[selectedValues setObject:questions1Array[index][#"question_id"] forKey:#"user_question_2"];
[question2Button setTitle:questions1Array[index][#"question_name"] forState:UIControlStateNormal];
}
});
}
-(IBAction) returnTextField:(id)sender
{
CGRect frame = self.view.frame;
frame.origin.y = 0;
[UIView animateWithDuration:0.3 animations:^{
self.view.frame = frame;
}];
[self.view endEditing:YES];
}
- (BOOL)textFieldShouldEndEditing:(UITextField*)textField
{
return YES;
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
[self animateTextField:textField up:NO];
[textField resignFirstResponder];
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField:textField up:YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField:textField up:NO];
}
- (void)actionSheet:(UIActionSheet *)popup clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (popup.tag) {
case 1: {
switch (buttonIndex) {
case 0:
[self openPhotoLibraryButton:self];
break;
case 1:
[self openCameraButton:self];
break;
default:
break;
}
break;
}
default:
break;
}
}
- (IBAction)openCameraButton:(id)sender
{
[self.view endEditing:YES];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
[picker setSourceType:UIImagePickerControllerSourceTypeCamera];
picker.allowsEditing = false;
[self presentViewController:picker animated:true completion:nil];
}
else{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Alert!" message:#"Camera is not connected" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
- (IBAction)openPhotoLibraryButton:(id)sender
{
[self.view endEditing:YES];
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
[picker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
picker.allowsEditing = true;
[self presentViewController:picker animated:true completion:nil];
}
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
imageData=[[NSData alloc]init];
if ([info[#"UIImagePickerControllerMediaType"] isEqualToString:#"public.image"])
{
UIImage *image = [info objectForKey:#"UIImagePickerControllerEditedImage"];
if (!image)
{
image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
NSURL *imagePath = [info objectForKey:#"UIImagePickerControllerReferenceURL"];
image=[SettingsClass rotateImageAppropriately:image];
NSString *imageNamewithformat = [imagePath lastPathComponent];
imageName=#"assets.jpg";
NSString *Imageformat = [imageNamewithformat substringFromIndex: [imageNamewithformat length] - 3];
if ([Imageformat isEqualToString:#"JPG"]||[Imageformat isEqualToString:#"jpg"]) {
imageData=UIImageJPEGRepresentation(image, 0.33f);
imageName=#"assets.jpg";
}
else if ([Imageformat isEqualToString:#"PNG"]||[Imageformat isEqualToString:#"png"])
{
imageData=UIImagePNGRepresentation(image);
imageName=#"assets.png";
}
else
{
imageData=UIImageJPEGRepresentation(image, 0.33f);
imageName=#"assets.jpg";
}
[profilePicImageView setImage:image];
}
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
CGPoint temp = [textField.superview convertPoint:textField.frame.origin toView:nil];
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait){
if(up) {
int moveUpValue = temp.y+textField.frame.size.height;
animatedDis = 264-(self.view.frame.size.height-moveUpValue-35);
}
}
else if(orientation == UIInterfaceOrientationPortraitUpsideDown) {
if(up) {
int moveUpValue = self.view.frame.size.height-temp.y+textField.frame.size.height;
animatedDis = 264-(self.view.frame.size.height-moveUpValue-35);
}
}
else if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
if(up) {
int moveUpValue = temp.y+textField.frame.size.height;
animatedDis = 352-(self.view.frame.size.height-moveUpValue-100);
}
}
else
{
if(up) {
int moveUpValue = temp.y+textField.frame.size.height;
animatedDis = 352-(768-moveUpValue-100);
}
}
if(animatedDis>0)
{
const int movementDistance = animatedDis;
const float movementDuration = 0.3f;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: nil context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
if (orientation == UIInterfaceOrientationPortrait){
self.view.frame = CGRectOffset( self.view.frame, 0, movement);
}
else if(orientation == UIInterfaceOrientationPortraitUpsideDown) {
self.view.frame = CGRectOffset( self.view.frame, 0, movement);
}
else if(orientation == UIInterfaceOrientationLandscapeLeft) {
self.view.frame = CGRectOffset( self.view.frame, 0, movement);
}
else {
self.view.frame = CGRectOffset( self.view.frame, 0, movement);
}
[UIView commitAnimations];
}
}
- (IBAction)backtohomeview :(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)getdistdata:(NSString*)idForItem
{
self.view.userInteractionEnabled = NO;
NSString *strURL;
strURL = [NSString stringWithFormat:#"http://bullionscope.com/Gold_Phase3/webservices/get_district.php?request=ios&province_id=%#",idForItem];
NSDictionary *headers = #{ #"cache-control": #"no-cache",
#"postman-token": #"900e1577-4876-cd9a-d24c-cb0631b4a1fb" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:#"POST"];
[request setAllHTTPHeaderFields:headers];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
}
else
{
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSString *success = [[jsonDic objectForKey:#"success"]stringValue];
if (
[success isEqualToString:
#"1"])
{
districList=[NSMutableArray arrayWithArray:[jsonDic objectForKey:#"data"]];
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
});
}
}
}];
[dataTask resume];
}
-(void)getIIL:(NSString*)idForItem
{
self.view.userInteractionEnabled = NO;
NSString *strURL;
strURL = [NSString stringWithFormat:#"http://bullionscope.com/Gold_Phase3/webservices/get_llg.php?request=ios&district_id=%#",idForItem];
NSDictionary *headers = #{ #"cache-control": #"no-cache",
#"postman-token": #"900e1577-4876-cd9a-d24c-cb0631b4a1fb" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:#"POST"];
[request setAllHTTPHeaderFields:headers];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
}
else
{
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSString *success = [[jsonDic objectForKey:#"success"]stringValue];
if (
[success isEqualToString:
#"1"])
{
llgList=[NSMutableArray arrayWithArray:[jsonDic objectForKey:#"data"]];
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
});
}
}
}];
[dataTask resume];
}
-(void)get_register_data
{
self.view.userInteractionEnabled = NO;
NSString *strURL;
http://bullionscope.com/Gold_Phase3/webservices/get_all_province.php?request=ios
strURL = [NSString stringWithFormat:#"http://bullionscope.com/Gold_Phase3/webservices/get_all_province.php?request=ios"];
NSDictionary *headers = #{ #"cache-control": #"no-cache",
#"postman-token": #"900e1577-4876-cd9a-d24c-cb0631b4a1fb" };
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
[request setHTTPMethod:#"POST"];
[request setAllHTTPHeaderFields:headers];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
}
else
{
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSString *success = [[jsonDic objectForKey:#"success"]stringValue];
if (
[success isEqualToString:
#"1"])
{
provinceList=[NSMutableArray arrayWithArray:[jsonDic objectForKey:#"data"]];
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
});
}
}
}];
[dataTask resume];
}
#end
I am making a game in which the player can achieve a positive high score or a negative low score depending on the choices they make. The high score has been working fine, but I'm having trouble with the low score.
-(void)authenticateLocalPlayer{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil) {
[self presentViewController:viewController animated:YES completion:nil];
}
else{
if ([GKLocalPlayer localPlayer].authenticated) {
_gameCenterEnabled = YES;
// Get the default leaderboard identifier.
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
else{
_leaderboardIdentifier = leaderboardIdentifier;
}
}];
}
else{
_gameCenterEnabled = NO;
}
}
};
}
-(void)reportScore{
GKScore *highscore = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
highscore.value = HighScoreNumber;
[GKScore reportScores:#[highscore] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
-(void)showLeaderboardAndAchievements:(BOOL)shouldShowLeaderboard{
GKGameCenterViewController *gcViewController = [[GKGameCenterViewController alloc] init];
gcViewController.gameCenterDelegate = self;
if (shouldShowLeaderboard) {
gcViewController.viewState = GKGameCenterViewControllerStateLeaderboards;
gcViewController.leaderboardIdentifier = _leaderboardIdentifier;
}
else{
gcViewController.viewState = GKGameCenterViewControllerStateAchievements;
}
[self presentViewController:gcViewController animated:YES completion:nil];
}
You'll notice leaderboardidentifier, it is useful for reporting scores to the default leaderboard, but when I try to get it to work for two different ones, the code shuts down.
I've tried adding this to "Report Score":
GKScore *lowscore = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
lowscore.value = LowScoreNumber;
[GKScore reportScores:#[lowscore] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
}
Then, I change the leaderboard identifiers to match itunesconnect, but I'm not sure how I need to change authenticateLocalPlayer and shouldShowLeaderboardandAchievements.
I have some experience with game center. I have two games on the App Store that have multiple leaderboards (Squared!! and Primes!).
Instead of having one method for each leaderboard I made one method for submitting scores. Here is that method:
-(void) submitScore:(int64_t)score Leaderboard: (NSString*)leaderboard
{
//1: Check if Game Center
// features are enabled
if (!_gameCenterFeaturesEnabled) {
return;
}
//2: Create a GKScore object
GKScore* gkScore =
[[GKScore alloc]
initWithLeaderboardIdentifier:leaderboard];
//3: Set the score value
gkScore.value = score;
//4: Send the score to Game Center
[gkScore reportScoreWithCompletionHandler:
^(NSError* error) {
[self setLastError:error];
BOOL success = (error == nil);
if ([_delegate
respondsToSelector:
#selector(onScoresSubmitted:)]) {
[_delegate onScoresSubmitted:success];
}
}];
}
When you want to submit your high scores all you have to do is add something like:
[[GCHelper sharedGameKitHelper] submitScore:myLowScore Leaderboard:TELS];
[[GCHelper sharedGameKitHelper] submitScore:myHighScore Leaderboard:TEHS];
GCHelper is the class that contains my submitScore:Leaderboard: method.
To view your leaderboards or achievements within your app try this:
- (void) presentLeaderboards {
GKGameCenterViewController* gameCenterController = [[GKGameCenterViewController alloc] init];
gameCenterController.viewState = GKGameCenterViewControllerStateLeaderboards;
gameCenterController.gameCenterDelegate = self;
[self presentViewController:gameCenterController animated:YES completion:nil];
}
- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController*) gameCenterViewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) presentAchievements {
GKGameCenterViewController* gameCenterController = [[GKGameCenterViewController alloc] init];
gameCenterController.viewState = GKGameCenterViewControllerStateAchievements;
gameCenterController.gameCenterDelegate = self;
I hope this answers your question!
I am wondering if it's possible to post something on a user's facebook wall using SLComposeViewController but without showing the share sheet/dialog?
Following is the code I am using:
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
SLComposeViewControllerCompletionHandler myBlock = ^(SLComposeViewControllerResult result){
if (result == SLComposeViewControllerResultCancelled) {
NSLog(#"Cancelled");
} else
{
NSLog(#"Done");
}
[controller dismissViewControllerAnimated:YES completion:Nil];
};
controller.completionHandler =myBlock;
[controller setInitialText:eventInfoToFacebook];
[self presentViewController:controller animated:YES completion:Nil];
}
Thanks in advance.
Import the Social Framework:
#import <Social/Social.h>
-
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
SLComposeViewControllerCompletionHandler myBlock = ^(SLComposeViewControllerResult result){
if (result == SLComposeViewControllerResultCancelled) {
NSLog(#"Cancelled");
} else
{
NSLog(#"Done");
}
[controller dismissViewControllerAnimated:YES completion:Nil];
};
controller.completionHandler =myBlock;
[controller setInitialText:#"Test Post from mobile.safilsunny.com"];
[controller addURL:[NSURL URLWithString:#"http://www.mobile.safilsunny.com"]];
[controller addImage:[UIImage imageNamed:#"fb.png"]];
[self presentViewController:controller animated:YES completion:Nil];
}
else{
NSLog(#"UnAvailable");
}
}
/
//Deprecated in iOS6
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
ACAccount *account = [[ACAccount alloc] initWithAccountType:accountType];
NSLog(#"%#, %#", account.username, account.description);
}];
Here I got the answer, for posting image data and url together we need to add Social.framework, this framework is available in iOS6.
Just add the Social.framework in your project and add the blew code.
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook])
{
SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
SLComposeViewControllerCompletionHandler myBlock = ^(SLComposeViewControllerResult result){
if (result == SLComposeViewControllerResultCancelled) {
NSLog(#"ResultCancelled");
} else
{
NSLog(#"Success");
}
[controller dismissViewControllerAnimated:YES completion:Nil];
};
controller.completionHandler =myBlock;
[controller addURL:[NSURL URLWithString:#"https://itunes.apple.com/us/app/social-checkin/id504791401?mt=8"]];
if (encoded_ImageData == nil) {
[controller addImage:[UIImage imageNamed:#"No_ImageFound.png"]];
}
else
{
[controller addImage:[UIImage imageWithData:encoded_ImageData]];
}
NSString *businessName;
//Set business name string to be passed on facebook
if (m_BusinessNameString == nil || [m_BusinessNameString isEqualToString:#""])
{
businessName = #"Business name not specified!";
}
else
{
businessName = [m_BusinessNameString uppercaseString];
}
NSString *nameString = [NSString stringWithFormat:#"CHECKED IN #"];
//user has checked in with his friends if sc-merchant
NSString *friendsString;
if ([checkedFriendsNameArray count] > 0)
{
NSMutableString *checkedFriendsTempStr = [[NSMutableString alloc] init];
for (NSMutableString *checkedStr in checkedFriendsNameArray)
{
[checkedFriendsTempStr appendFormat:[NSString stringWithFormat:#"%#,",checkedStr]];
friendsString = [NSString stringWithFormat:#"WITH %#",checkedFriendsTempStr];
}
}
else
{
friendsString = [NSString stringWithFormat:#"WITH NO FRIENDS"];
}
NSString *fname= [[NSUserDefaults standardUserDefaults] valueForKey:#"userfname"];
NSString *lname= [[NSUserDefaults standardUserDefaults] valueForKey:#"userlname"];
NSString *name=[fname stringByAppendingString:[NSString stringWithFormat:#"%#",lname]];
NSString *main_TextString =[NSString stringWithFormat:#"%# \n %# %# %# %#",upperCaseStatusString,name,nameString,businessName,friendsString];
[controller setInitialText:main_TextString];
[self presentViewController:controller animated:YES completion:Nil];
}
else{
NSLog(#"UnAvailable");
}
Add below Code in your ViewController and import below framework.
import FBSDKCoreKit
import FBSDKLoginKit
import FBSDKShareKit
#IBAction func btnPostClick(_ sender: Any)
{
if (FBSDKAccessToken.current() != nil)
{
if FBSDKAccessToken.current().hasGranted("publish_actions"){
postOnFB()
}
else
{
let loginManager = FBSDKLoginManager()
loginManager.logIn(withPublishPermissions: ["publish_actions"], from: self, handler: { (result, error) in
if error == nil{
self.postOnFB()
}
else{
print(error?.localizedDescription ?? "")
}
})
}
}
else
{
let loginManager = FBSDKLoginManager()
loginManager.logIn(withPublishPermissions: ["publish_actions"], from: self, handler: { (result, error) in
if error == nil{
self.postOnFB()
}
})
}
}
func postOnFB()
{
FBSDKGraphRequest(graphPath: "me/feed", parameters: ["message": "YOUR MESSAGE"], httpMethod: "POST").start { (connection, result, error) in
if error == nil{
print("post id \(result ?? "")")
}
else{
print("error is \(error?.localizedDescription ?? "")")
}
}
}
this is possible in facebook-ios-sdk 3.0.
here
i am making the share with this code.
[FBRequestConnection startWithGraphPath:#"me/feed"
parameters:params
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
NSDictionary * result,
NSError *error) {
if (error) {
NSLog(#"Error: %#", [error localizedDescription]);
} else {
}
}];
i called this method when user clicks share button and there is no dialog with the user it directly post to the users wall. params is parameters that sharing includes.
I'm recoding audio/video using AVfoudnation. and I need to play a sounds, using system sounds, before I start capturing video/audio. This is working correctly the first time, but when I try to do it the second time, the system audi doesn't play. My guess is that something in the AVfoundation is not been released correctly.
In my application deletage, I have this code in the applicationDidFinishLaunching method:
VKRSAppSoundPlayer *aPlayer = [[VKRSAppSoundPlayer alloc] init];
[aPlayer addSoundWithFilename:#"sound1" andExtension:#"caf"];
self.appSoundPlayer = aPlayer;
[aPlayer release];
and also this method
- (void)playSound:(NSString *)sound
{
[appSoundPlayer playSound:sound];
}
As you can see I'm using VKRSAppSoundPlayer, which works great!
In a view, I have this code:
- (void) startSession
{
self.session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
if([session canSetSessionPreset:AVCaptureSessionPreset640x480])
session.sessionPreset = AVCaptureSessionPresetMedium;
[session commitConfiguration];
CALayer *viewLayer = [videoPreviewView layer];
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = viewLayer.bounds;
[viewLayer addSublayer:captureVideoPreviewLayer];
self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:[self frontFacingCameraIfAvailable] error:nil];
self.audioInput = [AVCaptureDeviceInput deviceInputWithDevice:[self audioDevice] error:nil];
if(videoInput){
self.videoOutput = [[AVCaptureMovieFileOutput alloc] init];
[session addOutput:videoOutput];
//[videoOutput release];
if([session canAddInput:videoInput]){
//[session beginConfiguration];
[session addInput:videoInput];
}
//[videoInput release];
[session removeInput:[self audioInput]];
if([session canAddInput:audioInput]){
[session addInput:audioInput];
}
//[audioInput release];
if([session canAddInput:audioInput])
[session addInput:audioInput];
NSLog(#"startRunning!");
[session startRunning];
[self startRecording];
if(![self recordsVideo])
[self showAlertWithTitle:#"Video Recording Unavailable" msg:#"This device can't record video."];
}
}
- (void) stopSession
{
[session stopRunning];
[session release];
}
- (AVCaptureDevice *)frontFacingCameraIfAvailable
{
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *captureDevice = nil;
Boolean cameraFound = false;
for (AVCaptureDevice *device in videoDevices)
{
NSLog(#"1 frontFacingCameraIfAvailable %d", device.position);
if (device.position == AVCaptureDevicePositionBack){
NSLog(#"1 frontFacingCameraIfAvailable FOUND");
captureDevice = device;
cameraFound = true;
break;
}
}
if(cameraFound == false){
for (AVCaptureDevice *device in videoDevices)
{
NSLog(#"2 frontFacingCameraIfAvailable %d", device.position);
if (device.position == AVCaptureDevicePositionFront){
NSLog(#"2 frontFacingCameraIfAvailable FOUND");
captureDevice = device;
break;
}
}
}
return captureDevice;
}
- (AVCaptureDevice *) audioDevice
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
if ([devices count] > 0) {
return [devices objectAtIndex:0];
}
return nil;
}
- (void) startRecording
{
#if _Multitasking_
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
[self setBackgroundRecordingID:[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}]];
}
#endif
[videoOutput startRecordingToOutputFileURL:[self generatenewVideoPath]
recordingDelegate:self];
}
- (void) stopRecording
{
[videoOutput stopRecording];
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections error:(NSError *)error
{
NSFileManager *man = [[NSFileManager alloc] init];
NSDictionary *attrs = [man attributesOfItemAtPath: [outputFileURL path] error: NULL];
NSString *fileSize = [NSString stringWithFormat:#"%llu", [attrs fileSize]];
// close this screen
[self exitScreen];
}
-(BOOL)recordsVideo
{
AVCaptureConnection *videoConnection = [AVCamUtilities connectionWithMediaType:AVMediaTypeVideo
fromConnections:[videoOutput connections]];
return [videoConnection isActive];
}
-(BOOL)recordsAudio
{
AVCaptureConnection *audioConnection = [AVCamUtilities connectionWithMediaType:AVMediaTypeAudio
fromConnections:[videoOutput connections]];
return [audioConnection isActive];
}
If I do [videoInput release]; and [audioInput release]; I got a bad access error. that's why they are commented out. This may be part of the issue.
If I try to play the system sound n times, it work, but if I go first to the recording script, it wont work after that.
Any ideas?
The proper way to release AVCaptureSession is the following:
- (void) destroySession {
// Notify the view that the session will end
if ([delegate respondsToSelector:#selector(captureManagerSessionWillEnd:)]) {
[delegate captureManagerSessionWillEnd:self];
}
// remove the device inputs
[session removeInput:[self videoInput]];
[session removeInput:[self audioInput]];
// release
[session release];
// remove AVCamRecorder
[recorder release];
// Notify the view that the session has ended
if ([delegate respondsToSelector:#selector(captureManagerSessionEnded:)]) {
[delegate captureManagerSessionEnded:self];
}
}
If you're having some sort of release problems (bad access), I can recommend taking your code out of your current "messy" project to some other new project and debug the problem over there.
When I had similar problem, I just did that. I shared it on Github, you might find this project useful: AVCam-CameraReleaseTest
I am trying to explore some codes in Objective-C. I came across an open source program - batch renamer. I was looking at its code and adding my own implementation. There is one thing in this code that I could not understand - I was hoping someone would be able to help me out.
The problem is that there is a renamer delegate "- (void)renamed" and I have no idea how it is called. So, I was wondering how does the program know when to call/use this delegate.
The code is as follows:
#import "ControllerMain.h"
static NSString *addFilesIdentifier = #"addFiles_item";
static NSString *removeFilesIdentifier = #"removeFiles_item";
static NSString *cleanAllIdentifier = #"cleanAll_item";
static NSString *updateUrl = #"http://www.hardboiled.it/software/update.xml";
#implementation ControllerMain
- (id)init
{
self = [super init];
//init some object
tableSource = [[NSMutableArray alloc] init];
updater = [[STUpdateChecker alloc] init];
renamer = [[STRenamer alloc] init];
//set some variables
withExt = NO;//for include the extension in the renaming, default NO
renamed = NO;//is YES after renaming preview
insoverappPosition = 0;
//set the notification for NSControlTextDidChangeNotification
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(textDidEndEditing:) name:#"NSControlTextDidChangeNotification" object:nil];
return self;
}
-(void)awakeFromNib
{
//set the delegates
[tabella setDelegate:self];
[tableSource setDelegate:self];
[renamer setDelegate:self];
[updater setDelegate:self];
//check if the software is updated
[updater checkUpdateWithUrl:[NSURL URLWithString:updateUrl]];
//drag' drop - set the dragged types
[tabella registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
//toolbar configuration
toolbar = [[NSToolbar alloc] initWithIdentifier:#"toolbar"];
[toolbar setDelegate:self];
//mainWindows properties
[mainWindow center];
[mainWindow setTitle:#"macXrenamer"];
[mainWindow setToolbar:toolbar];
//set the extension checkbox
[extSwitch setState:0];
//Set the custom cell imageAndTextCell
ImageAndTextCell *imageAndTextCell = nil;
NSTableColumn *tableColumn = nil;
tableColumn = [tabella tableColumnWithIdentifier:#"original_name"];
imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease];
[imageAndTextCell setEditable: NO];
[tableColumn setDataCell:imageAndTextCell];
//
//initialize the window for empty table
[self tableSourceIsEmpty];
//release the toolbar
[toolbar release];
}
- (void)dealloc
{
//release all
[tabella unregisterDraggedTypes];
[tableSource release];
[renamer release];
[super dealloc];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
//close the application
return YES;
}
/* ################### tableSource delegates #################################*/
- (void)tableSourceIsEmpty
{
if (KDEBUG)
NSLog(#"tablesource is empty");
[upper_lower setEnabled:NO];
[from setEditable:NO];
[to setEditable:NO];
[insertText setEditable:NO];
[insertAtPosition setEditable:NO];
[insertAtPosition setIntValue:0];
[renameButton setEnabled:NO];
[annullButton setEnabled:NO];
[searchField setEditable:NO];
[replaceField setEditable:NO];
}
- (void)tableSourceIsNotEmpty
{
if (KDEBUG)
NSLog(#"tablesource is not empty");
[upper_lower setEnabled:YES];
[from setEditable:YES];
[to setEditable:YES];
[insertText setEditable:YES];
[insertAtPosition setEditable:YES];
[searchField setEditable:YES];
[replaceField setEditable:YES];
}
-(void)tableSourceDidChange
{
NSString *countString = [NSString stringWithFormat:#"%d files",[tableSource count]];
[number_of_files setStringValue:countString];
}
/*####################end tableSource delegates###############################*/
/*######################renamer delegates#####################################*/
- (void)renamed
{
NSLog(#"renaming preview ok");
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor blackColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor blackColor]];
[to setTextColor:[NSColor blackColor]];
}
renamed = YES;
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
}
- (void)notRenamed
{
renamed = NO;
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor redColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor redColor]];
[to setTextColor:[NSColor redColor]];
}
NSLog(#"exception in preview delegate");
[renameButton setEnabled:NO];
}
/* ###################end renamer delegates ##################################*/
//make the file extension editable
-(IBAction)makeExtEditable:(id)sender
{
if (KDEBUG)
NSLog(#"makeExtEditable action");
if ([sender state] == 0) {
withExt = NO;
}else if ([sender state] == 1) {
withExt = YES;
}
}
//add files to the table
-(IBAction)addFiles:(id)sender
{
//start the progression bar
[progBar startAnimation:self];
int result;
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
[oPanel setCanChooseFiles:YES];
[oPanel setAllowsMultipleSelection:YES];
[oPanel setResolvesAliases:NO];
result = [oPanel runModalForTypes:nil];
if (result == NSOKButton) {
NSArray *filesToOpen = [oPanel filenames];
[tableSource add:filesToOpen];
[tabella reloadData];
}
//stop the progression bar
[progBar stopAnimation:self];
}
//remove files from the table
-(IBAction)removeFiles:(id)sender
{
if(KDEBUG)
NSLog(#"remove the selected file from the table");
[progBar startAnimation:self];
NSIndexSet *selected = [tabella selectedRowIndexes];
[tableSource removeAtIndexes:selected];
[tabella reloadData];
[progBar stopAnimation:self];
}
//remove all files from the table
-(IBAction)clearTable:(id)sender
{
if(KDEBUG)
NSLog(#"clear all table");
[progBar startAnimation:self];
[tableSource cleanAll];
[tabella reloadData];
[progBar stopAnimation:self];
}
//annull
-(IBAction)annulRenaming:(id)sender
{
[tableSource annull];
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor blackColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor blackColor]];
[to setTextColor:[NSColor blackColor]];
}
renamed = NO;
[renameButton setEnabled:NO];
[tabella reloadData];
}
/*###########################log section######################################*/
-(IBAction)showLogWindows:(id)sender{
if ([logWindow isVisible]) {
[logWindow setIsVisible:FALSE];
}else {
[logWindow setIsVisible:TRUE];
}
}
-(void)addToLog:(NSString *)text
{
NSString *textLog = [text stringByAppendingString:#"\n\r"];
NSRange endRange;
endRange.location = [[logField textStorage] length];
endRange.length = 0;
[logField replaceCharactersInRange:endRange withString:textLog];
endRange.length = [textLog length];
[logField scrollRangeToVisible:endRange];
}
/*#######################end log section######################################*/
/*######################editing actions#######################################*/
-(IBAction)finalRenaming:(id)sender
{
if(KDEBUG)
NSLog(#"renaming button pressed");
//start the progression bar
[progBar startAnimation:self];
//count of the files really renamed
int countRenamed = 0;
//count of the renaming error
int errRenamed = 0;
//the result of rename()
int renameResult;
//the enumerator and the obj
NSEnumerator *en = [tableSource objectEnumerator];
id row;
if(renamed)
{
while(row = [en nextObject])
{
renameResult = rename([[row objectAtIndex:0] fileSystemRepresentation], [[row objectAtIndex:1] fileSystemRepresentation]);
if(renameResult == 0){
NSString *textLog = [NSString stringWithFormat:#"%# renamed with\n %#", [row objectAtIndex:0],[row objectAtIndex:1]];
NSLog(textLog);
[self addToLog:textLog];
countRenamed++;
}else {
NSString *textLog =[NSString stringWithFormat: #"Error in file renaming %#", [row objectAtIndex:0]];
NSLog(textLog);
[self addToLog:textLog];
errRenamed++;
}
}
if(errRenamed >0){
//open the panel alert
int result;
result = NSRunAlertPanel(#"Renaming error. Please check the log", #"Error!", #"Ok", NULL, NULL);
}
//print the result of renaming
[notiField setStringValue:[NSString stringWithFormat:#"renamed %d/%d files, %d errors", countRenamed,[tableSource count],errRenamed]];
//
[tableSource reinitialize];
[tabella reloadData];
[renameButton setEnabled:NO];
[annullButton setEnabled:NO];
[progBar stopAnimation:self];
}
}
- (void)textDidEndEditing:(NSNotification *)aNotification
{
[progBar startAnimation:self];
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
if(KDEBUG)
NSLog(#"insert selected");
if(insoverappPosition == 1)
{
if(KDEBUG)
NSLog(#"overwrite selected");
tableSource = [renamer overwriteChar:tableSource insertText:[insertText stringValue] position:[insertAtPosition intValue] withExt:withExt];
}else if(insoverappPosition == 0){
if(KDEBUG)
NSLog(#"insert selected");
tableSource = [renamer insertChar:tableSource insertText:[insertText stringValue] position:[insertAtPosition intValue] withExt:withExt];
}else if(insoverappPosition == 2){
if(KDEBUG)
NSLog(#"append selected");
tableSource = [renamer appendChar:tableSource appendText:[insertText stringValue] withExt:withExt];
}
}else if ([tabViewId isEqual:#"remove"]) {
if(KDEBUG)
NSLog(#"remove selected");
tableSource = [renamer removeChar:tableSource from:[from intValue] to:[to intValue] withExt:withExt];
}else if([tabViewId isEqual:#"search"]){
if(KDEBUG)
NSLog(#"search selected");
tableSource = [renamer searchAndReplace:tableSource string:[searchField stringValue] withString:[replaceField stringValue] withExt:withExt];
}
[progBar stopAnimation:self];
}
-(IBAction)upLowerCellClicked:(id)sender
{
NSCell* cell;
cell = [upper_lower selectedCell];
int tag = [cell tag];
if (tag == 0) {
if(KDEBUG)
NSLog(#"lowercase selected");
tableSource = [renamer makeLowerCase:tableSource withExt:withExt];
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
[tabella reloadData];
}
else if(tag == 1){
if(KDEBUG)
NSLog(#"uppercase selected");
tableSource = [renamer makeUpperCase:tableSource withExt:withExt];
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
[tabella reloadData];
}
}
-(IBAction)insertOverwriteClicked:(id)sender
{
if(KDEBUG)
NSLog(#"insertOverwriteClicked");
NSCell* cell;
cell = [insert_overwrite selectedCell];
int tag = [cell tag];
if(tag == 0)
{
if(KDEBUG)
NSLog(#"insert");
[insertAtPosition setEnabled:YES];
insoverappPosition = 0;
}else if(tag==1){
if(KDEBUG)
NSLog(#"overwrite");
[insertAtPosition setEnabled:YES];
insoverappPosition = 1;
}else if (tag==2) {
if(KDEBUG)
NSLog(#"append");
[insertAtPosition setEnabled:NO];
insoverappPosition = 2;
}
}
/*################end editing actions#########################################*/
-(void)newUpdateIsOnline
{
NSLog(#"newUpdateIsOnline");
BOOL retval;
retval = (NSAlertDefaultReturn == NSRunAlertPanel(#"Update Available", #"Update now or later", #"Update", #"Cancel", nil, nil));
if(retval){
if(KDEBUG)
NSLog(#"update now");
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:#"http://www.hardboiled.it/software/rinominatore-upgrade.zip"]];
//to edit
//[[NSNotificationCenter defaultCenter] postNotificationName:#"openSheetNotification" object:self userInfo:nil];
}else {
if(KDEBUG)
NSLog(#"cancel the update");
}
//release the updater. now is useless
[updater release];
}
/*################nstableview delegates#######################################*/
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [tableSource count];
}
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if ([[aTableColumn identifier] isEqualToString: #"original_name"]) {
id obj = [tableSource objectAtRow:rowIndex atIndex:0] ;
return [obj lastPathComponent];
//return theIcon;
}else if([[aTableColumn identifier] isEqualToString: #"new_name"]){
id obj = [tableSource objectAtRow:rowIndex atIndex:1] ;
return [obj lastPathComponent];
}
return nil;
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if(cell_with_icon)
{
if ( [[aTableColumn identifier] isEqualToString:#"original_name"] ){
[((ImageAndTextCell*) cell) setImage:[tableSource objectAtRow:rowIndex atIndex:2]];
}
}
}
/* ###############end nstableview delegates #################################*/
/*############### nstoolbar delegates #######################################*/
- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
{
return [NSArray arrayWithObjects:addFilesIdentifier,
removeFilesIdentifier,cleanAllIdentifier,
NSToolbarFlexibleSpaceItemIdentifier,
NSToolbarSpaceItemIdentifier,
NSToolbarSeparatorItemIdentifier, nil];;
}
- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
{
return [NSArray arrayWithObjects:addFilesIdentifier,
removeFilesIdentifier,NSToolbarFlexibleSpaceItemIdentifier,cleanAllIdentifier, nil];
}
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
NSToolbarItem *toolbarItem = nil;
if ([itemIdentifier isEqualTo:addFilesIdentifier]) {//button addfiles
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Add"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Add"];
[toolbarItem setImage:[NSImage imageNamed:#"add.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(addFiles:)];
}else if ([itemIdentifier isEqualTo:removeFilesIdentifier]) {//button remove files
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Remove"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Remove"];
[toolbarItem setImage:[NSImage imageNamed:#"remove.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(removeFiles:)];
}else if ([itemIdentifier isEqualTo:cleanAllIdentifier]) {//button clean
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Clean All"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Clean the table"];
[toolbarItem setImage:[NSImage imageNamed:#"cleanAll.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(clearTable:)];
}
return [toolbarItem autorelease];
}
/*###############end nstoolbar delegates #####################################*/
/*################drag'n drop delegates #####################################*/
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard {
// Drag and drop support
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:self];
[pboard setData:data forType:NSFilenamesPboardType];
return YES;
}
- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
{
// Add code here to validate the drop
if (KDEBUG)
NSLog(#"validate Drop");
return NSDragOperationEvery;
}
- (BOOL)tableView:(NSTableView*)tv acceptDrop:(id )info row:(int)row dropOperation:(NSTableViewDropOperation)op
{
if (KDEBUG)
NSLog(#"acceptDrop");
NSPasteboard *pboard = [info draggingPasteboard];
if ( [[pboard types] containsObject:NSFilenamesPboardType] ) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
[tableSource add:files];
}
[tabella reloadData];
return YES;
}
/*################end drag'n drop delegates ##################################*/
#end
The delegate is the object, not the method. The ControllerMain object is set as some other object's delegate. When that other object sees the condition that tells it renaming has occurred (whatever that means), it executes something along the lines of [[self delegate] renamed], which calls the ControllerMain method.