UIImageView switching setContentMode random EXEC_BAD_ACCESS - iphone

I'm using an UIImageView and UIScrollView inside UIViewController to show images. Actual Size and Fit to Screen options available at the toolbar to let user switch between modes. While switching between modes I am getting EXEC_BAD_ACCESS error randomly. Randomly means I can switch to Actual Size mode to Fit to Screen modes copule of times. When I hit one of them randomly application crashes.
Here is the code that I am using if it wont help I may post the h and m files.
-(void)loadImage{
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:imgFilePath];
imageView.image = [UIImage imageWithData: [NSData dataWithContentsOfFile:filePath]];
imgLoaded = 1;
}
-(void)FitToScreen{
if(imgLoaded<1) [self loadImage];
if(currentState != STATE_IMGPLAYER_FULLSCREEN ){
currentState = STATE_IMGPLAYER_FULLSCREEN;
//[imageView setContentMode:UIViewContentModeCenter];
[imageView setContentMode:UIViewContentModeScaleToFill];
CGSize photoSize = imageView.frame.size;
[scrollView setContentSize:photoSize];
}
//
}
-(void)ActualSize{
if(currentState != STATE_IMGPLAYER_ACTUAL_SIZE){
currentState = STATE_IMGPLAYER_ACTUAL_SIZE;
[imageView setContentMode:UIViewContentModeTopLeft];
[scrollView setContentMode:UIViewContentModeCenter];
CGSize photoSize = [imageView.image size];
[scrollView setContentSize:photoSize];
}
}
-(IBAction)info_clicked:(id)sender
{
UIButton *button = (UIButton *)sender;
if ([button tag] == BTN_FIT2SIZE) {
[Button setEnabled:NO];
[Button2 setEnabled:YES];
[self ActualSize];
} else if ([button tag] == BTN_FIT2SCREEN) {
[Button setEnabled:YES];
[Button2 setEnabled:NO];
[self FitToScreen];
}
[button release];
}
Console Msg:
Program received signal: “EXC_BAD_ACCESS”.
Thanks for your help.

A first quick guess is that maybe you aren't retaining the imageView or its image? If you could post your stack trace and maybe the line where it crashes, it would be useful.

Related

Change frame of cancel button in UISearchBar

