I'm trying to incorporate a colorpicker into my app. I've copied over the KZColorPicker library into my project from https://github.com/alexrestrepo/KZColorPicker
The problem is that the library apparently was created without using ARC. I'm using ARC so I got a ton of errors, which I then commented out all the release statements that were erroring.
After instantiating the "KZDefaultColorViewController", it will get to the ViewDidLoad statement but give me a "EXC_BAD_ACCESS code=1" error. Any ideas???
Here's my IBAction that initiates the colorpicker screen:
- (IBAction)selectColor1:(id)sender
{
DebugLog(#"Change Color 1 Intiated");
// Use this code to push to the color picker
KZDefaultColorViewController *pickerController = [self.storyboard instantiateViewControllerWithIdentifier:#"ColorViewController"];
pickerController.navigationItem.title = #"Choose Color 1";
[self.navigationController pushViewController:pickerController animated:YES];
}
Then it goes to KZDefaultColorViewController's ViewDidLoad where it seems I get the EXC_BAD_ACCESS error:
- (void)viewDidLoad {
[super viewDidLoad];
KZColorPicker *picker = [[KZColorPicker alloc] initWithFrame:self.view.frame];
picker.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
picker.selectedColor = self.selectedColor;
picker.oldColor = self.selectedColor;
[picker addTarget:self action:#selector(pickerChanged:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:picker];
}
I converted this project to arc after removing the line about [_window release]; and fixing the IS_IPAD definition to just be 0 for now, without issue. (via the Edit menu, under Refactor, convert to Arc)
If you copied some of the project to your own, the error is probably due to either not implementing the KZDefaultColorControllerDelegate properly, or you're missing the pickerChanged: method in your code.. or not converting to arc first. Commenting out release statements won't necessarily fix all arc issues.
Related
I have a custom UIImagePickerController that works nicely, only I am facing one issue that I feel should be fairly simple - I just have yet to figure out the solution.
Upon touching my custom added "photo" button, I have it targeted to the build in takePicture method of the UIIPC. Here is my code
#interface CustomCameraController ()
#end
#implementation CustomCameraController {
CGFloat width, height;
}
- (instancetype)init {
if (self = [super init]) {
width = self.view.frame.size.width, height = self.view.frame.size.height;
self.allowsEditing = YES;
self.sourceType = UIImagePickerControllerSourceTypeCamera;
self.showsCameraControls = NO;
self.toolbarHidden = YES;
[self buildCameraOverlay];
}
return self;
}
- (void)buildCameraOverlay {
UIView *customOverlay = [UIView alloc] ...
// ... Custom overlay setup done here
_takePhoto = [[CustomButton alloc] initWithFrame:CGRectMake(0, 0, heightBottomBar*.5, heightBottomBar*.5)];
_takePhoto.center = CGPointMake(bottomBar.frame.size.width/2, bottomBar.frame.size.height/2);
[_takePhoto setImage:[UIImage imageNamed:#"camera button icon"] forState:UIControlStateNormal];
[_takePhoto addTarget:self action:#selector(takePicture) forControlEvents:UIControlEventTouchUpInside];
[bottomBar addSubview:_takePhoto];
// ...
self.cameraOverlayView = customOverlay;
}
This is done in my custom controller CustomCameraController init call.
The problem is, upon taking the picture via takePicture, the camera shutter goes off, everything works just fine, but the controller dismisses itself. I'm trying to figure out how to stop it from closing immediately after taking the picture, so I can A)present the taken picture, and B) give the user the option to choose the image or cancel and retake another one (returning to the camera)
If anyone knows why this happens or something that I am missing / doing incorrectly please let me know. I'm sure it's a simple answer - just can't seem to figure it out. Thanks!
The most common reason for such a weird behaviour is usually lack of delegate methods (for UIImagePickerController in this case) or their wrong implementation.
i cannot seem to get this right. ive looked at several tutorials with no luck. i realize it is a simple task, which is why i am so confused on why it isnt working for me.
i have a programmatically made button inside an expanding cell and when you press it, it is suppose to access the camera to take a picture. i have this code:
- (void)buttonPressed:(UIButton *)button {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[picker setDelegate:self];
//picker.allowsImageEditing = NO;
[self presentModalExpandingCell:picker animated:YES];
picker.showsCameraControls = YES;
}
the error appears in line 5. and says "no visible #interface for 'ExpandingCell' declares the selector 'presentModalExpandingCell:animated:'" i have "" in the .h file so i have no idea what to do.
any help will be greatly appreciated. thanks in advance.
Have you declared the method "presentModalExpandingCell" in your class? Because, if not, that is why the compiler is throwing that error.
I have been developing in Objective-C for two months, so I am quite new to this language and iOS environment. I am updating to iOS7 an app that is working fine for iOS6.
I am getting the next error when a modal view with a web view inside is presented, only in iOS7 and this is working in iOS6. There is a URL request inside but I cannot find what is causing the error.
'-[__NSMallocBlock__ absoluteURL]: unrecognized selector sent to instance 0x16e8b020'
This is the viewWillAppear method on the modal view controller:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.webView.request) {
//THE NEXT LINE THROWS THE ERROR
NSURLRequest *req = [[NSURLRequest alloc] initWithURL:self.initialURL];
[self.webView loadRequest:req];
}
}
Maybe I am doing something silly but really now I do not know where to look at.
If anyone has experienced something like that before, I will appreciate some help. Thanks in advance.
EDIT:
#interface MyViewController ()
#property (copy, nonatomic) NSURL *initialURL;
#end
#implementation MyViewController
- (id)initWithURL:(NSURL *)initialURL
{
self = [super init];
if (self) {
_initialURL = initialURL;
_webView = [[UIWebView alloc] init];
_webView.backgroundColor = [UIColor clearColor];
_webView.opaque = NO;
_webView.delegate = self;
[self.view addSubview:_webView];
self.modalPresentationStyle = UIModalPresentationFormSheet;
self.view.backgroundColor = [UIColor whiteColor];
}
return self;
}
Method call:
self.modalWebViewController = [[[MyViewController alloc] initWithURL:url] autorelease];
I assume that iOS calls absoluteURL on the self.initialURL object passed to the initWithURL: method. However, the object receiving this message is an NSMallocBlock, so there seems to be something wrong. I assume that your self.initialURL object should be of type NSURL. If so, this would indicate a memory management problem causing the pointer of self.initalURL to point to somewhere else in memory (not to the object you want it to point to).
You could try to run your app with NSZombiesEnabled which prevents any objects from being actually deallocated and instead warns you if a deleted object is still accessed.
You can activate NSZombies in the scheme to run your app (click on the name of your app in Xcode's toolbar on the upper right and choose "Edit Scheme..." from the pop-up menu). In the run-configuration in the "Diagnostics" tab there is a checkbox for activating Zombie objects.
- (void)fadeOutSplash {
UIImageView *splash = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default-Landscape~ipad.png"]];
[self.window.rootViewController.view addSubview:splash]; // <-- OBJECT IS BEING RETAINED HERE
[UIView animateWithDuration:0.5
animations:^{
splash.alpha = 0;
}
completion:^(BOOL finished) {
[splash removeFromSuperview];
}];
}
I think ARC is retaining my "splash" when I add it to the subview of the rootViewController. ARC should release "splash" when I run my animation completion because it removes my "splash" from it's own super view. However, I can see in the allocation instruments that this parent view controller is staying allocated and it shows the problem line being where splash is added to the rootViewController. What can I do to make sure "splash" is released?
I fixed this problem, but I'm not exactly sure how.. Here's the likely solution:
- (void)removeFromSuperView
{
// Use this space to manually release any non IB pointers / variables as needed
self.someDictionaryIMadeInInit = nil;
while(self.subviews.count > 0) [[self.subviews objectAtIndex:0] removeFromSuperView];
[super removeFromSuperView];
}
This a little trick I came up with for ARC related views. I recommend it more as a last resort because truly this should be solved the appropriate way, but it's worth a try to save you from tearing out your hair!
I am presenting a modal view controller which contains a UIScrollView with a bunch of images. When I dismiss my modal view controller I can see in my Allocations (instruments) that memory assigned to the images is hanging around but not causing leaks.
Causing me some confusion and any help would be great. Here is what I have...
UIViewController - DollViewController: This is my main view controller that I am presenting my modal over. Here is the code -
-(IBAction)openDollCloset {
NSLog(#"Open Closet");
[self playSound:#"soundMenuClick"];
ClosetViewController *closet = [[ClosetViewController alloc] initWithNibName:#"ClosetViewController" bundle:nil];
closet.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentModalViewController: closet animated: YES];
closet.delegate = self;
closet.addToCloset = NO;
[closet setCurrentDoll:myDoll];
[closet openCloset];
[closet release];
[self closeSubmenu];
}
I create my scrollview manually to hold the outfit images.
The object closetScroller is defined with #property (nonatomic, retain) UIScrollView *closetScroller; with a release in dealloc.
- (void)setScrollerValues {
if (closetScroller == nil)
{
self.closetScroller = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 400)];
[self.closetScroller setDecelerationRate:UIScrollViewDecelerationRateFast];
[self.closetScroller setDelegate:self];
[self.closetScroller setPagingEnabled:YES];
[self.closetScroller setShowsHorizontalScrollIndicator:NO];
[self.view addSubview:closetScroller];
}
[self.closetScroller setContentSize:CGSizeMake(outfitCount * 320, 400)];
}
After creating the scrollView I add the images to the scroller. I believe I am releasing everything right. I am creating the images with NSData objects and releasing them.
- (void)addOutfitsToScroller {
// Clear out any old images in case we just deleted an outfit
if ([[closetScroller subviews] count] > 0)
{
CATransition *fade = [CATransition animation];
[fade setDelegate:self];
[fade setType:kCATransitionReveal];
[fade setSubtype:kCATransitionFromRight];
[fade setDuration:0.40f];
[[self.closetScroller subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
[[closetScroller layer] addAnimation:fade forKey:#"FadeButtons"];
}
// Set the pageControl to same number of buttons
[pageControl setNumberOfPages:outfitCount];
// Load the outfit image and add it to the scroller
for (int i = 0; i < outfitCount; i++)
{
NSArray *savedDataArray = [[NSArray alloc] initWithArray:[closetItemsArray objectAtIndex:i]];
UIImageView *v = [[UIImageView alloc] initWithFrame:CGRectMake(320*i, 0, 320, 400)];
[v setUserInteractionEnabled:NO];
[v setAlpha:0.40f];
NSData *imageData = [[NSData alloc] initWithContentsOfFile:[savedDataArray objectAtIndex:1]];
UIImage *outfitImage = [[UIImage alloc] initWithData:imageData];
UIImageView *closetImage = [[UIImageView alloc] initWithImage:outfitImage];
[imageData release];
[outfitImage release];
[savedDataArray release];
CGSize frameOffset;
#ifdef LITE_VERSION
frameOffset = CGSizeMake(40, 60);
#else
frameOffset = CGSizeMake(20, 10);
#endif
closetImage.frame = CGRectOffset(closetImage.frame, frameOffset.width , frameOffset.height);
[v addSubview:closetImage];
[closetImage release];
[self.closetScroller addSubview:v];
[v release];
}
}
This all works great. Then when the user selects the "Close" button or selects an outfit I call:
[self.delegate closeClosetWindow];
Which calls the delegate method in the parentViewController which simply makes this call:
[self dismissModalViewControllerAnimated:YES];
I have also tried calling dismissModalViewControllerAnimated:YES from the modal view controller itself. It simply forwards the message to it's parentViewController and closes the modal just the same as the first way. Neither makes a difference with regards to the memory.
So what I do instead is use this method to close the view:
[[self.closetScroller subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
[self dismissModalViewControllerAnimated:YES];
When I do that, I can see my Object Allocations decrease in Instruments. Prior to opening the closet view I have object alloc at about 1.85mb. When I open the closet it increases to 2.5 or so depending on how many outfit images are loaded into the UIScrollView. Then when I close the view without the above method it stays at 2.5 and increases the next time I open it. Although when using the above method that removes the outfit images from the scroller, my object alloc drops back down close the the 1.85mb. Maybe a little more which tells me it's hanging on to some other stuff also.
Also note that when looking at the object allocations, I do see the ClosetViewController object created and when I close the modal it's refrence is released. I can see it malloc and free the view as I open and close it. It's not retaining the view object itself. i'm so confused.
Not sure what to do here. I am not getting any leaks and I am releasing everything just fine. Any ideas would be great.
mark
I Noticed object alloc in instruments keeping a live reference to UIScrollView every time I opened modal window. So to fix, when allocating for my scrollview, I instead allocated a new UIScrollView object and assigned it to closetScroller and then released. This took care of the problem
I think you were simply not releasing closetScroller in the dealloc of your view controller.