In few words, my application is doing that :
1) My main view (RootViewController) has a buton when I tap on it, it displays the player (PlayerViewController) :
2) In my Player, I initialize the video I want to play
-> It's working good, my movie is display
My problem :
When I go back to my main view :
And I tap again on the button, I get a *Program received signal: “EXC_BAD_ACCESS”.*
If I comment self.player.contentURL = [self movieURL]; it's working, but when I let it, iI have this problem.
I read that it's due to null pointer or memory problem but I don't understand why it's working the first time and not the second time. I release my object in dealloc method.
Thanks for your help !
Bruno.
Here is my code :
Root View Controller
RootViewController.h
#import <UIKit/UIKit.h>
#import "PlayerViewController.h"
#interface RootViewController : UIViewController {
IBOutlet UIButton * myButton;
}
#property (nonatomic,retain) IBOutlet UIButton * myButton;
-(IBAction)displayPlayer:(id)sender;
- (void) returnToRoot: (PlayerViewController *) controller;
#end
RootViewController.m
#import "RootViewController.h"
#implementation RootViewController
#synthesize myButton;
-(IBAction)displayPlayer:(id)sender
{
PlayerViewController *playerViewController = [[PlayerViewController alloc] initWithNibName:#"PlayerViewController" bundle:nil];
playerViewController.delegate = self;
playerViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController: playerViewController animated: YES];
[playerViewController release];
}
- (void) returnToRoot: (PlayerViewController *) controller
{
[self dismissModalViewControllerAnimated: YES];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#end
Player View Controller
PlayerViewController.h
#import <UIKit/UIKit.h>
#import <MediaPlayer/MPMoviePlayerController.h>
#protocol PlayerViewControllerDelegate;
#interface PlayerViewController : UIViewController {
UIView *viewForMovie;
MPMoviePlayerController *player;
}
#property (nonatomic, assign) id <PlayerViewControllerDelegate> delegate;
#property (nonatomic, retain) IBOutlet UIView *viewForMovie;
#property (nonatomic, retain) MPMoviePlayerController *player;
- (NSURL *)movieURL;
-(IBAction)goBackToRoot:(id)sender;
#end
#protocol PlayerViewControllerDelegate
- (void) returnToRoot: (PlayerViewController *) controller;
#end
PlayerViewController.m
#import "PlayerViewController.h"
#implementation PlayerViewController
#synthesize player;
#synthesize viewForMovie;
#synthesize delegate;
- (void)dealloc {
[super dealloc];
[player release];
[viewForMovie release];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"viewDidLoad");
self.player = [[MPMoviePlayerController alloc] init];
[self.player autorelease];
self.player.view.frame = self.viewForMovie.bounds;
self.player.view.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
[self.viewForMovie addSubview:player.view];
self.player.contentURL = [self movieURL];
[self.player play];
}
-(NSURL *)movieURL
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath =
[bundle
pathForResource:#"myVideo"
ofType:#"mp4"];
if (moviePath) {
return [NSURL fileURLWithPath:moviePath];
} else {
return nil;
}
}
-(IBAction)goBackToRoot:(id)sender{
[self.delegate returnToRoot: self];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
#end
Problem
The second time I call "displayPlayer" I had the EXC_BAD_ACCESS
I solved it !!!
I look on the MPMoviePlayerController to see what kind of variable is contentURL
(NSURL *)contentURL
It means I have also to liberate it.
I do that in my dealloc method putting a nil value:
-(void) dealloc {
[super dealloc];
self.player.contentURL = nil;
[player release];
[viewForMovie release];
}
If I comment self.player.contentURL =
[self movieURL]; it's working, but
when I let it, iI have this problem.
In that case, how is contentURL declared? Does the #property definition include copy or retain?
Related
LoginViewController is my initial view controller. Email address is an input in the LoginViewController and I am trying to send it to FirstViewController. I went through a lot of solutions posted here but was unsuccessful to find a link to my answer.
Please have a look at my code and tell me where I am going wrong. I am stuck at this point from a couple of days. My main problem is that, the output of emailString shows null when I print it to see if it was carried to the FirstViewController.
FYI - I am using storyboard. I have a Tab Bar Controller which has three tabs and FirstViewController is the first tab page.
LoginViewController.h
#import <UIKit/UIKit.h>
#import "FirstViewController.h"
#interface LoginViewController : UIViewController{
NSString *email;
}
- (IBAction)LoginButton:(id)sender;
- (IBAction)CancelButton:(id)sender;
- (IBAction)dismissKeyboard:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *EmailField;
#property (weak, nonatomic) IBOutlet UITextField *PasswordField;
#end
LoginViewController.m
#import "LoginViewController.h"
#import "FirstViewController.h"
#define USERNAME #"abc#gmail.com"
#interface LoginViewController ()
#end
#implementation LoginViewController
#synthesize EmailField;
#synthesize PasswordField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
email = [[NSString alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction)LoginButton:(id)sender {
email = EmailField.text;
if([EmailField.text isEqualToString:USERNAME])
{
FirstViewController *fvc = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
fvc.emailString = [[NSString alloc] initWithFormat:#"%#",EmailField.text];
// fvc.emailString = email;
[self.navigationController pushViewController:fvc animated:YES];
}
[EmailField resignFirstResponder];
}
- (IBAction)CancelButton:(id)sender {
NSLog(#"Cancel button pressed!!!");
[EmailField resignFirstResponder];
[PasswordField resignFirstResponder];
}
- (IBAction)dismissKeyboard:(id)sender {
[EmailField resignFirstResponder];
[PasswordField resignFirstResponder];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self LoginButton:nil];
[textField resignFirstResponder];
return YES;
}
#end
FirstViewController.h
#import <UIKit/UIKit.h>
#import "LoginViewController.h"
#interface FirstViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *emailLabel;
#property (nonatomic, retain) NSMutableData *receivedData;
#property (copy) NSString *emailString;
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize emailLabel;
#synthesize receivedData;
#synthesize emailString;
- (void)viewDidLoad
{
[super viewDidLoad];
[emailLabel setText: emailString];
NSString *theURL = [NSURL URLWithString:[NSString stringWithFormat:#"http://.....email=%#",emailString]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:theURL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if(connection){
NSLog(#"connection successful");
NSLog(#"%#",emailString);
receivedData = [NSMutableData data];
}
else{
NSLog(#"connection failed");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[receivedData setLength:0];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(#"Success");
NSLog(#"Received %d bytes of data",[receivedData length]);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
I tried implementing prepareFOrSegue method in LoginViewController too. But it still didnot make any change. This is the code I have written in it.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"showDetailSegue"])
{
NSString *email = EmailField.text;
NSLog (#"++++++++++ %#", email);
FirstViewController *fvc = [segue destinationViewController];
fvc.emailString=email;
}
}
Screenshot of Storyboard:
If you are using StoryBoards I'd strongly suggest you use segues to call the different view controllers. That way you can push vc's and pass info relatively easily.
You can override the native method prepareForSegue in your Login VC, and set the properties there. You can name your segue id as anything in the storyboard.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"firstVC"]) {
FirstViewController *firstVC = [segue destinationViewController];
firstVC.emailString = EmailField.text;
}
}
if you really want, and I'd advise against it vs. using static variables is
NSUserDefaults.
[[NSUserDefaults standardUserDefaults]
setObject:EmailField.text forKey:#"emailString"];
to get it back later
NSString *emailString = [[NSUserDefaults standardUserDefaults]
stringForKey:#"emailString"];
NSLog(#"%#",emailString);
I would save the Email and password in the IOS Keychain securely instead of passing it in between views.
https://developer.apple.com/library/ios/#documentation/security/conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html#//apple_ref/doc/uid/TP30000897-CH208-SW1
I got the solution.
The only three lines requires for me to add in the prepareForSegue were these three and I got my program working
FirstViewController* fvc = [[FirstViewController alloc] init];
UITabBarController *tbc = [segue destinationViewController];
fvc = (FirstViewController *) [[tbc customizableViewControllers] objectAtIndex:0];
Thanks everyone!
I try to calculate the size of a UIWebView with a given content, but without showing the view. I only need to know the size.
My Problem: When I execute the code, the delegate of the UIWebView isn't called. Why?
MessageSizeCaluclator.h
#import < Foundation/Foundation.h>
#class Message;
#interface MessageSizeCaluclator : NSObject <UIWebViewDelegate>
- (id)initWithMessage:(Message*)message;
- (void)saveSize;
#end
MessageSizeCaluclator.m
#import "Message.h"
#import "MessageSizeCaluclator.h"
#interface MessageSizeCaluclator () <UIWebViewDelegate>
#property (strong, nonatomic) Message* message;
#property (strong, nonatomic) UIWebView* webView;
#end
#implementation MessageSizeCaluclator
#synthesize message = _message;
#synthesize webView = _webView;
- (id)initWithMessage:(Message*)message
{
self = [super init];
if (self) {
_message = message;
// WebView
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
_webView.delegate = self;
}
return self;
}
- (void)saveSize
{
NSLog(#"%s message = %#", __PRETTY_FUNCTION__, _message.text);
[_webView loadHTMLString:[NSString stringWithFormat:#"<div style='font-family:Helvetica;font-size:13px;'>This is a test</div>", _message.text]
baseURL:nil];
}
#pragma mark - Web view delegate
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSLog(#"%s", __PRETTY_FUNCTION__);
}
#end
Implementation
MessageSizeCaluclator* messageSizeCalculator = [[MessageSizeCaluclator alloc] initWithMessage:message];
[messageSizeCalculator saveSize];
Add your UIWebView to some UIView, make its frame offscreen (so users can't see it). The delegate methods won't be called if UIWebView is not in the view hierarchy of the app.
I have been pulling my hair out all afternoon trying to figure out why the following code will not work. All I am trying to do is pass a string, from one class to another.
In my FirstDetailViewController.h file I declare the NSString
#property(nonatomic, retain) NSString *infoForArray;
And then in my Grinding01_DetailViewController.m I try to set a value for the string
#import "Grinding01_DetailViewController.h"
#import "FirstDetailViewController.h"
#implementation Grinding01_DetailViewController
...
NSString *didLoadMessage = #"Grinding01 Loaded";
FirstDetailViewController *temp = [[FirstDetailViewController alloc] initWithNibName:#"FirstDetailView" bundle:nil];
temp.infoForArray = didLoadMessage;
[self.navigationController pushViewController:temp animated:YES];
}
When I output the infoForArray from the FirstDetailViewController.h it is null.
Any help would be appreciated, I think there's a simple step that I am missing, but I just can't see it.
EDIT: Here is the code from the FirstDetailViewController
FirstDetailViewController.h
#import <UIKit/UIKit.h>
#import "Protocols.h"
#interface FirstDetailViewController : UIViewController <SubstitutableDetailViewController> {
//for the output
IBOutlet UITextView *outputView;
UIToolbar *navigationBar;
NSMutableArray *logMessages;
}
#property (nonatomic, retain) IBOutlet UIToolbar *navigationBar;
//for incoming messages
#property(nonatomic, retain) NSString *infoForArray;
#end
FirstDetailViewController.m
#import "FirstDetailViewController.h"
#implementation FirstDetailViewController
#synthesize navigationBar, infoForArray;
-(void)viewDidLoad{
[super viewDidLoad];
//The log cannot be changed
outputView.editable = NO;
}
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidUnload {
[super viewDidUnload];
self.navigationBar = nil;
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:YES];
NSLog(#"message: %#", infoForArray);
outputView.text = infoForArray;
}
#pragma mark -
#pragma mark Managing the popover
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the toolbar.
NSMutableArray *itemsArray = [navigationBar.items mutableCopy];
[itemsArray insertObject:barButtonItem atIndex:0];
[navigationBar setItems:itemsArray animated:NO];
[itemsArray release];
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Remove the popover button from the toolbar.
NSMutableArray *itemsArray = [navigationBar.items mutableCopy];
[itemsArray removeObject:barButtonItem];
[navigationBar setItems:itemsArray animated:NO];
[itemsArray release];
}
#pragma mark -
#pragma mark Rotation support
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[navigationBar release];
[super dealloc];
}
#end
It sounds like the trouble area is in in FirstDetailViewController. I would suggest posting the code for that so we can see what's going on.
my guess is you are checking for infoForArray somewhere in the instantiation process of FirstDetailViewController, which occurs before you set temp.infoForArray = didLoadMessage.
Just for reference, if you check for infoForArray in viewDidLoad that will be too early. viewDidLoad is triggered when the view is put into memory. What you want is viewDidAppear, which you may have to add yourself
I'm trying to save the name of a button using a singleton so that the name can be accessed in another view to play a video with the same name. However, I'm getting the error: SIGABRT. I don't really see what's wrong with my code. Any ideas?
#import "List.h"
#import "MyManager.h"
#import "Video.h"
#implementation ExerciseList
-(IBAction) goToVideo:(UIButton *) sender{
MyManager *sharedManager = [MyManager sharedManager];
sharedManager.vidName = [[sender titleLabel] text];
Video *videoGo = [[Video alloc] initWithNibName: #"Video" bundle: nil];
[self.navigationController pushViewController: videoGo animated: YES];
[videoGo release];
}
Here is my .h and .m for MyManager:
#import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSMutableArray *workouts;
NSString *vidName;
}
#property (nonatomic, retain) NSMutableArray *workouts;
#property (nonatomic, retain) NSString *vidName;
+ (id)sharedManager;
#end
#import "MyManager.h"
static MyManager *sharedMyManager = nil;
#implementation MyManager
#synthesize workouts;
#synthesize vidName;
#pragma mark Singleton Methods
+ (id)sharedManager {
#synchronized(self) {
if (sharedMyManager == nil)
sharedMyManager = [[self alloc] init];
}
return sharedMyManager;
}
- (id)init {
if ((self = [super init])) {
workouts = [[NSMutableArray alloc] init];
vidName = [[NSString alloc] init];
}
return self;
}
-(void) dealloc{
self.workouts = nil;
self.vidName = nil;
[super dealloc];
}
#end
You should access the title of the button
sharedManger.vidName = [sender currentTitle];
However you are not using ARC so also check where your vidName property is retain or copy.
if it is not retain or copy then you can use this code also
if(sharedManger.vidname != nil){
[sharedManger.vidName release];
sharedManger.vidName = nil;
}
sharedManger.vidName = [[sender currentTitle] retain];
I am new on iphone and objective-c development.
I want to know how i can change the view (XIB File) after the camera takes a picture.
Can anyone help me or share some code? I am searching for this since a week :(
After finishing the app, i am ready to share my project and/or make a tutorial.
Infos about my App: i want to scan barcodes and save the barcodes in my app.
For scanning barcodes iam using the ZBarSDK.
I hava a TabBarController, on the first Tab, i can open the camera.
After the scan process i want to jump to the second tab (another XIB File) and show the results.
Thanks for any help.
Here my code of the first tab (ScanCodeViewController):
.h
#import < UIKit/UIKit.h >
#class OutPutCodeViewController;
#interface ScanCodeViewController : UIViewController <ZBarReaderDelegate> {
IBOutlet UIImageView *img;
OutPutCodeViewController *output;
}
#property (nonatomic, retain) IBOutlet UIImageView *img;
#property (nonatomic, retain) OutPutCodeViewController *output;
- (IBAction) scanButton;
#end
.m
#import "ScanCodeViewController.h"
#implementation ScanCodeViewController
#synthesize img;
#synthesize output;
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[img release];
[super dealloc];
}
- (IBAction) scanButton {
NSLog(#"Scanbutton wurde geklickt!");
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
ZBarImageScanner *scanner = reader.scanner;
[scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to: 0];
[self presentModalViewController:reader animated: YES];
[reader release];
}
- (void) imagePickerController: (UIImagePickerController*) reader
didFinishPickingMediaWithInfo: (NSDictionary*) info
{
NSLog(#"Entered imagePickerController");
// ADD: get the decode results
id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results) {
break;
}
img.image = [info objectForKey:UIImagePickerControllerOriginalImage];
[reader dismissModalViewControllerAnimated: YES];
//[self presentModalViewController:output animated:YES]; //by using this, app chrashes
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissModalViewControllerAnimated: YES];
}
#end
And here the Secong Tab (OutPutCodeViewController)
.h
#import <UIKit/UIKit.h>
#interface OutPutCodeViewController : UIViewController {
IBOutlet UIImageView *resultImage;
IBOutlet UITextField *resultText;
}
#property (nonatomic, retain) IBOutlet UIImageView *resultImage;
#property (nonatomic, retain) IBOutlet UITextField *resultText;
#end
.m
#import "OutPutCodeViewController.h"
#implementation OutPutCodeViewController
#synthesize resultImage;
#synthesize resultText;
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[resultImage release];
[resultText release];
[super dealloc];
}
#end
Got it!
It is not possible to set more animate:YES.
Here is the sample and right code.
I hope it helps others.
- (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)
break;
[reader dismissModalViewControllerAnimated: NO];
TableDetailViewController *tc = [[TableDetailViewController alloc] initWithNibName:#"TableDetailViewController" bundle:nil];
tc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:tc animated:YES];
[tc release];
}
brush51
In didFinishPickingMediaWithInfo you should call [self.tabBarController setSelectedIndex:1] to switch to the second tab.