edit 2
I found out it depends on the method used. I somehow lose the appdelegate pointer when I access it via scrollViewDidEndDecelerating instead of awakeFromNib. But I do need to use scrollViewDidEndDecelerating.
Can someone of you please fix this?
Works fine
- (void)awakeFromNib
{
AppDelegate *mainDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"%#", [NSString stringWithFormat:#"%#", mainDelegate.content1]);
}
Crashes bad_access to mainDelegate.content1
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
AppDelegate *mainDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"%#", [NSString stringWithFormat:#"%#", mainDelegate.content1]);
}
ORIGINAL QUESTION (I keep this for past-reference. Just read the above functions)
This problem regards stringWithContentsOfURL
The code below works, downloads HTMLstring to mainDelegate.content1 and shows it appropriately in UIWebView controller.myWebView. If I modify the function, so that I conduct the downloading process beforehand, let it be somewhere in AppDelegate.m, the program crashes upon processing mainDelegate.content1 in this very function.
Here goes the good code
- (void)ReloadView:(int)page{
MyViewController *controller = [viewControllers objectAtIndex:pageControl.currentPage];
mainDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSError * error;
NSURL * Tmpurl;
NSString *tmpContent;
NSString *urlAddress;
urlAddress = mainDelegate.TitleStrP1;
Tmpurl = [NSURL URLWithString:urlAddress];
tmpContent = [NSString stringWithContentsOfURL:Tmpurl encoding:NSUTF8StringEncoding error:&error];
maindelegate.content1 = [NSString stringWithString:tmpContent];
[controller.myWebView loadHTMLString:mainDelegate.content1 baseURL:nil];
}
And here what I am trying to do and what doesn't work. SomeFunction executes upon startup of the app. I checked the loaded value after downloading HTMLstring into content1 from the Internet site and html code indeed is there.
- (void)ReloadView:(int)page{
MyViewController *controller = [viewControllers objectAtIndex:pageControl.currentPage];
mainDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
//code had been removed here
[controller.myWebView loadHTMLString:mainDelegate.content1 baseURL:nil];
}
-(void)SomeFunction{
NSError * error;
NSURL * Tmpurl;
NSString *tmpContent;
NSString *urlAddress;
urlAddress = mainDelegate.TitleStrP1;
Tmpurl = [NSURL URLWithString:urlAddress];
tmpContent = [NSString stringWithContentsOfURL:Tmpurl encoding:NSUTF8StringEncoding error:&error];
maindelegate.content1 = [NSString stringWithString:tmpContent];
}
Your help is appreciated.
Thanks
EDIT:
AppDelegate.h
#import <UIKit/UIKit.h>
#class ContentController,MyViewController;
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
...
NSString *content1;
NSString *content2;
}
...
#property (nonatomic, strong) NSString * content1;
#property (nonatomic, strong) NSString * content2;
AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
content1 = [NSString stringWithString:#""];
content2 = [NSString stringWithString:#""];
NSError * error;
NSURL * Tmpurl;
NSString *tmpContent;
NSString *urlAddress;
urlAddress = TitleStrP1;
Tmpurl = [NSURL URLWithString:urlAddress];
tmpContent = [NSString stringWithContentsOfURL:Tmpurl encoding:NSUTF8StringEncoding error:&error];
content1 = [NSString stringWithString:tmpContent];
urlAddress = TitleStrP2;
Tmpurl = [NSURL URLWithString:urlAddress];
tmpContent = [NSString stringWithContentsOfURL:Tmpurl encoding:NSUTF8StringEncoding error:&error];
content2 = [NSString stringWithString:tmpContent];
...
}
Is your "Content1" property in the appDelegate using "strong"? Also, to use properties, you should be using lower class as the setter needs to capitalize the variable name (setContent1). That is
#property (nonatomic, strong) NSString *content1;
EDIT:
[[UIApplication sharedApplication] delegate] will always work. By bad, you did not say if there is a value there or not (that is, is it nil). So one of these is happening.
1) your AppDelegate object is getting released and dealloced. I'm not sure how you would do this but its possible.
2) You have told UIApplication to create a delegate in main.m, in the fourth parameter of "UIApplicationMain()", but have also specified a NIB in your .plist file and that nib ALSO has a AppDelegate object in it and is wired to the UIApplication as a delegate. If you are using a NIB the property attribute for AppDelegate better be STRONG as its not retained by the UIApplication (it says this in the delegate property of UIApplication).
3) If the "delegate" property is nil, then someone has set it to nil.
Think about it - the UIApplication delegate gets set very early, otherwise you would never get the launched message.
So you need to add a "dealloc" method to your app delegate and log if that happens. You can also add a simple "init" method that also logs when AppDelegate is created - then see if my suspicion is correct.
Related
I am integrating Instagram into my application using the instagram-ios-sdk. I can successfully login to Instagram and obtain an access token, but after that when I am try to post a picture using UIDocumentInteractionController from UIImagePickerController, the image is not posting. The code to send a picture is given below:
(void)_startUpload:(UIImage *) image {
NSLog(#"Image Object = %#",NSStringFromCGSize(image.size));
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Test.igo"];
[UIImageJPEGRepresentation(image, 1.0) writeToFile:jpgPath atomically:YES];
NSLog(#"file url %#",jpgPath);
NSURL *igImageHookFile = [[NSURL alloc] init];
igImageHookFile = [NSURL fileURLWithPath:jpgPath];
NSLog(#"File Url = %#",igImageHookFile);
documentInteractionController.UTI = #"com.instagram.photo";
[UIDocumentInteractionController interactionControllerWithURL:igImageHookFile];
[self setupControllerWithURL:igImageHookFile usingDelegate:self];
[documentInteractionController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
}
(UIDocumentInteractionController *) setupControllerWithURL: (NSURL*) fileURL usingDelegate: (id <UIDocumentInteractionControllerDelegate>) interactionDelegate {
NSLog(#"%#",fileURL);
UIDocumentInteractionController *interactionController =
[UIDocumentInteractionController interactionControllerWithURL: fileURL];
interactionController.delegate = interactionDelegate;
return interactionController;
}
I converted the image to .ig format, with a resolution of (612 *612). But still the image is not posting on Instagram. Am I missing something? Can any one help me with this?
Thanks
First off, in your code, you're not assigning the return value of setupControllerWithURL: usingDelegate: to an object, so that method isn't actually accomplishing anything, just creating a new instance of UIDocumentInteractionController and discarding it.
Secondly, from the documentation:
"Note that the caller of this method needs to retain the returned object."
You're not retaining the document controller (or assigning it to a strongly referenced property in the case of ARC) from what I can tell.
Try this -
In your #interface:
#property (nonatomic, strong) UIDocumentInteractionController *documentController;
In your #implementation:
self.documentController = [UIDocumentInteractionController interactionControllerWithURL:igImageHookFile];
self.documentController.delegate = self;
self.documentController.UTI = #"com.instagram.photo";
[self.documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
Also, the line NSURL *igImageHookFile = [[NSURL alloc] init]; is unnecessary because in the next line igImageHookFile = [NSURL fileURLWithPath:jpgPath]; you're creating a new instance and discarding the first one. Just use NSURL *igImageHookFile = [NSURL fileURLWithPath:jpgPath];
I have a UIButton in a nib (xib) that id like to play a sound when touched, what protocol needs to be followed to make this happen?
** overhauled question** Throughout my time here on Stack Overflow, i've learned a lot, and not just about what i'm usually needing help with (Objective-C, xCode), but with how Stack Overflow works. I find it to be a vast wealth of information and support and i've looked at how i've asked this question before and it made absolutely no sense at all. To help future users, i've edited what I was originally asking for, in a way others can understand like Naveen did below. Apologies
Add this framework
AudioToolBox framework
Include this header file .h file
#include <AudioToolbox/AudioToolbox.h>
CFURLRef soundFileURLRef;
SystemSoundID soundFileObject;
Add this code in viewdidLoad
NSURL *tapSound = [[NSBundle mainBundle] URLForResource: #"Voice035"
withExtension: #"amr"];
// Store the URL as a CFURLRef instance
self.soundFileURLRef = (CFURLRef) [tapSound retain];
// Create a system sound object representing the sound file.
AudioServicesCreateSystemSoundID (
soundFileURLRef,
&soundFileObject
);
On Button Tap, Call this method
AudioServicesPlayAlertSound (soundFileObject);
Do release in dealloc
AudioServicesDisposeSystemSoundID (soundFileObject);
CFRelease (soundFileURLRef);
For more info : http://developer.apple.com/library/ios/#documentation/AudioToolbox/Reference/SystemSoundServicesReference/Reference/reference.html#//apple_ref/c/func/AudioServicesCreateSystemSoundID
I would say, create an 'Observer' class that plays the sound that all buttons are connected to. I'll give an example below, It is a singleton class. It's written on a whim, and not tested but gives you an idea.
//SoundObserver.h
#include <AVFoundation/AVFoundation.h>
#interface SoundObserver {
AVAudioPlayer *audioPlayer;
}
-(void)playSound;
+(SoundObserver*)sharedInstance;
#property (nonatomic, retain) AVAudioPlayer *audioPlayer;
#end
//SoundObserver.m
static SoundObserver *instance = nil;
#implementation SoundObserver
-(id)init {
self = [super init];
if(self) {
//Get path to file.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"sound"
ofType:#"wav"];
// filePath to URL
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
//Initialize the AVAudioPlayer.
self.audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
// Preloads buffer and prepare for use.
[self.audioPlayer prepareToPlay];
[filePath release];
[fileURL release];
}
}
+(SoundObserver*)sharedInstance {
#synchronized(self) {
if (instance == nil)
instance = [[self alloc] init];
}
return instance;
}
-(void)playSound {
//make sure the audio resets to beginning each activation.
[self.audioPlayer play];
}
-(void)dealloc {
//Clean up
[self.audioPlayer release];
self.audioPlayer = nil;
[super dealloc];
}
// User example.
In applicationDidFinishLaunching:
[SoundObserver sharedInstance];
From here you can connect all buttons to the same function, or call it from anywhere in the App that #import's SoundObserver.h
-(IBOutlet)buttonClick:(id)sender {
[[SoundObserver sharedInstance] playSound];
}
I have a database with 10 tables. As I need to access this database in different view controllers, I have to declare the two methods shown below in each of them. Is there a way I can avoid this by declaring these methods in the application delegate. If yes, how can I go about using these methods in different classes.
- (NSString *) getWritableDBPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:DATABASE_NAME];
}
-(void)createEditableCopyOfDatabaseIfNeeded
{
// Testing for existence
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:DATABASE_NAME];
NSLog(#"%#",writableDBPath);
success = [fileManager fileExistsAtPath:writableDBPath];
if (success)
return;
// The writable database does not exist, so copy the default to
// the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:DATABASE_NAME];
success = [fileManager copyItemAtPath:defaultDBPath
toPath:writableDBPath
error:&error];
if(!success)
{
NSAssert1(0,#"Failed to create writable database file with Message : '%#'.",
[error localizedDescription]);
}
}
in your view controller first of all create a delegate variable
YourAppDelegate *appDelegate=(YourAppDelegate *)[[UIApplication sharedApplication]delegate];
then u can call any methods that you have define in your delegate
like [appDelegate methodName];
This just screams to be implemented as a separate controller with class level methods. I would highly recommend creating a Database controller with a definition like so:
#interface DatabaseController: NSObject
+ (NSString *) getWritableDBPath ;
+ (void) createEditableCopyOfDatabaseIfNeeded ;
#end
Then in your code using it as so:
#import "DatabaseController.h"
NSString * somePath = [DatabaseController getWritableDBPath];
[DatabaseController createEditableCopyOfDatabaseIfNeeded];
Set them as public, so you can call them with [ ]
You just need to change the minus for +
+(void)createEditableCopyOfDatabaseIfNeeded;
You will need to define a protocol for this class and add a variable of that protocol to the member variable of this class as follows:
The classes where the object is created can either call this method using the object. The Best option is to use the app delegate class to implement these methods.
You can then assign the objects's delegate as the app delegate and call the methods.
#protocol mySqlDelegate ;
#interface mySqlClass {
id <mySqlDelegate> delegate;
}
#property (nonatomic, assign) id <mySqlDelegate> delegate;
#end
#protocol mySqlDelegate
- (void) delegateMethodsForThisClass;
#end
first create a common instance for appdelegate.
otherwise in constant.h file create a instance like
mAppDelegate=(YourAppDelegate*)[[UIApplication sharedApplication] ];
then just import constant.h and you may use mAppdelegate anywhere so using this you easily call
Hey guys, I'm receiving a SIGABRT when trying to use an instance variable for anything but an NSLOG :
//Class_X.H
#interface MeldingController : UIViewController
{
NSString *refURLAsString;
}
#property (nonatomic, retain) NSString *refURLAsString;
//Class_X.M
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
self.refURLAsString = [info objectForKey:UIImagePickerControllerReferenceURL];
NSLog(#"%#",self.refURLAsString);//Successfully outputs the ReferenceURL string
}
-(void)function_abc
{
NSLog(#"%#",self.refURLAsString);//Successfully outputs the ReferenceURL string
NSURL *URL = [NSURL URLWithString:self.refURLAsString]; //SIGABRT
//Or even trying to make another string using refUrlAsString
NSString *string = [[NSString alloc]init];
string = self.refURLAsString;//SIGABRT
}
iPhone Simulator iOS version 4.3, Xcode 4.
Any ideas anyone? cheers.
Your refURLAsString is of type NSString *, but [info objectForKey:UIImagePickerControllerReferenceURL] should return a NSURL * instance according to the docs. You want:
self.refURLAsString = [[info objectForKey:UIImagePickerControllerReferenceURL] absoluteString];
The reason why the NSLog works is because it calls the description method on each object that is to be printed via the %# sequence, and that does return a string. But refURLAsString is pointing to a NSURL instead of a NSString, and that makes [NSURL URLWithString:self.refURLAsString]; crash.
try this
string =[refURLAsString copy];
Your code is screwing up refURLAsString. I can't tell you how from the posted code. Activate NSZombieEnabled for details.
Not sure exactly whats the issue is, but try string = [NSString stringWithFormat:#"%#",self.refURLAsString]; and see if it crashes here too
NSString *string = [NSString stringWithFormat:#"%#",self.refURLAsString];
no need to alloc here
I am having a crash I do not understand. I am downloading a couple files from a remote server, and when a file has finished downloading, I am attempting to retrieve an object that was attached to the request object.
Tia for any help!
S.
Main Class
for (TrainingEntry* _entry in objects) {
HTTPRequest * request = [HTTPRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#/%#", [[ConfigLoader config] objectForKey:#"Server"], _entry.url]]];
[request setDownloadDestinationPath:[NSString stringWithFormat:#"%#/%#", documentsDirectoryPath, _entry.filename]];
[request setEntry:_entry];
[request setRaw:_entry.title];
TrainingEntry * test = (TrainingEntry*)[request _entry];
NSLog(#"title: %#", [test title]); //<= This works
NSLog(#"filename: %#", [test filename]); //<= This works
[[self networkQueue] addOperation:request];
}
// Start Queue
[[self networkQueue] go];
...
- (void)requestFinished:(HTTPRequest *)request {
if ([[self networkQueue] requestsCount] == 0) {
[self setNetworkQueue:nil];
}
NSLog(#"req: %#", [request raw]);
NSLog(#"title: %#", [[request entry] title]); // <= This works
NSLog(#"filename: %#", [[request entry] filename]); // <= This crashes
}
HTTPRequest Object
#interface HTTPRequest : ASIHTTPRequest {
}
#property (nonatomic, retain) TrainingEntry * entry;
#property (nonatomic, retain) NSString * raw;
#end
TrainingEntry Class
#interface TrainingEntry : NSObject {
NSString * title;
NSString * filename;
}
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSString * filename;
Something that may be giving you trouble is not having copy in your property declaration. You should consider using copy for all objects that conform to the NSCopying protocol specification, especially NSString and other collection classes.
In the past, changing retain to copy for an NSString property solved a similar issue for me.
edit: some research
This post may help clarify why you should use copy over retain for immutable objects.
When a crash occurs, there will be a backtrace.
Post it.
Either your program will break in the debugger, and the call stack will be in the debugger UI (or you can type 'bt
With that, the cause of the crash is often quite obvious. Without that, we are left to critique the code.
If this crashes:
NSLog(#"filename: %#", [[request entry] filename]); // <= This crashes
It is either because request has been over-released and is no longer viable or because filename is returning a garbage object. Given that request worked previously, it is likely that filename has been over-released.
Where do you set filename?