I have the following code to change the appearance of the UISearchBar in my application and it can be seen in the image below also:
for(int i = 0; i < [[searchBar subviews] count]; i++){
UIView *subView = [[searchBar subviews] objectAtIndex:i];
if([[NSString stringWithFormat:#"%#", [subView class]] isEqualToString:#"UINavigationButton"]){
UIButton *cancelButton = (UIButton *)subView;
CGRect buttonFrame = cancelButton.frame;
buttonFrame.size.height = 52;
[cancelButton setFrame:buttonFrame];
[cancelButton setTitle:#"Cancel" forState:UIControlStateNormal];
[cancelButton setBackgroundImage:[UIImage imageNamed:#"cancel.png"] forState:UIControlStateNormal];
[cancelButton setBackgroundImage:[UIImage imageNamed:#"cancel_pressed.png"] forState:UIControlStateHighlighted];
}
}
As you can see I am trying to change the height of the button contained in the UISearchBar with no luck. I do get reference to the button as I can change the text and the background Image is changed just not the height of the frame. I would just like the height of the button to be the same as the search box at 52px.
EDIT:
I have found a really hacky solution, but it's not very elegant of adding a UIButton as the subview of the Cancel Button. It does the job but as I say it's not very nice.
Actually you could use method below to access the cancel Button:
UIBarButtonItem *cancelButton = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
So I override -layoutSubViews with this, but theres 2 issues I have
I hate iterating through the views to find the matching view, and it messes up the animation a little bit
- (UIButton *)cancelButton {
for (UIView *v in self.subviews) {
if ([v isKindOfClass:[UIButton class]]) {
NSString *caption = [[((UIButton *)v) titleLabel] text];
if ([caption isEqualToString:#"Cancel"] )
return (UIButton *)v;
}
}
return nil;
}
- (BOOL)cancelButtonIsShowing {
return ([self cancelButton] != nil);
}
- (void)layoutSubviews {
[super layoutSubviews];
if ([self cancelButtonIsShowing]) {
UIButton *cancelButton = [self cancelButton];
UIImage *i = [UIImage imageNamed:#"Cancel_BTN"];
CGRect f = CGRectMake(267, 5, i.size.width, i.size.height);
cancelButton.frame = f;
}
}

set iphone wallpaper with array of buttons objective c

Hi. I am developing an app and I would like to set the background in the app itself.
Now I created an array of buttons using a for loop and setting tags, but for some reason when I click the buttons nothing happens.
This is where the buttons are created:
-(void)showSettings {
[[objc_getClass("DreamBoard") sharedInstance] hideAllExcept:mainView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.5];
if(toggled){
photos = [[NSArray arrayWithObjects:
[UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/Images/Wallpapers/Wallpaper1.png"],
[UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/Images/Wallpapers/Wallpaper2.png"],
[UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/Images/Wallpapers/Wallpaper3.png"],
[UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/Images/Wallpapers/Wallpaper4.png"],
nil] retain];
w=0;
for ( UIImage *image in photos )
{
for (l = 0; l<(int)photos.count; l++)
{
wallpaperButton = [[UIButton alloc] initWithFrame:CGRectMake(5,130+150*w,150,150)];
wallpaperButton.tag = l;
[wallpaperButton setImage:image forState:UIControlStateNormal];
[wallpaperButton addTarget:self action:#selector(setWallpaper) forControlEvents:UIControlEventTouchDown];
[settingsMenu addSubview: wallpaperButton];
[wallpaperButton release];
}
w++;
}
Here is the function to set the wallpaper:
-(void)setWallpaper {
UIImageView *bgView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
if ([wallpaperButton tag] == 1) {
bgView.image = [UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/Images/Wallpapers/Wallpaper1.png"];
}
else if ([wallpaperButton tag] == 0) {
bgView.image = [UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/Wallpapers/Wallpaper2.png"];
}
else if ([wallpaperButton tag] == 2) {
bgView.image = [UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/ Wallpapers/Wallpaper3.png"];
}
else if ([wallpaperButton tag] == 3) {
bgView.image = [UIImage imageWithContentsOfFile:#"/var/mobile/Library/iZoon/Wallpapers/Wallpaper4.png"];
}
[mainView insertSubview:bgView atIndex:0];
[bgView release];
}
Now the buttons display correctly but they don't do anything.
Any help is appreciated. Thanks.
Add an NSLog statement to see if the setWallpaper method is being called. If it is, then i think this might be a fix:
If you just add the images to your XCode Project, you can just get them by their name. Make sure you check the "copy files to project folder if needed" box when you drag the images into the project. Then to get the image you can just do this:
if ([wallpaperButton tag] == 1) {
bgView.image = [UIImage imageNamed:#"Wallpaper1.png"];
}
.
.
.
[self.view addSubview:bgView];
Also, you should be aware that unless your app is hiding the status bar (the one with the battery and clock) then your images should actually have a height of 460 because 20px are used up by that.

How to customize Buttons in UIActionSheet?

I want to change the image of the buttons of UIActionSheet, I have images for each button, and I want each button show the image I want. I searched the web I found a lot of answers but they didn't work.
Here is the initialization of the UIActionSheet
-(IBAction)showActionSheet:(id)sender {
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:#"title" delegate:self cancelButtonTitle:#"Cancel Button" destructiveButtonTitle:nil otherButtonTitles:#"Other Button 1", #"Other Button 2", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleDefault;
[popupQuery showInView:self.view];
[popupQuery release];
}
I create a subclass CustomActionSheet derived UIActionSheet, and implement a method called customizeGUI.
I use CustomActionSheet like UIActionSheet, except I must call method customizeGUI of subclass in willPresentActionSheet delegate:
- (void)willPresentActionSheet:(UIActionSheet *)actionSheet {
if ([actionSheet isKindOfClass:[CustomActionSheet class]]) {
CustomActionSheet *sheet = (CustomActionSheet*)actionSheet;
[sheet customizeGUI];
}
}
(CustomActionSheet.m)
- (void)customizeGUI {
UIImageView *imgvwBackground = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bg_actionsheet.png"]];
CGRect rect = self.bounds;
imgvwBackground.frame = rect;
[self insertSubview:imgvwBackground atIndex:0];
[imgvwBackground release];
int buttonIndex = 0;
UIImage *imgButtonDestructive = [UIImage imageNamed:#"btn_actionsheet_destructive.png"];
UIImage *imgButtonCancel = [UIImage imageNamed:#"btn_actionsheet_cancel.png"];
UIImage *imgButtonNormal = [UIImage imageNamed:#"btn_actionsheet_normal.png"];
for (UIView *sub in self.subviews) {
NSString *className = [NSString stringWithFormat:#"%#", [sub class]];
if ( ([className isEqualToString:#"UIThreePartButton"]) //iOS 4
|| ([className isEqualToString:#"UIAlertButton"]) ) { //iOS 5
rect = sub.frame;
sub.hidden = YES;
UIButton *btn = [[UIButton alloc] initWithFrame:rect];
UIImage *imgForButton = nil;
if (buttonIndex == self.cancelButtonIndex) {
imgForButton = imgButtonCancel;
}
else if (buttonIndex == self.destructiveButtonIndex) {
imgForButton = imgButtonDestructive;
}
else {
imgForButton = imgButtonNormal;
}
NSString *sTitle = [self buttonTitleAtIndex:buttonIndex];
btn.titleLabel.font = [UIFont boldSystemFontOfSize:19];
[btn setBackgroundImage:imgForButton forState:UIControlStateNormal];
[btn setTitle:sTitle forState:UIControlStateNormal];
btn.tag = buttonIndex;
[btn addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
[btn release];
buttonIndex++;
}
}
}
- (void)buttonClicked:(id)sender {
UIButton *btn = sender;
if ([self.delegate respondsToSelector:#selector(actionSheet:clickedButtonAtIndex:)]) {
[self.delegate actionSheet:self clickedButtonAtIndex:btn.tag];
}
[self dismissWithClickedButtonIndex:btn.tag animated:YES];
}
Hope this way can help you and give you an idea to customize UIActionSheet
If you change these sizes, not only might you make your application less usable, but that may violate Apple's Human Interface Guidelines, leading to a rejection of your application when submitted.
Here is the example how to use UiActionsheet by Apple
Looks like you'll just have to create your own class. I'd look into subclassing either UIView or UIActionSheet. There are those PSD things around that you can get the images you'll need, pending copyright.
EDIT: If you do end up creating your own class, and its any good, consider uploading it to http://cocoacontrols.com/

message sent to deallocated instance issue

I have been debugging the following issue for the past couple hours and can't seem to come up with a good conclusion.
-[NSIndexPath row]: message sent to deallocated instance 0x506cf90
I am implementing a swipe recognizer on each cell on the UITableView. Whenever a swipe is detected, the code below will be called. What it does is to show/hide a subview in the cell. If the subview already shows then it hides, otherwise it shows. If a subview is already shown on cell 5 and a swipe is detected on cell 3 then we remove that subview first then add the subview on cell 3.
I tried the code below and it seems to works with some cells. However, there is a cell particularly at the bottom of the UITableView in which if I try to hide the subview it gives me the error above. It works just perfectly fine for the other cell, just cells at the bottom. Why is this?
The code is as follows:
- (void)swipe:(UISwipeGestureRecognizer *)recognizer direction:(UISwipeGestureRecognizerDirection)direction
{
if (recognizer && recognizer.state == UIGestureRecognizerStateEnded)
{
// Get the table view cell where the swipe occured
CGPoint location = [recognizer locationInView:self.table];
NSIndexPath* indexPath = [self.table indexPathForRowAtPoint:location];
ConvoreCell* cell = (ConvoreCell *) [self.table cellForRowAtIndexPath:indexPath];
[self.table beginUpdates];
NSLog(#"ROW is %d", global.row);
//removing the options view at the other cell before adding a new one
if (global != nil && global.row != indexPath.row){
[sideSwipeView removeFromSuperview];
[sideSwipeView release];
sideSwipeView = nil;
}
//options already exist, we need to remove it
if (sideSwipeView != nil){
[sideSwipeView removeFromSuperview];
[sideSwipeView release];
sideSwipeView = nil;
slide = NO;
} else {
//options do not exist and therefore we need to add it
NSArray * buttonData = [[NSArray arrayWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:#"Mark Read", #"title", #"mark.png", #"image", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"Track", #"title", #"play.png", #"image", nil],
[NSDictionary dictionaryWithObjectsAndKeys:#"Leave", #"title", #"delete.png", #"image", nil],
nil] retain];
NSMutableArray * buttons = [[NSMutableArray alloc] initWithCapacity:buttonData.count];
sideSwipeView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.frame.size.height-25, 320, 25)];
[sideSwipeView setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin];
[sideSwipeView setBackgroundColor:[UIColor colorWithPatternImage: [UIImage imageNamed:#"dotted-pattern.png"]]];
[sideSwipeView setTag:-10];
CGFloat leftEdge = BUTTON_LEFT_MARGIN;
for (NSDictionary* buttonInfo in buttonData)
{
if (!([[buttonInfo objectForKey:#"title"] isEqualToString:#"Mark Read"] && [[[groups objectAtIndex:indexPath.row] unread] intValue] == 0))
{
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
UIImage* buttonImage = [UIImage imageNamed:[buttonInfo objectForKey:#"image"]];
if ([[[groups objectAtIndex:indexPath.row] tracked] intValue] == 1 && [[buttonInfo objectForKey:#"title"] isEqualToString:#"Track"]){
buttonImage = [UIImage imageNamed:#"pause.png"];
[button setSelected:YES];
} else
[button setSelected:NO];
button.frame = CGRectMake(leftEdge, 0, buttonImage.size.width, buttonImage.size.height);
UIImage* grayImage = [self imageFilledWith:[UIColor colorWithWhite:0.9 alpha:1.0] using:buttonImage];
[button setImage:grayImage forState:UIControlStateNormal];
if ([[buttonInfo objectForKey:#"title"] isEqualToString:#"Mark Read"]){
[button addTarget:self action:#selector(markRead:) forControlEvents:UIControlEventTouchUpInside];
} else if ([[buttonInfo objectForKey:#"title"] isEqualToString:#"Track"]){
[button addTarget:self action:#selector(track:) forControlEvents:UIControlEventTouchUpInside];
} else if ([[buttonInfo objectForKey:#"title"] isEqualToString:#"Leave"]){
[button addTarget:self action:#selector(leave:) forControlEvents:UIControlEventTouchUpInside];
}
[button setTag:indexPath.row];
[buttons addObject:button];
[sideSwipeView addSubview:button];
leftEdge = leftEdge + buttonImage.size.width + BUTTON_SPACING;
}
}
[cell.contentView addSubview:sideSwipeView];
[buttons release];
[buttonData release];
global = indexPath;
slide = YES;
}
[self.table endUpdates];
[self.table deselectRowAtIndexPath:indexPath animated:YES];
}
}
Now the issue here is that the pointer to indexPath somehow got deallocated. I was able to get around this by making a copy of the indexPath instead of just having a reference to the pointer. So I did:
global = [indexPath copy];
for some reason after this method is called it deallocates indexPath and I am not sure who does it.. I think iOS does it... is it true?
NSIndexPath* indexPath = [self.table indexPathForRowAtPoint:location];
That returns an autoreleased instance. So, yes, your assignment to global needs to retain the object. copy effectively returns a retained instance.
Don't leak, though. If you just do:
global = [indexPath copy];
And you don't release the original value of global first, you'll leak.
Oh, and: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

UIButton doesn't interact in UIScrollView

I have a windowed (e.g. not a full-screen) UIScrollView (inside a UIView) which scrolls through groups of UIImageViews with UIButtons on them (the idea being you click the button to do something with the displayed image). The UIButton does take any touch events - how can I fix it?
I've read this, this, this, this and this - but I either don't understand the answer or its implications, or it's not really relevant.
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
Sentence *testSentence = [[managedObjectContext executeFetchRequest:request error:&error] objectAtIndex:i];
//NSLog(#"testSentence: %#", testSentence);
//NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", i];
//Your going to need to optimise this by creating another thumbnail image to use here.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *imageName = [[paths objectAtIndex:0] stringByAppendingPathComponent:[testSentence image]];
//NSLog(#"imageName: %#", imageName);
UIImage *image = [[UIImage alloc] initWithContentsOfFile:imageName];
//NSLog(#"image: %#", image);
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
//NSLog(#"imageView: %#", imageView);
[imageView setContentMode:UIViewContentModeScaleAspectFit];
[imageView setBackgroundColor:[UIColor blackColor]];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
imageView.frame = rect;
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTitle:#"Play" forState:UIControlStateNormal];
aButton.frame = CGRectMake(10, 10, 70, 70);
[aButton setUserInteractionEnabled:YES];
[aButton setEnabled:YES];
[aButton setAlpha:1];
UIView *buttonWrapperUIView = [[UIView alloc] init];
[aButton addTarget:self action:#selector(clickPlay:) forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:aButton];
[imageView bringSubviewToFront:aButton];
[scrollView1 addSubview:imageView];
NSLog(#"aButton %#", aButton);
[image release];
[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
try
[imageView setUserInteractionEnabled:YES]