reading a value from preferences - objective-c

I have just recently implemented the inAppSettings kit. My goal was to load my default view and then add a navigation bar button item to the right called "settings". Once the user pressed the settings button it would take them to my settings bundle where they would make a choice to which website they wanted, and then press back which would load up my default view once again with webview loaded once again with the new url.
I have implemented everything that I just described above but once the selection is made within the settings and the user presses back (aka dismisses the settings view to go back to the default view), the app crashes and I have no idea why. My code is below and if anyone knows why this is happening, it would be much appreciated. Let it be noted that once I run the app again after it crashes, the website loads correctly based on the settings they chose before it crashed.
P.S. the options the user can click to select are: Google, stackoverflow.
ERROR Message: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Upcoming settingsViewControllerDidEnd:]: unrecognized selector sent to instance 0x281c70'
Thank you in advance
- (IASKAppSettingsViewController*)appSettingsViewController {
if (!appSettingsViewController) {
appSettingsViewController = [[IASKAppSettingsViewController alloc] initWithNibName:#"IASKAppSettingsView" bundle:nil];
appSettingsViewController.delegate = self;
}
return appSettingsViewController;
}
-(IBAction)selectSettings {
UINavigationController *aNavController = [[UINavigationController alloc] initWithRootViewController:self.appSettingsViewController];
//[viewController setShowCreditsFooter:NO]; // Uncomment to not display InAppSettingsKit credits for creators.
// But we encourage you not to uncomment. Thank you!
self.appSettingsViewController.showDoneButton = YES;
[self presentModalViewController:aNavController animated:YES];
[aNavController release];
}
-(NSDictionary *)intialDefaults {
NSArray *keys = [[[NSArray alloc] initWithObjects:kPicture, nil] autorelease];
NSArray *values= [[[NSArray alloc] initWithObjects: #"none", nil] autorelease];
return [[[NSDictionary alloc] initWithObjects: values forKeys: keys] autorelease];
}
-(void)setValuesFromPreferences {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults registerDefaults:[self intialDefaults]];
NSString *picturePreference= [userDefaults stringForKey:kPicture];
if([picturePreference isEqualToString:#"google"]) {
[self getUpcoming:#"http://www.google.ca"];
} else
if ([picturePreference isEqualToString:#"stackoverflow"]) {
[self getUpcoming:#"http://www.stackoverflow.com"];
} else {
[self getUpcoming:#"http://www.yahoo.com"];
}
}
-(void)getUpcoming:(id) hello {
NSURL *url= [NSURL URLWithString:hello];
NSURLRequest *requestURL= [NSURLRequest requestWithURL:url];
[web loadRequest:requestURL];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
web.hidden=NO;
[spinner stopAnimating];
[load_message dismissWithClickedButtonIndex:0 animated:TRUE];
pic1.hidden=YES;
}
-(void) loadMethod {
load_message = [[UIAlertView alloc] initWithTitle:#"Loading..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
spinner= [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(135.0, 60.0);
[load_message addSubview:spinner];
[load_message show];
[spinner startAnimating];
[self performSelector:#selector(setValuesFromPreferences) withObject:nil afterDelay:0.0];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIBarButtonItem *settingButton= [[UIBarButtonItem alloc]
initWithTitle:#"Settings"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(selectSettings)];
self.navigationItem.rightBarButtonItem = settingButton;
web.hidden=YES;
pic1.hidden=NO;
}
- (void) viewDidAppear:(BOOL)animated {
[self loadMethod];
}

Do you implement the InAppSettingKit delegate? Add this to your current class above
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController *)sender
{
// dismiss the view here
[self dismissModalViewControllerAnimated:YES];
// do whatever you need to do
}

Related

Tab bar Controller and Facebook Connect Issues Xcode 4.3 IOS 5.1

I am trying to connect to the facebook and take the users name and picture, so far i can connect and fetch user name . i have a working code can be downloaded from here (single view application)
But if i put a tab bar controller to the code, it can not receive a response from facebook.
I add a tabbar controller programatically like below code
in app.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Regular Code
/*self.viewController = [[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
*/
//Tab bar controller code
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
UIViewController *viewController1 = [[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil] autorelease];
self.rootController = [[[UITabBarController alloc] init] autorelease];
self.rootController.viewControllers = [NSArray arrayWithObjects:viewController1, nil];
self.window.rootViewController = self.rootController;
[self.window makeKeyAndVisible];
return YES;
}
// This method will be used for iOS versions greater than 4.2.
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[_viewController facebook] handleOpenURL:url];
}
If i put a breaking point at line handleOpenurl In NSUrl there is this= fbAPPID://authorize/#access_token=BABABSbbsabsbabb
I guess access_token means i have succesfully loged in . So tab bar doesnt block me to login put blokcs my facebook methods in Viewcontroller.m
Without tab bar all methods in Viewcontroller.m works great when i add tab bar and breakpoints none of the facebook methods below works. I dont get any errors though.
-(void)request:(FBRequest *)request didLoad:(id)result
-(void)fbDidLogin
ViewController.m
#import "ViewController.h"
#import "FBConnect.h"
#import "Facebook.h"
#implementation ViewController
#synthesize btnLogin;
#synthesize btnPublish;
#synthesize lblUser;
#synthesize actView;
#synthesize facebook;
#synthesize permissions;
#synthesize isConnected;
#synthesize imageView;
// The alert view that will be shown while the game will upload to facebook.
UIAlertView *msgAlert;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
-(void)checkForPreviouslySavedAccessTokenInfo{
// Initially set the isConnected value to NO.
isConnected = NO;
// Check if there is a previous access token key in the user defaults file.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] &&
[defaults objectForKey:#"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
// Check if the facebook session is valid.
// If it’s not valid clear any authorization and mark the status as not connected.
if (![facebook isSessionValid]) {
[facebook authorize:nil];
isConnected = NO;
}
else {
isConnected = YES;
}
}
}
-(void)setLoginButtonImage{
UIImage *imgNormal;
UIImage *imgHighlighted;
UIImageView *tempImage;
// Check if the user is connected or not.
if (!isConnected) {
// In case the user is not connected (logged in) show the appropriate
// images for both normal and highlighted states.
imgNormal = [UIImage imageNamed:#"LoginNormal.png"];
imgHighlighted = [UIImage imageNamed:#"LoginPressed.png"];
}
else {
imgNormal = [UIImage imageNamed:#"LogoutNormal.png"];
imgHighlighted = [UIImage imageNamed:#"LogoutPressed.png"];
}
// Get the screen width to use it to center the login/logout button.
// We’ll use a temporary image view to get the appopriate width and height.
float screenWidth = [UIScreen mainScreen].bounds.size.width;
tempImage = [[UIImageView alloc] initWithImage:imgNormal];
[btnLogin setFrame:CGRectMake(screenWidth / 2 - tempImage.frame.size.width / 2, btnLogin.frame.origin.y, tempImage.frame.size.width, tempImage.frame.size.height)];
// Set the button’s images.
[btnLogin setBackgroundImage:imgNormal forState:UIControlStateNormal];
[btnLogin setBackgroundImage:imgHighlighted forState:UIControlStateHighlighted];
// Release the temporary image view.
[tempImage release];
}
-(void)showActivityView{
// Show an alert with a message without the buttons.
msgAlert = [[UIAlertView alloc] initWithTitle:#"My test app" message:#"Please wait..." delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[msgAlert show];
// Show the activity view indicator.
actView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0.0, 0.0, 40.0, 40.0)];
[actView setCenter:CGPointMake(160.0, 350.0)];
[actView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:actView];
[actView startAnimating];
}
-(void)stopShowingActivity{
[actView stopAnimating];
[msgAlert dismissWithClickedButtonIndex:0 animated:YES];
}
-(void)saveAccessTokenKeyInfo{
// Save the access token key info into the user defaults.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Set the permissions.
// Without specifying permissions the access to Facebook is imposibble.
permissions = [[NSArray arrayWithObjects:#"read_stream", #"publish_stream", nil] retain];
// Set the Facebook object we declared. We’ll use the declared object from the application
// delegate.
facebook = [[Facebook alloc] initWithAppId:#"331327710279153" andDelegate:self];
// Check if there is a stored access token.
[self checkForPreviouslySavedAccessTokenInfo];
// Depending on the access token existence set the appropriate image to the login button.
[self setLoginButtonImage];
// Specify the lblUser label's message depending on the isConnected value.
// If the access token not found and the user is not connected then prompt him/her to login.
if (!isConnected) {
[lblUser setText:#"Tap on the Login to connect to Facebook"];
}
else {
// Get the user's name from the Facebook account.
[facebook requestWithGraphPath:#"me" andDelegate:self];
}
// Initially hide the publish button.
[btnPublish setHidden:YES];
}
- (void)viewDidUnload
{
[self setBtnLogin:nil];
[self setLblUser:nil];
[self setBtnPublish:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
// Keep this just for testing purposes.
NSLog(#"received response");
}
-(void)request:(FBRequest *)request didLoad:(id)result{
// With this method we’ll get any Facebook response in the form of an array.
// In this example the method will be used twice. Once to get the user’s name to
// when showing the welcome message and next to get the ID of the published post.
// Inside the result array there the data is stored as a NSDictionary.
if ([result isKindOfClass:[NSArray class]]) {
// The first object in the result is the data dictionary.
result = [result objectAtIndex:0];
}
// Check it the “first_name” is contained into the returned data.
if ([result objectForKey:#"first_name"]) {
// If the current result contains the "first_name" key then it's the user's data that have been returned.
// Change the lblUser label's text.
[lblUser setText:[NSString stringWithFormat:#"Welcome %#!", [result objectForKey:#"first_name"]]];
// Show the publish button.
[btnPublish setHidden:NO];
}
else if ([result objectForKey:#"id"]) {
// Stop showing the activity view.
[self stopShowingActivity];
// If the result contains the "id" key then the data have been posted and the id of the published post have been returned.
UIAlertView *al = [[UIAlertView alloc] initWithTitle:#"My test app" message:#"Your message has been posted on your wall!" delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[al show];
[al release];
}
}
-(void)request:(FBRequest *)request didFailWithError:(NSError *)error{
NSLog(#"%#", [error localizedDescription]);
// Stop the activity just in case there is a failure and the activity view is animating.
if ([actView isAnimating]) {
[self stopShowingActivity];
}
}
-(void)fbDidLogin{
// Save the access token key info.
[self saveAccessTokenKeyInfo];
// Get the user's info.
[facebook requestWithGraphPath:#"me" andDelegate:self];
}
-(void)fbDidNotLogin:(BOOL)cancelled{
// Keep this for testing purposes.
//NSLog(#"Did not login");
UIAlertView *al = [[UIAlertView alloc] initWithTitle:#"My test app" message:#"Login cancelled." delegate:self cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[al show];
}
-(void)fbDidLogout{
// Keep this for testing purposes.
//NSLog(#"Logged out");
// Hide the publish button.
[btnPublish setHidden:YES];
}
- (IBAction)LoginOrLogout {
// If the user is not connected (logged in) then connect.
// Otherwise logout.
if (!isConnected) {
[facebook authorize:permissions];
// Change the lblUser label's message.
[lblUser setText:#"Please wait..."];
}
else {
[facebook logout:self];
[lblUser setText:#"Tap on the Login to connect to Facebook"];
}
isConnected = !isConnected;
[self setLoginButtonImage];
}
- (IBAction)Publish {
// Show the activity indicator.
[self showActivityView];
// Create the parameters dictionary that will keep the data that will be posted.
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
#"My test app", #"name",
#"http://www.google.com", #"link",
#"FBTestApp app for iPhone!", #"caption",
#"This is a description of my app", #"description",
#"Hello!\n\nThis is a test message\nfrom my test iPhone app!", #"message",
nil];
// Publish.
// This is the most important method that you call. It does the actual job, the message posting.
[facebook requestWithGraphPath:#"me/feed" andParams:params andHttpMethod:#"POST" andDelegate:self];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc {
[btnLogin release];
[lblUser release];
[btnPublish release];
[actView release];
[facebook release];
[permissions release];
[super dealloc];
}
#end
I am confused how can i make this tab bar controlling working.
I have changed the design
Now Login view is displayed first then it continues to real app which has tab bar controller.
Issue was _viewcontroller facebook , when _viewcontroller has been called it was not returning any thing
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[_viewController facebook] handleOpenURL:url];
}
So I changed my code(especially _viewcontroller line) to below code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
UIViewController * viewController1 = [[[VoteMe alloc] initWithNibName:#"VoteMe" bundle:nil] autorelease];
UIViewController *viewController2 = [[[PostController alloc] initWithNibName:#"PostController" bundle:nil] autorelease];
UIViewController *viewController3 = [[[FriendsController alloc] initWithNibName:#"FriendsController" bundle:nil] autorelease];
UIViewController *viewController4 = [[[Responses alloc] initWithNibName:#"Responses" bundle:nil] autorelease];
UIViewController *viewController5 = [[[User alloc] initWithNibName:#"User" bundle:nil] autorelease];
self.rootController = [[[UITabBarController alloc] init] autorelease];
self.rootController.viewControllers = [NSArray arrayWithObjects:viewController1,viewController2,viewController3,viewController4,viewController5, nil];
self.window.rootViewController = self.rootController;
[self.window makeKeyAndVisible];
loginView=[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
[self.window addSubview:loginView.view];
return YES;
}
// This method will be used for iOS versions greater than 4.2.
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[loginView facebook] handleOpenURL:url];
}
It works fine

Add custom UIButton to UIKeyboard's accessory view for a UIWebView

I need to add a camera button to a UIWebView's keyboard accessory view toolbar (the one that already has the "Back|Next" and "Done" buttons).
Is there an easy way to do this?
I'm still looking for a better way to do it, but one solution for the moment would be to destroy the bar and recreate it like so :
- (void)viewDidLoad
{
[super viewDidLoad];
UIWebView *web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
NSURL *aURL = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *aRequest = [NSURLRequest requestWithURL:aURL];
[web loadRequest:aRequest];
[self.view addSubview:web];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[self performSelector:#selector(removeBar) withObject:nil afterDelay:0];
}
- (void)removeBar {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
// iOS 5 sticks the UIWebFormView inside a UIPeripheralHostView.
if ([[possibleFormView description] rangeOfString:#"UIPeripheralHostView"].location != NSNotFound) {
for (UIView *subviewWhichIsPossibleFormView in [possibleFormView subviews]) {
if ([[subviewWhichIsPossibleFormView description] rangeOfString:#"UIWebFormAccessory"].location != NSNotFound) {
UISegmentedControl *nav = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Previous",#"Next", nil]];
nav.momentary = YES;
nav.frame = CGRectMake(5, 8, 120, 30);
nav.segmentedControlStyle = UISegmentedControlStyleBar;
nav.tintColor = [UIColor colorWithWhite:0.25 alpha:1];
[nav addTarget:self action:#selector(navigate) forControlEvents:UIControlEventValueChanged];
UIBarButtonItem *pictureBtn =[[UIBarButtonItem alloc] initWithTitle:#"Picture" style:UIBarButtonItemStyleBordered target:self action:#selector(takePic:)];
UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyboard)];
NSArray *buttons = [NSArray arrayWithObjects:flexButton,pictureBtn,flexButton,doneButton, nil];
[(UIToolbar *)subviewWhichIsPossibleFormView addSubview:nav];
[(UIToolbar *)subviewWhichIsPossibleFormView setItems:buttons];
}
}
}
}
}
But then, you have to implement the previous, next and done function again. But it's not the hardest part.
there is an easier way to do this.
Keep your keyboard notification in your viewDidLoad
After that all you will need is the following method:
-(void)keyboardDidShow:(NSNotification*)notif
{
NSArray *array = [[UIApplication sharedApplication] windows];
for (UIWindow* wind in array) {
for (UIView* currView in wind.subviews) {
if ([[currView description] hasPrefix:#"<UIPeripheralHostView"]) {
for (UIView* perView in currView.subviews) {
if ([[perView description] hasPrefix:#"<UIWebFormAccessory"]) {
UIBarButtonItem *doneBttn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyBoard)];
NSMutableArray *arr = [[NSMutableArray alloc] initWithArray: [(UIToolbar *) perView items]];
[arr addObject:doneBttn];
[(UIToolbar *) perView setItems:arr];
}
}
}
}
}
}
I have basically taken the original prev/next buttons from the UIWebFormAccessory and added a done button to the end of it, but you can add what ever buttons you want to this.
Some may think this shouldn't be implemented in -(void)keyboardDidShow: because you are changing the UI after it displays on screen, but so far I haven't noticed any issues with this. (only tested in simulator)
Hope this was useful!

Xcode Unrecognized Selector Error

I've been having a ton of issues with this section of an app that I'm writing, I'm sure people here are getting sick of me so I'm going to try and solve all my questions in this post. I'm working on an app that behaves like a photo gallery, and I'm implementing the option to have the user delete photos from their gallery. To accomplish this, I decided to place an invisible button over each picture. When the user hits an "Edit" button, the hidden delete buttons over each picture become active. I'm using the same IBOutlet over each of the hidden buttons for simplicity, and I've tagged each button appropriately in Interface Builder. When the user taps the button over the picture, an alert view appears asking if they really want to delete it. If they click yes, I call removeObjectAtIndex and delete the image from the UI. But, when I click "Yes" in the alert view, I get an error from Xcode stating:
2012-04-04 11:26:40.484 AppName[608:f803] -[UIButton setImage:]: unrecognized selector sent to instance 0x6a922c0
2012-04-04 11:26:40.485 AppName[608:f803] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton setImage:]: unrecognized selector sent to instance 0x6a922c0'*
I've been trying to figure out what is causing this for a few hours now to no avail. I'm not setting the image of a UIButton anywhere in my code. I did in IB, but I simply set the buttons types to Custom so that they appear invisible. I will post my entire file below, I can't find any issues in my code, so any help is much appreciated! Thanks.
EDIT Here is the current version of the code:
- (IBAction)grabImage {
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
_popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
[_popover presentPopoverFromRect:self.imageView.bounds inView:self.imageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else {
[self presentModalViewController:imgPicker animated:YES];
}
[self.imgPicker resignFirstResponder];
}
// Sets the image in the UIImageView
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
if (imageView.image == nil) {
imageView.image = img;
self.array = [NSMutableArray arrayWithObject:[NSData dataWithData:UIImagePNGRepresentation(imageView.image)]];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
if (imageView2.image == nil) {
imageView2.image = img;
NSLog(#"The image is a %#", imageView);
[self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView2.image)]];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
if (imageView3.image == nil) {
imageView3.image = img;
[self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView3.image)]];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
if (imageView4.image == nil) {
imageView4.image = img;
[self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView4.image)]];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Photo Gallery", #"Photo Gallery");
self.tabBarItem.image = [UIImage imageNamed:#"42-photos.png"];
}
return self;
}
////start of saving////
- (void)applicationDidEnterBackground:(UIApplication*)application {
NSLog(#"Image on didenterbackground: %#", imageView);
self.array = [NSMutableArray arrayWithObject:[NSData dataWithData:UIImagePNGRepresentation(imageView.image)]];
[self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView2.image)]];
[self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView3.image)]];
[self.array addObject:[NSData dataWithData:UIImagePNGRepresentation(imageView4.image)]];
[self.user setObject:self.array forKey:#"images"];
[user synchronize];
}
- (void)viewDidLoad
{
self.user = [NSUserDefaults standardUserDefaults];
NSLog(#"It is %#", self.user);
self.array = [[self.user objectForKey:#"images"]mutableCopy];
imageView.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:0]];
imageView2.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:1]];
imageView3.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:2]];
imageView4.image = [[UIImage alloc] initWithData:[self.array objectAtIndex:3]];
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:app];
backToGalleryButton.hidden = YES;
tapToDeleteLabel.hidden = YES;
deleteButton1.hidden = YES;
[super viewDidLoad];
}
///// shows the hidden and invisible "delete" button over each photo.
- (IBAction)editButtonPressed:(id)sender {
grabButton.hidden = YES;
editButton.hidden = YES;
backToGalleryButton.hidden = NO;
tapToDeleteLabel.hidden = NO;
deleteButton1.hidden = NO;
}
////
// This is when the user taps on the image to delete it.
- (IBAction)deleteButtonPressed:(id)sender {
NSLog(#"Sender is %#", sender);
UIAlertView *deleteAlertView = [[UIAlertView alloc] initWithTitle:#"Delete"
message:#"Are you sure you want to delete this photo?"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
[deleteAlertView show];
int imageIndex = ((UIButton *)sender).tag;
deleteAlertView.tag = imageIndex;
}
- (void)alertView: (UIAlertView *) alertView
clickedButtonAtIndex: (NSInteger) buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex]) {
NSLog(#"User Clicked Yes. Deleting index %d of %d", alertView.tag, [array count]);
NSLog(#"The tag is %i", alertView.tag);
[self.array removeObjectAtIndex: alertView.tag];
NSLog(#"After deleting item, array count = %d", [array count]);
NSLog(#"Returned view is :%#, in view: %#", [self.view viewWithTag:alertView.tag], self.view);
((UIImageView *)[self.view viewWithTag:alertView.tag]).image =nil;
}
[self.user setObject:self.array forKey:#"images"];
}
Update: I added breakpoints, and discovered that ((UIImageView *)[self.view viewWithTag:alertView.tag]).image =nil; is the line that is causing the crash, I still can't figure out why though.
I don't see setImage: being called in any of that code you pasted into your question, but I can tell you this: UIButton's setImage method actually requires a button state as a second parameter.
e.g.
[UIButton setImage: forState:]
I've linked Apple's documentation for you.
If your calls to setImage: don't have a second parameter, that would explain the "unrecognized selector error" you're seeing.
This is an extension to #MichaelDautermann , who makes a very good point that a UIButton has a setImage:forState: method, but no setImage method. However, you ARE calling set image. Not on a button, but when you say imageView.image and imageView2.image. This invokes the setter method for the image view. I would set a breakpoint (or use NSLog and the %# item) to ensure that imageView is in fact an imageView and not a button. If it somehow changed from under you, this could be causing the issue. Simply set a break point at those two lines and see if you even make it past them.
Additionally, if Xcode isn't popping you over to which line is actually causing the issue, check your crash logs. Symbolicated, the log will give you the line number. Or, a less direct approach would be to set breakpoints at the ends of the methods you provided in your answer, and see how many you get past. Once you crash, you can narrow down which method is causing you grief, and then start setting break points within the method until you get to the line in question.
UPDATE:
You said in the comments that ((UIImageView *)[self.view viewWithTag:alertView.tag]).image =nil is what you have, but self.view is a UIControl. Changing the cast won't affect the result. Is the UIImageView whose image you are trying to delete a subview of a UIControl? If not, you're never going to get the image view back from viewWithTag. Generally, self.view refers to a view controller's view, so if you're getting a UIControl, my assumption is either your whole view is a UIControl, or you're doing this in the wrong class. Which class are you doing this in, and what is it a subclass of? It appears you are doing this in a view controller, but I just want to be sure. And again, in either case (UIControl or UIImageView), neither class responds to setImage.

Action sheet getting caught on tabbar

This is a tricky one that I've been working on for a while. I have a an action sheet that appears in a view with a tabbar, sometimes when I dismiss the action sheet it gets "caught" in the tabbar and am unable to do anything.The app doesn't crash because if i minimize it and then come back in it is dimissed, it just appears that the modal behavior isn't being dismissed properly.
I recently changed how the action sheet is displayed from "showInView" to "showFromTabBar" and am not sure if this is creating the issue.
Thanks,
William
Edit:
Below is the code I use to dismiss my actionsheet:
-(void)doneButtonPressed:(id)sender{
if ([[self viewWithTag:1] isKindOfClass:[PickerView class]]) {
PickerView *picker = (PickerView *)[self viewWithTag:1];
if (picker.selectedRow == nil) {
[picker populateSelectRowForRow:0 andComponent:0];
}
NSNotification *note = [NSNotification notificationWithName:#"doneButtonPressed" object:self.indexPath userInfo:picker.selectedRow];
[[NSNotificationCenter defaultCenter] postNotification:note];
}else {
DatePickerView *picker = (DatePickerView *)[self viewWithTag:1];
NSDictionary *extraInfo = [[NSDictionary alloc] initWithObjects:[[NSArray alloc] initWithObjects:[self formatDateToString:[picker date]], nil] forKeys:[[NSArray alloc] initWithObjects:#"value", nil]];
NSNotification *note = [NSNotification notificationWithName:#"doneButtonPressed" object:self.indexPath userInfo:extraInfo];
[[NSNotificationCenter defaultCenter] postNotification:note];
}
[self dismissWithClickedButtonIndex:0 animated:YES];
}
and the notification method that is called:
-(void)pickerUpdate:(NSNotification *)note{
NSIndexPath *indexPath = [note object];
NSDictionary *extraInfo = [note userInfo];
NSDictionary *dict = [[tableController.sectionAndFields objectAtIndex:indexPath.section] objectAtIndex:(indexPath.row + kHeaderAndFooterOffset)];
[tableController.formDetails setObject:[extraInfo objectForKey:#"value"] forKey:[dict objectForKey:#"key"]];
NSArray *reloadArray = [[NSArray alloc] initWithObjects:indexPath, nil];
[indexPath release];
[self.tv reloadRowsAtIndexPaths:reloadArray withRowAnimation:NO];
[reloadArray release];
}
I did manage to solve this however it feels very much like a hack, I introduced a delay into the code using:
[self performSelector:#selector(dismissFromActionSheet) withObject:nil afterDelay:0.2];
With dismissFromActionSheet being:
-(void)dismissFromActionSheet{
[self dismissWithClickedButtonIndex:0 animated:YES];
}

Exception with TabBar in iPhone SDK

A friend gave me a small tutorial to iPhone programming yesterday.
I then tried to make a small program with two views which I can switch using a TabBar: One with a blue background, one with a red one.
It displays them just fine, but when I run it (in the Simulator) and click on a Tab, it crashed with :
"Terminating app due to uncaught
exception
'NSInvalidArgumentException', reason:
'*** -[NSMachPort
_tabBarItemClicked:]: unrecognized selector sent to instance 0x38223e0"
I didn't manage to find the bug so far... Have you got any ideas ? :)
Code from DemoAppDelegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after application launch
[window makeKeyAndVisible];
UIColor *color = [UIColor blueColor];
DemoAppViewController *controller1 = [[DemoAppViewController alloc] initWithColor:color];
color = [UIColor redColor];
DemoAppViewController *controller2 = [[DemoAppViewController alloc] initWithColor:color];
[controller1 updateBackground];
[controller2 updateBackground];
UITabBarController *tbcontroller = [[UITabBarController alloc] init];
NSMutableArray *array = [NSMutableArray arrayWithObjects: controller1, controller2, nil];
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:#"Blue" image:nil tag:1];
[controller1 setTabBarItem: item];
[item release];
item = [[UITabBarItem alloc] initWithTitle:#"Red" image:nil tag:2];
[controller2 setTabBarItem: item];
[item release];
[tbcontroller setViewControllers:array];
[tbcontroller setSelectedIndex:0];
[window addSubview: [tbcontroller view]];
[tbcontroller release];
[controller1 release];
[controller2 release];
}
Code excerpt from DemoAppViewController:
- (DemoAppViewController *) initWithColor:(UIColor *)color
{
self = [super init];
if (self != nil) {
[color retain];
backgroundColor = color;
}
return self;
}
- (void) updateBackground
{
UIView *view = [self view];
[view setBackgroundColor: backgroundColor];
}
The problem seems to be in this line: [tbcontroller release];
This is deallocating your tbcontroller. I've commented out that line of code and it works. Try making sure to retain your controller somewhere else since apparently adding the subview isn't doing the job. It may also be related to the viewcontroller themselves being released.