#autoreleasepool EXC_BAD_ACCESS - objective-c

I have a simple UIViewControler and when i call the method [self performSelectorInBackground:#selector(load) withObject:nil]; it causes and EXC_BAD_ACCESS
Here is the UIViewControler.m and UIViewControler.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (strong, nonatomic) UITextView *myTextView;
#end
#import "ViewController.h"
#implementation ViewController
#synthesize myTextView;
- (id)init {
self = [super init];
if (self) {
myTextView = [[UITextView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[[self view] addSubview:myTextView];
[self performSelectorInBackground:#selector(load) withObject:nil];
}
return self;
}
- (void) load {
#autoreleasepool {
[myTextView setText:#"LOADING ..."];
//DO SOMETHING ....
}
}
#end
PS.:
The project uses Objective-C ARC

UIKit objects are not thread-safe: you must only access them on the main thread. The line [myTextView setText:#"LOADING ..."]; cannot be safely executed in a background thread.
This may or may not be the reason you are getting an EXC_BAD_ACCESS error but without seeing the rest of the load method I have no way of knowing what else might be wrong.

Related

cocoa nstextfielddelegate EXC_BAD_ACCESS [duplicate]

I am trying to create a delegate for an NSTextField in my view controller, but the program crashes with EXC_BAD_ACCESS. Why does this happen? I read that I am calling a non-existent object, but I don´t know what does not exist. I am using ARC.
This is how the delegate object is created in my view controller:
#import <Cocoa/Cocoa.h>
#import "Delegate.h"
#interface ViewController : NSViewController <NSTextFieldDelegate>{
}
#end
--
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSTextField* textField1 = [[NSTextField alloc] initWithFrame:NSMakeRect(200, 200, 150, 20)];
[self.view addSubview:textField1];
Delegate* delegate1 = [[Delegate alloc]init];
[textField1 setDelegate:delegate1];
}
#end
Why does my program crash?
I think the delegate1 is release, in viewDidLoad
Delegate* delegate1 = [[Delegate alloc]init];
You should create a var for handling it in ViewController.h. Then
delegate1 = [[Delegate alloc]init];

Delegate assignment causes EXC_BAD_ACCESS

I am trying to create a delegate for an NSTextField in my view controller, but the program crashes with EXC_BAD_ACCESS. Why does this happen? I read that I am calling a non-existent object, but I don´t know what does not exist. I am using ARC.
This is how the delegate object is created in my view controller:
#import <Cocoa/Cocoa.h>
#import "Delegate.h"
#interface ViewController : NSViewController <NSTextFieldDelegate>{
}
#end
--
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSTextField* textField1 = [[NSTextField alloc] initWithFrame:NSMakeRect(200, 200, 150, 20)];
[self.view addSubview:textField1];
Delegate* delegate1 = [[Delegate alloc]init];
[textField1 setDelegate:delegate1];
}
#end
Why does my program crash?
I think the delegate1 is release, in viewDidLoad
Delegate* delegate1 = [[Delegate alloc]init];
You should create a var for handling it in ViewController.h. Then
delegate1 = [[Delegate alloc]init];

iOS access a single instance of an object from two different classes

Is it possible to create an instance of an object in class A and access that same instance of the object from class B? I am trying to develop an app that creates a TCP Socket using NSInputStream and NSOutputStream and need more than one class to be able to access it.
Thank you,
Travis Elliott
edit
Here is the code I am working with. Its a program that deals with socket connections. I basically need to be able to communicate to the same socket from my appDelegate and View controller. Here is the code I have based on your help. I am using the appDelegate as the control(D in your example), perhaps I cannot do this. CommunicationHub is the class I need to control the same instance of from both AppDelegate and ViewController.
AppDelegate.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#import "CommunicationHub.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>{
ViewController *viewController;
CommunicationHub *cHub;
}
#property (strong, nonatomic) UIWindow *window;
#property (strong, retain) ViewController *viewController;
#property (strong, retain) CommunicationHub *cHub;
-(void)CreateInstances;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#implementation AppDelegate
#synthesize viewController;
#synthesize cHub;
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self CreateInstances];
// Override point for customization after application launch.
return YES;
}
-(void)CreateInstances{
NSLog(#"Inside CreateInstances");
CommunicationHub *cHub = [[CommunicationHub alloc] init];
viewController = [[ViewController alloc] init];
[viewController initWithcHub:cHub];
NSLog(#"ID of cHub in AppDelegate is %i", cHub);
}
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(#"Application Will Resign Active");
[cHub disconnect];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "CommunicationHub.h"
#interface ViewController : UIViewController
{
CommunicationHub *cHub;
}
#property (strong, nonatomic) IBOutlet UITextField *IPAddress;
#property (strong, nonatomic) IBOutlet UITextField *PortNumber;
- (IBAction)goAwayKeyBoard:(id)sender;
- (IBAction)touchBackground:(id)sender;
-(void) initWithcHub:(CommunicationHub *)ptr;
- (IBAction)connectSocket:(id)sender;
- (IBAction)disconnectSocket:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize IPAddress;
#synthesize PortNumber;
-(void) initWithcHub:(CommunicationHub *)ptr
{
cHub = [[ptr retain]init];
NSLog(#"id of cHub in ViewController is %i", cHub);
}
- (IBAction)connectSocket:(id)sender
{
//Called by button on UI.
int portNumber = [PortNumber.text intValue];
[cHub Connect:(int *)portNumber ipAddress:(IPAddress.text)];
}
- (IBAction)disconnectSocket:(id)sender
{
//Called by button on UI.
[cHub disconnect];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setIPAddress:nil];
[self setPortNumber:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
-(IBAction)goAwayKeyBoard:(id)sender{
[self resignFirstResponder];
}
- (IBAction)touchBackground:(id)sender {
[IPAddress resignFirstResponder];
[PortNumber resignFirstResponder];
}
#end
CommunicationHub.h
#import <UIKit/UIKit.h>
NSInputStream *inputStream;
NSOutputStream *outputStream;
#interface CommunicationHub : NSObject <NSStreamDelegate>
- (void)Connect:(int *)port ipAddress:(NSString *)ipAddress;
- (void) disconnect;
#end
CommunicationHub.m
#import "CommunicationHub.h"
#implementation CommunicationHub
- (void)Connect:(int *)port ipAddress:(NSString *)ipAddress
{
NSLog(#"inside connect method");
if ([inputStream streamStatus] == 0 ||[inputStream streamStatus] == 5 ||[inputStream streamStatus] == 6 ||[inputStream streamStatus] == 7)
{
NSString *myString = ipAddress;
CFStringRef *myCFString = (__bridge CFStringRef)myString;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, myCFString, port, &readStream, &writeStream);
inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
}
}
- (void) disconnect
{
NSLog(#"inside disconnect method");
if (inputStream != nil) {
if ([inputStream streamStatus] == 2) {
NSLog(#"Disconnecting Streams");
[inputStream close];
[outputStream close];
}else {
NSLog(#"Stream is not Open");
int status = [inputStream streamStatus];
NSLog(#"Stream Status is %i", status);
}
}else {
NSLog(#"Input Stream equals Nil");
}
}
#end
To make it long:
Assuming you have class A, B and C.
C needs to be accessible, from both A and B.
Now, let's assume we have controller D, which instantiates both A and B.
Have D instantiate C first, and store it in a variable.
C *C_Class = [[[C alloc] init] autorelease];
Next, instantiate A and B with C (I'm assuming 'retain properties' here)
self.A_Class = [[[A alloc] initWithC:C_Class] autorelease];
self.B_Class = [[[B alloc] initWithC:C_Class] autorelease];
In both classes, you need the instance method:
- (id)initWithC:(C *)C_Class;
and in the .m file:
- (id)initWithC:(C *)C_Class {
C_C = [C_Class retain]; //Assuming a regular instance variable
}
- (void) dealloc {
[C_C release]; //All that is retained, must be released.
}
From this moment on, you have access to that one instance of Class C in classes A and B, via the name 'C_C'.
Now, please mind that this is just written from the back of my head and prone to have errors, but it SHOULD be alright.
I hope it helps :)
Edit: Since the OP seems to have trouble with these code fragments, I'll add a more complete code.
Let's start with the control class 'D'.
D.h:
#import "A.h"
#import "B.h"
#interface D : NSObject
-(void)CreateInstances;
#property (strong, retain) A *A_Class;
#property (strong, retain) B *B_Class;
#end
D.m:
#import "D.h"
#import "C.h"
#implementation D
-(void)CreateInstances {
C *C_Class = [[C alloc] init] autorelease];
self.A_Class = [[[A alloc] initWithC:C_Class] autorelease];
self.B_Class = [[[B alloc] initWithC:C_Class] autorelease];
}
#end
A.h (B.h mirrors this behavior, maybe consider using a superclass for both)
#import "C.h"
#interface A : NSObject {
C *C_Class; //Class Reference to the C-Object
}
-(id) initWithC:(C *)ptr; //Initialization method, which takes a 'C'-Object.
#end;
A.m
#import "A.h"
#implementation A
- (id) initWithC:(C *)ptr {
C_Class = [ptr retain]; //So the object doesn't get released prematurely.
}
- (void) dealloc {
[C_Class release]; //To avoid memory leaks.
}
#end
Now, please remember, that I wrote this off the top of my head and didn't run it through a compiler, but it SHOULD work, save typos and the likes.
Another edit:
After the OP added his own code, I will post relevant bits of 'corrected' code here.
AppDelegate.m
-(void)CreateInstances{
NSLog(#"Inside CreateInstances");
cHub = [[CommunicationHub alloc] init]; //We're using the instance variable. Not the local one.
viewController = [[ViewController alloc] initWithcHub:cHub];
//[viewController initWithcHub:cHub]; //You may want to rethink your function names.
NSLog(#"ID of cHub in AppDelegate is %i", cHub);
}
ViewController.m
//If a method names STARTS with 'init', it SHOULD initialize the object.
-(id) initWithcHub:(CommunicationHub *)ptr
{
self = [super init]; //Calls the 'init' from the parent class.
if(self) {
cHub = [ptr retain]; //Just retain. After all, the object IS initialized already.
NSLog(#"id of cHub in ViewController is %i", cHub);
}
return self;
}
- (void) dealloc {
[cHub release]; //Basic rule of memory management: ALL that is retained, must be released. In dealloc, at latest.
}
- (IBAction)connectSocket:(id)sender
{
//Called by button on UI.
//Do not pass a pointer to anything, unless you mean to use a pointer.
[cHub Connect:[PortNumber.text intValue] ipAddress:(IPAddress.text)];
}
The rest should be somewhat correct, or at least not subject of this question.

EXC_BAD_ACCESS when I change moviePlayer contentURL

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?

Why does my UIWebView not Allow User Interaction?

I'm new to these forums so I apologize for my noobieness. I did as thorough a search as I could, but I couldn't find anyone else with this issue, applogise if this has been covered elsewhere.
I've created a very simple example of my problem. I'm sure I'm missing something but I can't for the life of me figure out what.
I'm creating a UIWebView and adding it to a custom view controller that inherits from UIViewController. When the app loads in the iPad simulator, the uiwebview loads the desired page, but the UIWebView is entirely unresponsive. The webview does not pan or scroll and none of the in page links can be clicked. However, if you change the orientation of the webview suddleny everything works.
Thanks in advance for your help!!
AppDelegate header
#import <UIKit/UIKit.h>
#import "EditorViewController.h"
#interface FixEditorTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
EditorViewController *editorView;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) EditorViewController *editorView;
#end
AppDelegate Implementation
#import "FixEditorTestAppDelegate.h"
#import "EditorViewController.h"
#implementation FixEditorTestAppDelegate
#synthesize window;
#synthesize editorView;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"application is loading");
editorView = [[EditorViewController alloc] init];
[window addSubview:[editorView view]];
[window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[window release];
[editorView release];
[super dealloc];
}
#end
View Controller header
#import <UIKit/UIKit.h>
#interface EditorViewController : UIViewController <UIWebViewDelegate> {
UIWebView *webView;
}
#property (nonatomic, retain) UIWebView *webView;
#end
View Controller Implementation
#import "EditorViewController.h"
#implementation EditorViewController
#synthesize webView;
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
NSLog(#"loadView called");
UIView *curView = [[UIView alloc] init];
webView = [[UIWebView alloc] init];
webView.frame = CGRectMake(20, 40, 728, 964);
webView.delegate = self;
webView.backgroundColor = [UIColor redColor];
[curView addSubview: webView];
self.view = curView;
[curView release];
}
//Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"viewDidLoad called");
NSURL *url = [[NSURL alloc] initWithString:#"http://www.nytimes.com"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[webView loadRequest:request];
[url autorelease];
[request release];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
- (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 {
webView.delegate = nil;
[webView release];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
You should really be loading this from a nib, but if you're going to create it programmatically, you probably want to add this to loadView:
webView.userInteractionEnabled = YES;
webView.scalesPageToFit = YES;
I'm going to go out on a limb here, as you aren't getting much response..
There is nothing wrong with this code (out on a limb! i haven't tested it). Neither is there anything wrong with not using a .nib (but really, you would have to have a reason, right?).
Using a nib doesn't do anything magic, just pretty much what you have done here.
Your problem must be elsewhere.. can you interact with a different kind of view? A button, say? Maybe it is something to do with the window setup?
The issue is with the extra UIView you have in there. It isn't needed, and I think the touch events aren't getting enabled. I tried out the code and it didn't work like you said. Then I changed the EditorViewController to this, and it works now (all I did was to remove the extra UIView) dragging and select links now works.
- (void)loadView {
NSLog(#"loadView called");
webView = [[UIWebView alloc] init];
webView.frame = CGRectMake(20, 40, 728, 964);
webView.delegate = self;
webView.backgroundColor = [UIColor redColor];
self.view = webView;
}