Hi im new for iphone application development.i wanna use page controller for my uiscroll view.In single view im using two scroll views and two page controls.i setted pagecontrol with following codings but only for two pages its working fine.but i wanna add more than two pages for a scroll view whic consist of static buttons.![enter image description here][1]
//
// newsampleViewController.m
// newsample
//
// Created by SmartJobDevelopers on 4/3/12.
// Copyright 2012 __MyCompanyName__. All rights reserved.
//
#import "newsampleViewController.h"
#implementation newsampleViewController
#synthesize scr_anger;
#synthesize scr_sketch;
#synthesize pageControl;
#synthesize pageControl1;
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[self setupPage];
//[scr_anger setScrollEnabled:YES];
//[scr_anger setContentSize:CGSizeMake(1290,15)];
//[scr_sketch setScrollEnabled:YES];
//[scr_sketch setContentSize:CGSizeMake(1310,15)];
[super viewDidLoad];
}
-(IBAction)buttonPressed:(id)sender {
i_curtag=(int)[sender tag];
//NSLog(#"%d",i_curtag);
[self fn_btnOperation];
//[self opt:str_filename];
//NSLog(#"str_filename:%#",str_filename);
}
-(void)fn_btnOperation
{
if (i_curtag==1)
{
//str_filename=[NSString stringWithFormat:#"%d.png",i_curtag];
//NSLog(#"str_filename:%#",str_filename);
str_filename=#"1.png";
// NSLog(#"1.png");
}
else if(i_curtag==2)
{
str_filename=#"2.png";
//NSLog(#"2.png");
}
else if(i_curtag==3)
{
str_filename=#"3.png";
//NSLog(#"3.png");
}
else if(i_curtag==4)
{
str_filename=#"4.png";
// NSLog(#"4.png");
}
else if(i_curtag==5)
{
str_filename=#"5.png";
//NSLog(#"5.png");
}
else if(i_curtag==6)
{
str_filename=#"6.png";
//NSLog(#"6.png");
}
else if(i_curtag==7)
{
str_filename=#"7.png";
// NSLog(#"7.png");
}
else if(i_curtag==8)
{
str_filename=#"8.png";
//NSLog(#"8.png");
}
else if(i_curtag==9)
{
str_filename=#"9.png";
// NSLog(#"9.png");
}
else if(i_curtag==10)
{
str_filename=#"10.png";
// NSLog(#"10.png");
}
[self opt:str_filename];
}
-(id)opt:(NSString*)filename
{
//NSLog(#"filename:%#",filename);
str_filename=filename;
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:#""delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Save Image" otherButtonTitles:#"Mail Image",nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[popupQuery showInView:self.view];
[popupQuery release];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex1
{
if (buttonIndex1 == 0)
{
// NSLog(#"str_filename in actionsheet:%#",str_filename);
[self savesingleimage];
// NSLog(#"save");
}
else if (buttonIndex1 == 1)
{
//NSLog(#"str_filename in else:%#",str_filename);
[self fmail];
//NSLog(#"mail");
}
}
-(void)fmail
{
//NSLog(#"str_filename:%#",str_filename);
NSMutableString *emailBody = [[[NSMutableString alloc] initWithString:#"<html><body><p>"] retain];
[emailBody appendString:#"<b><u>EMOTIONAL ICONS</u></b><br><br>"];
[emailBody appendString:#"</p></body></html>"];
MFMailComposeViewController *emailDialog = [[MFMailComposeViewController alloc] init];
UIImage *icon1 = [UIImage imageNamed:str_filename];
NSData *imageData1 = UIImageJPEGRepresentation(icon1, 1);
[emailDialog addAttachmentData:imageData1 mimeType:#"image/jpg" fileName:str_filename];
emailDialog.mailComposeDelegate =self;
[emailDialog setSubject:#"Emotional Icons"];
[emailDialog setMessageBody:emailBody isHTML:YES];
[emailDialog.navigationBar setTintColor:[UIColor blackColor]];
[self presentModalViewController:emailDialog animated:YES];
[emailDialog release];
[emailBody release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Status:" message:#"" delegate:nil cancelButtonTitle:#"ok" otherButtonTitles:nil];
switch (result) {
case MFMailComposeResultCancelled:
alert.message = #"Message Canceled";
break;
case MFMailComposeResultSaved:
alert.message = #"Message Saved";
break;
case MFMailComposeResultSent:
alert.message = #"Message Sent";
break;
case MFMailComposeResultFailed:
alert.message = #"Message Failed";
break;
default:
alert.message = #"Message Not Sent";
break;
}
[self dismissModalViewControllerAnimated:YES];
[alert show];
[alert release];
}
-(void)savesingleimage{
// NSLog(#"str_filename in save: %#",str_filename);
UIImage *image1 = [UIImage imageNamed:str_filename];
UIImageWriteToSavedPhotosAlbum(image1, nil, nil, nil);
UIAlertView *successAlert = [[UIAlertView alloc] initWithTitle:#"Saved"
message:#"Image Saved into PhotoAlbum"
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(110, 170, 50, 50)];
NSString *path = [[NSString alloc] initWithString:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:str_filename]];
UIImage *bkgImg = [[UIImage alloc] initWithContentsOfFile:path];
[imageView setImage:bkgImg];
[bkgImg release];
[path release];
[successAlert addSubview:imageView];
[imageView release];
[successAlert show];
[successAlert release];
}
#pragma mark -
#pragma mark The Guts
- (void)setupPage
{
scr_anger.delegate = self;
scr_sketch.delegate =self;
//[self.scr_anger setBackgroundColor:[UIColor blackColor]];
[scr_anger setCanCancelContentTouches:NO];
[scr_sketch setCanCancelContentTouches:NO];
scr_anger.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scr_anger.clipsToBounds = YES;
scr_anger.scrollEnabled = YES;
scr_anger.pagingEnabled = YES;
scr_sketch.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scr_sketch.clipsToBounds = YES;
scr_sketch.scrollEnabled = YES;
scr_sketch.pagingEnabled = YES;
self.pageControl.numberOfPages = 2;
self.pageControl1.numberOfPages = 2;
[scr_anger setScrollEnabled:YES];
[scr_sketch setScrollEnabled:YES];
[scr_anger setContentSize:CGSizeMake(1290,15)];
[scr_sketch setContentSize:CGSizeMake(1940,15)];
}
#pragma mark -
#pragma mark UIScrollViewDelegate stuff
- (void)scrollViewDidScroll:(UIScrollView *)_scrollView
{
// NSLog(#"scrollview val=%d",_scrollView.tag);
i=_scrollView.tag;
// NSLog(#"i=%d",i);
if (_scrollView.tag==101) {
if (pageControlIsChangingPage) {
return;
}
/*
* We switch page at 50% across
*/
//scr_anger.frame = CGRectMake(0, 0, 320, 0);
CGFloat pageWidth =scr_anger.frame.size.width;
//NSLog(#"pagewidth=%f",pageWidth);
int page = floor((scr_anger.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
// NSLog(#"page=%d",page);
pageControl.currentPage = page;
}
else if(_scrollView.tag==102)
{
if (pageControlIsChangingPage) {
return;
}
/*
* We switch page at 50% across
*/
CGFloat pageWidth =scr_sketch.frame.size.width;
int page = floor((scr_sketch.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl1.currentPage = page;
NSLog(#"page=%d",page);
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)_scrollView
{
pageControlIsChangingPage = NO;
}
#pragma mark -
#pragma mark PageControl stuff
- (IBAction)changePage:(id)sender
{
/*
* Change the scroll view
*/
//NSLog(#"i=%d",i);
if (i==101) {
CGRect frame = scr_anger.frame;
//pageControl.frame = CGRectMake(0, 390, 320, 15);
frame.origin.x = frame.size.width * pageControl.currentPage;
frame.origin.y = 0;
[scr_anger scrollRectToVisible:frame animated:YES];
/*
* When the animated scrolling finishings, scrollViewDidEndDecelerating will turn this off
*/
pageControlIsChangingPage = YES;
}
else if(i==102)
{
CGRect frame1 = scr_sketch.frame;
frame1.origin.x = frame1.size.width * pageControl1.currentPage;
frame1.origin.y = 0;
[scr_sketch scrollRectToVisible:frame1 animated:YES];
pageControlIsChangingPage = YES;
}
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (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 {
[scr_anger release];
[scr_sketch release];
[pageControl release];
[pageControl1 release];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
This is a relly good tutorial about UIScrollView&IPageControl combination. But I my self look for a tutorail for more dynamic designs(like main page of ios applications-i increments-decrements automatically)
Here's a information : http://cocoawithlove.com/2009/01/multiple-virtual-pages-in-uiscrollview.html
In your setupPage: method, You have a code to allow number of pages like this.
self.pageControl.numberOfPages = 2;
self.pageControl1.numberOfPages = 2;
If you want to increase a numberOfPages, then increase the numberOfPages in these lines.
Related
I tried to play video advertisements using the Custom Vast tag in the Google IMA integration application on macOS 12.0.1 and Xcode 13.1 but it gives the below error. I tried somany ways to but couldn't fix it. info.plist file I have shown below.
AdvancedExample[1476:21763] Error loading ads: Ads cannot be requested
because this AdsLoader failed to load
info.plist
VideoViewController.m
#import "VideoViewController.h"
#import AVFoundation;
#import "Constants.h"
typedef enum { PlayButton, PauseButton } PlayButtonType;
#interface VideoViewController () <AVPictureInPictureControllerDelegate, IMAAdsLoaderDelegate,
IMAAdsManagerDelegate, UIAlertViewDelegate>
// Tracking for play/pause.
#property(nonatomic) BOOL isAdPlayback;
// Play/Pause buttons.
#property(nonatomic, strong) UIImage *playBtnBG;
#property(nonatomic, strong) UIImage *pauseBtnBG;
// PiP objects.
#property(nonatomic, strong) AVPictureInPictureController *pictureInPictureController;
#property(nonatomic, strong) IMAPictureInPictureProxy *pictureInPictureProxy;
// Storage points for resizing between fullscreen and non-fullscreen
/// Frame for video player in fullscreen mode.
#property(nonatomic, assign) CGRect fullscreenVideoFrame;
/// Frame for video view in portrait mode.
#property(nonatomic, assign) CGRect portraitVideoViewFrame;
/// Frame for video player in portrait mode.
#property(nonatomic, assign) CGRect portraitVideoFrame;
/// Frame for controls in fullscreen mode.
#property(nonatomic, assign) CGRect fullscreenControlsFrame;
/// Frame for controls view in portrait mode.
#property(nonatomic, assign) CGRect portraitControlsViewFrame;
/// Frame for controls in portrait mode.
#property(nonatomic, assign) CGRect portraitControlsFrame;
/// Option for tracking fullscreen.
#property(nonatomic, assign) BOOL fullscreen;
/// Option for tracking load event
#property(nonatomic, assign) BOOL didRequestAds;
/// Gesture recognizer for tap on video.
#property(nonatomic, strong) UITapGestureRecognizer *videoTapRecognizer;
// IMA objects.
#property(nonatomic, strong) IMAAdsManager *adsManager;
#property(nonatomic, strong) IMACompanionAdSlot *companionSlot;
// Content player objects.
#property(nonatomic, strong) AVPlayer *contentPlayer;
#property(nonatomic, strong) AVPlayerLayer *contentPlayerLayer;
#property(nonatomic, strong) id playHeadObserver;
#end
#implementation VideoViewController
#pragma mark Set-up methods
// Set up the new view controller.
- (void)viewDidLoad {
[super viewDidLoad];
[self.topLabel setText:self.video.title];
// Set the play button image.
self.playBtnBG = [UIImage imageNamed:#"play.png"];
// Set the pause button image.
self.pauseBtnBG = [UIImage imageNamed:#"pause.png"];
self.isAdPlayback = NO;
self.fullscreen = NO;
self.didRequestAds = NO;
// Fix iPhone issue of log text starting in the middle of the UITextView
self.automaticallyAdjustsScrollViewInsets = NO;
// Set up CGRects for resizing the video and controls on rotate.
CGRect videoViewBounds = self.videoView.bounds;
self.portraitVideoViewFrame = self.videoView.frame;
self.portraitVideoFrame =
CGRectMake(0, 0, videoViewBounds.size.width, videoViewBounds.size.height);
CGRect videoControlsBounds = self.videoControls.bounds;
self.portraitControlsViewFrame = self.videoControls.frame;
self.portraitControlsFrame =
CGRectMake(0, 0, videoControlsBounds.size.width, videoControlsBounds.size.height);
// Set videoView on top of everything else (for fullscreen support).
[self.view bringSubviewToFront:self.videoView];
[self.view bringSubviewToFront:self.videoControls];
// Check orientation, set to fullscreen if we're in landscape
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft ||
[[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight) {
[self viewDidEnterLandscape];
}
// Set up content player and IMA classes, then request ads. If the user selected "Custom",
// get the ad tag from the pop-up dialog.
[self setUpContentPlayer];
[self setUpIMA];
}
// Makes the request on first appearance only.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (self.didRequestAds) {
return;
}
self.didRequestAds = YES;
if ([self.video.tag isEqual:#"custom"]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Tag"
message:#"Enter your test tag below"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
} else {
[self requestAdsWithTag:self.video.tag];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[self.contentPlayer pause];
// Don't reset if we're presenting a modal view (for example, in-app clickthrough).
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
if (self.adsManager) {
[self.adsManager destroy];
self.adsManager = nil;
}
[self removeObservers];
self.contentPlayer = nil;
}
[super viewWillDisappear:animated];
}
//Remove ContentPlayer Observer
- (void)removeObservers {
if (self.playHeadObserver) {
[self.contentPlayer removeTimeObserver:self.playHeadObserver];
self.playHeadObserver = nil;
}
#try {
[self.contentPlayer removeObserver:self forKeyPath:#"rate"];
[self.contentPlayer removeObserver:self forKeyPath:#"currentItem.duration"];
} #catch (NSException *exception) { }
}
// If pop-up dialog was shown, request ads with provided tag on dialog close.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
[self requestAdsWithTag:[[alertView textFieldAtIndex:0] text]];
}
// Initialize the content player and load content.
- (void)setUpContentPlayer {
// Load AVPlayer with path to our content.
NSURL *contentURL = [NSURL URLWithString:self.video.video];
self.contentPlayer = [AVPlayer playerWithURL:contentURL];
// Playhead observers for progress bar.
__weak VideoViewController *controller = self;
self.playHeadObserver = [controller.contentPlayer
addPeriodicTimeObserverForInterval:CMTimeMake(1, 30)
queue:NULL
usingBlock:^(CMTime time) {
CMTime duration = [controller
getPlayerItemDuration:controller.contentPlayer.currentItem];
[controller updatePlayHeadWithTime:time duration:duration];
}];
[self.contentPlayer addObserver:self forKeyPath:#"rate" options:0 context:#"contentPlayerRate"];
[self.contentPlayer addObserver:self
forKeyPath:#"currentItem.duration"
options:0
context:#"playerDuration"];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(contentDidFinishPlaying:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.contentPlayer.currentItem];
// Set up fullscreen tap listener to show controls.
self.videoTapRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(showFullscreenControls:)];
[self.videoView addGestureRecognizer:self.videoTapRecognizer];
// Create a player layer for the player.
self.contentPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.contentPlayer];
// Size, position, and display the AVPlayer.
self.contentPlayerLayer.frame = self.videoView.layer.bounds;
[self.videoView.layer addSublayer:self.contentPlayerLayer];
// Set ourselves up for PiP.
self.pictureInPictureProxy =
[[IMAPictureInPictureProxy alloc] initWithAVPictureInPictureControllerDelegate:self];
self.pictureInPictureController =
[[AVPictureInPictureController alloc] initWithPlayerLayer:self.contentPlayerLayer];
self.pictureInPictureController.delegate = self.pictureInPictureProxy;
if (![AVPictureInPictureController isPictureInPictureSupported] && self.pictureInPictureButton) {
self.pictureInPictureButton.hidden = YES;
}
}
// Handler for keypath listener that is added for content playhead observer.
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == #"contentPlayerRate" && self.contentPlayer == object) {
[self updatePlayHeadState:(self.contentPlayer.rate != 0)];
} else if (context == #"playerDuration" && self.contentPlayer == object) {
[self
updatePlayHeadDurationWithTime:[self getPlayerItemDuration:self.contentPlayer.currentItem]];
}
}
#pragma mark UI handlers
// Handle clicks on play/pause button.
- (IBAction)onPlayPauseClicked:(id)sender {
if (!self.isAdPlayback) {
if (self.contentPlayer.rate == 0) {
[self.contentPlayer play];
} else {
[self.contentPlayer pause];
}
} else {
if (self.playHeadButton.tag == PlayButton) {
[self.adsManager resume];
[self setPlayButtonType:PauseButton];
} else {
[self.adsManager pause];
[self setPlayButtonType:PlayButton];
}
}
}
// Updates play button for provided playback state.
- (void)updatePlayHeadState:(BOOL)isPlaying {
[self setPlayButtonType:isPlaying ? PauseButton : PlayButton];
}
// Sets play button type.
- (void)setPlayButtonType:(PlayButtonType)buttonType {
self.playHeadButton.tag = buttonType;
[self.playHeadButton setImage:buttonType == PauseButton ? self.pauseBtnBG : self.playBtnBG
forState:UIControlStateNormal];
}
// Called when the user seeks.
- (IBAction)playHeadValueChanged:(id)sender {
if (![sender isKindOfClass:[UISlider class]]) {
return;
}
if (self.isAdPlayback == NO) {
UISlider *slider = (UISlider *)sender;
// If the playhead value changed by the user, skip to that point of the
// content is skippable.
[self.contentPlayer seekToTime:CMTimeMake(slider.value, 1)];
}
}
// Used to track progress of ads for progress bar.
- (void)adDidProgressToTime:(NSTimeInterval)mediaTime totalTime:(NSTimeInterval)totalTime {
CMTime time = CMTimeMakeWithSeconds(mediaTime, 1000);
CMTime duration = CMTimeMakeWithSeconds(totalTime, 1000);
[self updatePlayHeadWithTime:time duration:duration];
self.progressBar.maximumValue = totalTime;
}
// Get the duration value from the player item.
- (CMTime)getPlayerItemDuration:(AVPlayerItem *)item {
CMTime itemDuration = kCMTimeInvalid;
if ([item respondsToSelector:#selector(duration)]) {
itemDuration = item.duration;
} else {
if (item.asset && [item.asset respondsToSelector:#selector(duration)]) {
// Sometimes the test app hangs here for ios 4.2.
itemDuration = item.asset.duration;
}
}
return itemDuration;
}
// Updates progress bar for provided time and duration.
- (void)updatePlayHeadWithTime:(CMTime)time duration:(CMTime)duration {
if (CMTIME_IS_INVALID(time)) {
return;
}
Float64 currentTime = CMTimeGetSeconds(time);
if (isnan(currentTime)) {
return;
}
self.progressBar.value = currentTime;
self.playHeadTimeText.text =
[[NSString alloc] initWithFormat:#"%d:%02d", (int)currentTime / 60, (int)currentTime % 60];
[self updatePlayHeadDurationWithTime:duration];
}
// Update the current playhead duration.
- (void)updatePlayHeadDurationWithTime:(CMTime)duration {
if (CMTIME_IS_INVALID(duration)) {
return;
}
Float64 durationValue = CMTimeGetSeconds(duration);
if (isnan(durationValue)) {
return;
}
self.progressBar.maximumValue = durationValue;
self.durationTimeText.text = [[NSString alloc]
initWithFormat:#"%d:%02d", (int)durationValue / 60, (int)durationValue % 60];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
switch (interfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
[self viewDidEnterPortrait];
break;
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationPortraitUpsideDown:
[self viewDidEnterLandscape];
break;
case UIInterfaceOrientationUnknown:
break;
}
}
- (void)viewDidEnterLandscape {
self.fullscreen = YES;
CGRect screenRect = [[UIScreen mainScreen] bounds];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
self.fullscreenVideoFrame = CGRectMake(0, 0, screenRect.size.height, screenRect.size.width);
self.fullscreenControlsFrame =
CGRectMake(0, (screenRect.size.width - self.videoControls.frame.size.height),
screenRect.size.height, self.videoControls.frame.size.height);
} else {
self.fullscreenVideoFrame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height);
self.fullscreenControlsFrame =
CGRectMake(0, (screenRect.size.height - self.videoControls.frame.size.height),
screenRect.size.width, self.videoControls.frame.size.height);
}
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
[[self navigationController] setNavigationBarHidden:YES];
self.videoView.frame = self.fullscreenVideoFrame;
self.contentPlayerLayer.frame = self.fullscreenVideoFrame;
self.videoControls.frame = self.fullscreenControlsFrame;
self.videoControls.hidden = YES;
}
- (void)viewDidEnterPortrait {
self.fullscreen = NO;
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
[[self navigationController] setNavigationBarHidden:NO];
self.videoView.frame = self.portraitVideoViewFrame;
self.contentPlayerLayer.frame = self.portraitVideoFrame;
self.videoControls.frame = self.portraitControlsViewFrame;
}
- (IBAction)videoControlsTouchStarted:(id)sender {
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:#selector(hideFullscreenControls)
object:self];
}
- (IBAction)videoControlsTouchEnded:(id)sender {
[self startHideControlsTimer];
}
- (void)showFullscreenControls:(UITapGestureRecognizer *)recognizer {
if (self.fullscreen) {
self.videoControls.hidden = NO;
self.videoControls.alpha = 0.9;
[self startHideControlsTimer];
}
}
- (void)startHideControlsTimer {
[self performSelector:#selector(hideFullscreenControls) withObject:self afterDelay:3];
}
- (void)hideFullscreenControls {
[UIView animateWithDuration:0.5
animations:^{
self.videoControls.alpha = 0.0;
}];
}
- (IBAction)onPipButtonClicked:(id)sender {
if ([self.pictureInPictureController isPictureInPictureActive]) {
[self.pictureInPictureController stopPictureInPicture];
} else {
[self.pictureInPictureController startPictureInPicture];
}
}
#pragma mark IMA SDK methods
// Initialize ad display container.
- (IMAAdDisplayContainer *)createAdDisplayContainer {
// Create our AdDisplayContainer. Initialize it with our videoView as the container. This
// will result in ads being displayed over our content video.
if (self.companionView) {
// MOE:strip_line [START ad_display_container_init]
return [[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
viewController:self
companionSlots:#[ self.companionSlot ]];
// [END ad_display_container_init] MOE:strip_line
} else {
return [[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
viewController:self
companionSlots:nil];
}
}
// Register companion slots.
- (void)setUpCompanions {
// MOE:strip_line [START companion_slot_declaration]
self.companionSlot =
[[IMACompanionAdSlot alloc] initWithView:self.companionView
width:self.companionView.frame.size.width
height:self.companionView.frame.size.height];
// [END companion_slot_declaration] MOE:strip_line
}
// Initialize AdsLoader.
- (void)setUpIMA {
if (self.adsManager) {
[self.adsManager destroy];
}
[self.adsLoader contentComplete];
self.adsLoader.delegate = self;
if (self.companionView) {
[self setUpCompanions];
}
}
// Request ads for provided tag.
- (void)requestAdsWithTag:(NSString *)adTagUrl {
[self logMessage:#"Requesting ads"];
// Create an ad request with our ad tag, display container, and optional user context.
IMAAdsRequest *request = [[IMAAdsRequest alloc]
initWithAdTagUrl:adTagUrl
adDisplayContainer:[self createAdDisplayContainer]
avPlayerVideoDisplay:[[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.contentPlayer]
pictureInPictureProxy:self.pictureInPictureProxy
userContext:nil];
[self.adsLoader requestAdsWithRequest:request];
}
// Notify IMA SDK when content is done for post-rolls.
- (void)contentDidFinishPlaying:(NSNotification *)notification {
// Make sure we don't call contentComplete as a result of an ad completing.
if (notification.object == self.contentPlayer.currentItem) {
[self.adsLoader contentComplete];
}
}
#pragma mark AdsLoader Delegates
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
// Grab the instance of the IMAAdsManager and set ourselves as the delegate.
self.adsManager = adsLoadedData.adsManager;
self.adsManager.delegate = self;
// Create ads rendering settings to tell the SDK to use the in-app browser.
IMAAdsRenderingSettings *adsRenderingSettings = [[IMAAdsRenderingSettings alloc] init];
adsRenderingSettings.linkOpenerPresentingController = self;
// Initialize the ads manager.
[self.adsManager initializeWithAdsRenderingSettings:adsRenderingSettings];
}
- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
// Something went wrong loading ads. Log the error and play the content.
[self logMessage:#"Error loading ads: %#", adErrorData.adError.message];
self.isAdPlayback = NO;
[self setPlayButtonType:PauseButton];
[self.contentPlayer play];
}
#pragma mark AdsManager Delegates
/*- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
[self logMessage:#"AdsManager event (%#).", event.typeString];
// When the SDK notified us that ads have been loaded, play them.
switch (event.type) {
case kIMAAdEvent_LOADED:
if (![self.pictureInPictureController isPictureInPictureActive]) {
[adsManager start];
}
break;
case kIMAAdEvent_PAUSE:
[self setPlayButtonType:PlayButton];
break;
case kIMAAdEvent_RESUME:
[self setPlayButtonType:PauseButton];
break;
case kIMAAdEvent_TAPPED:
[self showFullscreenControls:nil];
break;
default:
break;
}
}*/
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
[self logMessage:#"AdsManager event (%#).", event.typeString];
switch (event.type) {
case kIMAAdEvent_LOADED:
[adsManager start];
break;
//case kIMAAdEvent_STARTED: {
break;
case kIMAAdEvent_PAUSE:
[self setPlayButtonType:PlayButton];
break;
case kIMAAdEvent_RESUME:
[self setPlayButtonType:PauseButton];
break;
case kIMAAdEvent_TAPPED:
[self showFullscreenControls:nil];
break;
default:
break;
}
}
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error {
// Something went wrong with the ads manager after ads were loaded. Log the error and play the
// content.
[self logMessage:#"AdsManager error: %#", error.message];
self.isAdPlayback = NO;
[self setPlayButtonType:PauseButton];
[self.contentPlayer play];
}
- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager {
// The SDK is going to play ads, so pause the content.
self.isAdPlayback = YES;
[self setPlayButtonType:PauseButton];
[self.contentPlayer pause];
}
- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
// The SDK is done playing ads (at least for now), so resume the content.
self.isAdPlayback = NO;
[self setPlayButtonType:PauseButton];
[self.contentPlayer play];
}
#pragma mark Utility methods
- (void)logMessage:(NSString *)log, ... {
va_list args;
va_start(args, log);
NSString *s = [[NSString alloc] initWithFormat:[[NSString alloc] initWithFormat:#"%#\n", log]
arguments:args];
self.consoleView.text = [self.consoleView.text stringByAppendingString:s];
NSLog(#"%#", s);
va_end(args);
if (self.consoleView.text.length > 0) {
NSRange bottom = NSMakeRange(self.consoleView.text.length - 1, 1);
[self.consoleView scrollRangeToVisible:bottom];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I have been experimenting with some code in a sample project that uses xibs. In that project the below method takes a photo that was picked via UIImagePickerController and displays another VC modally initializing its scrollview with the image.
This works fine in the xib project but now that im integrating it into a storyboard project this section throws an exception:
SSPhotoCropperViewController *photoCropper =
[[SSPhotoCropperViewController alloc] initWithPhoto:nonRawImage
delegate:self
uiMode:SSPCUIModePresentedAsModalViewController
showsInfoButton:YES];
The error is:
'Could not load NIB in bundle: 'NSBundle </var/mobile/Applications/24FB2532-BB1D-4573-8551-386FAA154022/BubbleBoss.app> (loaded)' with name 'SSPhotoCropperViewController''
Which seems to be saying that its looking for the xib file that isnt there. I have created a mimicked storyboard version of the xib and hooked up all my actions and outlets the same.
How do I display a storyboard VC in the below method, set the scrollview photo to nonRawImage, pass it the min and max zoom as is done below?
Problem Method:
-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = info[UIImagePickerControllerMediaType];
[self dismissViewControllerAnimated:NO completion:nil];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
UIImage *image = info[UIImagePickerControllerOriginalImage];
UIImage *nonRawImage=[self scaleAndRotateImage:image];
SSPhotoCropperViewController *photoCropper =
[[SSPhotoCropperViewController alloc] initWithPhoto:nonRawImage
delegate:self
uiMode:SSPCUIModePresentedAsModalViewController
showsInfoButton:YES];
[photoCropper setMinZoomScale:0.25f];
[photoCropper setMaxZoomScale:3.00f];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:photoCropper];
[self presentViewController:nc animated:YES completion:nil];
// photoPreviewImageView.image = image;
if (_newMedia)
UIImageWriteToSavedPhotosAlbum(image,
self,
#selector(image:finishedSavingWithError:contextInfo:),
nil);
}
else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie])
{
// Code here to support video if enabled
}
}
Code from SSPhotoCropperViewController.m
- (id) initWithPhoto:(UIImage *)aPhoto
delegate:(id<SSPhotoCropperDelegate>)aDelegate
{
return [self initWithPhoto:aPhoto
delegate:aDelegate
uiMode:SSPCUIModePresentedAsModalViewController
showsInfoButton:YES];
}
- (id) initWithPhoto:(UIImage *)aPhoto
delegate:(id<SSPhotoCropperDelegate>)aDelegate
uiMode:(SSPhotoCropperUIMode)uiMode
showsInfoButton:(BOOL)showsInfoButton
{
if (!(self = [super initWithNibName:#"SSPhotoCropperViewController" bundle:nil])) {
return self;
}
self.photo = aPhoto;
self.delegate = aDelegate;
_uiMode = uiMode;
_showsInfoButton = showsInfoButton;
self.minZoomScale = 0.5f;
self.maxZoomScale = 3.0f;
self.infoMessageTitle = #"In order to crop the photo";
self.infoMessageBody = #"Use two of your fingers to zoom in and out the photo and drag the"
#" green window to crop any part of the photo you would like to use.";
self.photoCropperTitle = #"Crop Photo";
return self;
}
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.photo = nil;
self.delegate = nil;
}
return self;
}
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction) infoButtonTapped:(id)sender
{
UIAlertView *av = [[UIAlertView alloc] initWithTitle:self.infoMessageTitle
message:self.infoMessageBody
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[av show];
}
#pragma -
#pragma mark - View lifecycle
- (void) viewDidLoad
{
[super viewDidLoad];
//
// setup view ui
//
UIBarButtonItem *bi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(saveAndClose:)];
self.navigationItem.rightBarButtonItem = bi;
if (_uiMode == SSPCUIModePresentedAsModalViewController) {
bi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:#selector(cancelAndClose:)];
self.navigationItem.leftBarButtonItem = bi;
}
if (!_showsInfoButton) {
[self.infoButton setHidden:YES];
}
self.title = self.photoCropperTitle;
//
// photo cropper ui stuff
//
[self setScrollViewBackground];
[self.scrollView setMinimumZoomScale:self.minZoomScale];
[self.scrollView setMaximumZoomScale:self.maxZoomScale];
[self.cropRectangleButton addTarget:self
action:#selector(imageTouch:withEvent:)
forControlEvents:UIControlEventTouchDown];
[self.cropRectangleButton addTarget:self
action:#selector(imageMoved:withEvent:)
forControlEvents:UIControlEventTouchDragInside];
if (self.photo != nil) {
[self loadPhoto];
}
}
- (void) viewDidUnload
{
[super viewDidUnload];
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
#pragma -
#pragma UIScrollViewDelegate Methods
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
#pragma -
#pragma Private Methods
- (void) loadPhoto
{
if (self.photo == nil) {
return;
}
CGFloat w = self.photo.size.width;
CGFloat h = self.photo.size.height;
CGRect imageViewFrame = CGRectMake(0.0f, 0.0f, roundf(w / 2.0f), roundf(h / 2.0f));
self.scrollView.contentSize = imageViewFrame.size;
UIImageView *iv = [[UIImageView alloc] initWithFrame:imageViewFrame];
iv.image = self.photo;
[self.scrollView addSubview:iv];
self.imageView = iv;
}
Ok ive got the method call changed to
SSPhotoCropperViewController *photoCropper =
[[SSPhotoCropperViewController alloc] initWithPhoto:photo
delegate:self
uiMode:SSPCUIModePresentedAsModalViewController
showsInfoButton:YES];
[photoCropper setMinZoomScale:0.25f];
[photoCropper setMaxZoomScale:3.00f];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:photoCropper];
But Im not sure what to do with the below:
- (id) initWithPhoto:(UIImage *)aPhoto
delegate:(id<SSPhotoCropperDelegate>)aDelegate
uiMode:(SSPhotoCropperUIMode)uiMode
showsInfoButton:(BOOL)showsInfoButton
{
if (!(self = [super initWithNibName:#"SSPhotoCropperViewController" bundle:nil])) {
return self;
}
self.photo = aPhoto;
self.delegate = aDelegate;
_uiMode = uiMode;
_showsInfoButton = showsInfoButton;
self.minZoomScale = 0.5f;
self.maxZoomScale = 3.0f;
self.infoMessageTitle = #"In order to crop the photo";
self.infoMessageBody = #"Use two of your fingers to zoom in and out the photo and drag the"
#" green window to crop any part of the photo you would like to use.";
self.photoCropperTitle = #"Crop Photo";
return self;
}
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.photo = nil;
self.delegate = nil;
}
return self;
}
You should give your view controller an identifier within the storyboard, then instantiate it as follows:
YourViewControllerClass *viewController =
[[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil]
instantiateViewControllerWithIdentifier:#"ViewController"];
The identifier can be set using Storyboard ID from within the Identity Inspector.
Make sure you set the SSPhotoCropperViewController's Identifier in the storyboard to SSPhotoCropperViewController.
Change your method:
- (id) initWithPhoto:(UIImage *)aPhoto
delegate:(id<SSPhotoCropperDelegate>)aDelegate
uiMode:(SSPhotoCropperUIMode)uiMode
showsInfoButton:(BOOL)showsInfoButton
{
//if (!(self = [super initWithNibName:#"SSPhotoCropperViewController" bundle:nil])) {
if (!(self = [[UIStoryboard storyboardWithName:#"YourStoryBoardName" bundle:nil]
instantiateViewControllerWithIdentifier:#"SSPhotoCropperViewController"])) {
return self;
}
self.photo = aPhoto;
self.delegate = aDelegate;
_uiMode = uiMode;
_showsInfoButton = showsInfoButton;
self.minZoomScale = 0.5f;
self.maxZoomScale = 3.0f;
self.infoMessageTitle = #"In order to crop the photo";
self.infoMessageBody = #"Use two of your fingers to zoom in and out the photo and drag the"
#" green window to crop any part of the photo you would like to use.";
self.photoCropperTitle = #"Crop Photo";
return self;
}
when I tested my App in instruments for memory leak I found nothing(running using simulator).But When I run it in a mobile and then checked, there are many leaks in UIKit objects. This happening in every view.In simulator no such leaks are showing.
Below is the screenshot of the instrument where some leakage happened.
When I moved to secondViewController from HomeView, no leaks found.If again coming back to home,these many leaks are found. So, is it mean that, I have to release/nil all the UI objects which I used in that secondView. For your information, below are the UI objects I used in secondView.
1.Two Background UIImageView
2.One TitleBar UIImageView
3.3 UIButtons(Back,left and right button for iCarousel)
4.One iCarousel view
5.UIPageController(For this I have used a third Party code SMPageControl)
6.One title label.
Note : Mine is Non-ARC code.
Did anyone faced this problem before.How can I overcome this problem,since I have this problem in every View in my App.Because of this, my App getting memory waring frequently and crashing often.
Thank you.
Below is the my implementation file of that View.
EDIT1 :
#implementation CatalogueViewController
#synthesize deptCarousel = _deptCarousel;
#synthesize carouselItems = _carouselItems;
#synthesize categorymAr = _categorymAr;
#synthesize spacePageControl = _spacePageControl;
#synthesize wrap;
- (void)dealloc {
_deptCarousel = nil;
[_categorymAr release];
_categorymAr = nil;
_deptCarousel.delegate = nil;
_deptCarousel.dataSource = nil;
[_deptCarousel release];
[_carouselItems release];
[viewGesture release];
viewGesture = nil;
[_spacePageControl release];
_spacePageControl = nil;
imgViewBG = nil;
imgViewBG2 = nil;
btnPrev = nil;
btnNext = nil;
// [self releaseObjects];
[super dealloc];
}
- ( IBAction) btnBackClicked {
[self.navigationController popViewControllerAnimated:YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(#"catalogue", #"Catalogue");
// Do any additional setup after loading the view from its nib.
_deptCarousel.type = iCarouselTypeLinear;
_deptCarousel.scrollSpeed = 0.3f;
_deptCarousel.bounceDistance = 0.1f;
_deptCarousel.scrollToItemBoundary = YES;
_deptCarousel.stopAtItemBoundary = YES;
[_deptCarousel setScrollEnabled:NO];
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeNext:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[viewGesture addGestureRecognizer:swipeLeft];
[swipeLeft release];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipePrev:)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[viewGesture addGestureRecognizer:swipeRight];
[swipeRight release];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[viewGesture addGestureRecognizer:singleTap];
[singleTap release];
_carouselItems = [[NSMutableArray alloc] initWithCapacity:1];
_categorymAr = [[NSMutableArray alloc] initWithCapacity:1];
[self addCatalogues];
_spacePageControl.numberOfPages = [_categorymAr count];
[_spacePageControl setPageIndicatorImage:[UIImage imageNamed:IS_IPAD?#"Marker1.fw.png" : #"Markeri.png"]];
[_spacePageControl setCurrentPageIndicatorImage:[UIImage imageNamed:IS_IPAD?#"Marker-Highlight.png" : #"Marker-Highlight_i.png"]];
[_spacePageControl addTarget:self action:#selector(spacePageControl:) forControlEvents:UIControlEventValueChanged];
}
- (void)spacePageControl:(SMPageControl *)sender{
[_deptCarousel scrollToItemAtIndex:sender.currentPage animated:YES];
}
- ( void ) addCatalogues {
[_categorymAr addObjectsFromArray:[[DBModel database] categoryList]];
for (int i = 0; i < [_categorymAr count]; i++) {
[_carouselItems addObject:[NSNumber numberWithInt:i]];
}
[_deptCarousel reloadData];
}
- (void)viewDidUnload{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[self phoneType];
[super viewWillAppear:animated];
if (IS_IPAD) {
UIInterfaceOrientation statusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
[self handleOrientation:statusBarOrientation];
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- ( void ) phoneType{
if(!IS_IPAD){
if(IS_IPHONE5){
imgViewBG.image = [UIImage imageNamed:#"Background5_5.jpg"];
imgViewBG.center = CGPointMake(162,265);
imgViewBG2.image = [UIImage imageNamed:#"Background11_5.png"];
_spacePageControl.center = CGPointMake(160, 478);
_deptCarousel.center = CGPointMake(160, 355);
viewGesture.center = CGPointMake(160, 355);
btnPrev.center = CGPointMake(25, 355);
btnNext.center = CGPointMake(295, 355);
}
else{
imgViewBG.image = [UIImage imageNamed:#"Background5.jpg"];
imgViewBG2.image = [UIImage imageNamed:#"Background9.png"];
}
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField{
textFieldSearch.placeholder = #"";
UIButton *clearButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
[clearButton setImage:[UIImage imageNamed:IS_IPAD?#"Btn_X_Large.fw.png":#"Btn_X.fw.png"] forState:UIControlStateNormal];
[clearButton addTarget:self action:#selector(btnClearTextField) forControlEvents:UIControlEventTouchUpInside];
[textFieldSearch setRightViewMode:UITextFieldViewModeAlways];
[textFieldSearch setRightView:clearButton];
[clearButton release];
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
[textFieldSearch setRightView:nil];
if ([textFieldSearch.text isEqualToString:#""]) {
textFieldSearch.placeholder = NSLocalizedString(#"hud_search_for_a_product_here",#"");
}
}
-(IBAction)btnClearTextField{
textFieldSearch.text = #"";
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (IS_IPAD) {
return YES;
} else {
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation )toInterfaceOrientation duration:(NSTimeInterval)duration{
if (IS_IPAD) {
[self handleOrientation:toInterfaceOrientation];
}
}
- ( void ) handleOrientation:(UIInterfaceOrientation )toInterfaceOrientation {
if (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
imgViewBG.image = [UIImage imageNamed:#"Background_Catalogue_P.jpg"];
imgViewBG2.image = [UIImage imageNamed:#"Background_Overlay_P.fw.png"];
btnPrev.center = CGPointMake(90, 640);
btnNext.center = CGPointMake(677, 640);
textFieldSearch.frame = CGRectMake(187, 54, 418, 25);
_deptCarousel.frame = CGRectMake(235, 250, 300, 800);
_spacePageControl.center = CGPointMake(385, 920);
viewGesture.center = CGPointMake(385, 658);
}else {
imgViewBG.image = [UIImage imageNamed:#"Background_Catalogue_L.jpg"];
imgViewBG2.image = [UIImage imageNamed:#"Background_Overlay_L.fw.png"];
btnPrev.center = CGPointMake(54, 385);
btnNext.center = CGPointMake(640, 385);
textFieldSearch.frame = CGRectMake(240, 55, 567, 25);
_deptCarousel.frame = CGRectMake(50, 250, 600, 300);
_spacePageControl.center = CGPointMake(346, 660);
viewGesture.center = CGPointMake(347, 405);
}
}
- ( IBAction )btnDepartmentClicked:(id)sender {
int btnTag = [sender tag];
ProductCategoriesViewController *productView = [[ProductCategoriesViewController alloc] initWithNibName:#"ProductCategoriesView" bundle:nil];
if ( btnTag == 0 ) {
[productView setStrTitle:NSLocalizedString(#"women", #"Women")];
}else if ( btnTag == 1 ) {
[productView setStrTitle:NSLocalizedString(#"men", #"Men")];
} else {
[productView setStrTitle:NSLocalizedString(#"sports", #"Sports")];
}
[self.navigationController pushViewController:productView animated:YES];
[productView release];
}
- ( BOOL ) textFieldShouldReturn:( UITextField * )textField {
[textField resignFirstResponder];
[Flurry logEvent:#"Product searched" withParameters:[NSDictionary dictionaryWithObjectsAndKeys:textField.text,#"1", nil]];
[self productSearch:textField.text isBar:NO isQR:NO];
return YES;
}
- ( void ) productSearch:( NSString * )_searchText isBar:( BOOL )_isBar isQR:( BOOL )_isQr {
if ([_searchText isEqualToString:#""]) {
return;
}
NSMutableArray *ProductList = [[NSMutableArray alloc] init];
[ProductList addObjectsFromArray:[[DBModel database] productSearch:_searchText isBar:_isBar isQR:_isQr]];
if ( [ProductList count] == 0 ) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"product", #"")
message:NSLocalizedString(#"cannot_find_product", #"")
delegate:nil
cancelButtonTitle:NSLocalizedString(#"ok", #"")
otherButtonTitles:nil];
[alert show];
[alert release];
} else {
GeneralProductListViewController *generalProductList = [[GeneralProductListViewController alloc] initWithNibName:IS_IPAD?#"GeneralProductListView~iPad": #"GeneralProductListView" bundle:nil];
[generalProductList setMArProducts:ProductList];
[self.navigationController pushViewController:generalProductList animated:YES];
[generalProductList release];
}
[ProductList release];
}
-(IBAction) spin:(id)sender {
if([sender tag]==0)
{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]+1 animated:YES];
// [_deptCarousel scrollByNumberOfItems:1 duration:2.0];
}
else{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]-1 animated:YES];
}
}
-(void)swipeNext:(UISwipeGestureRecognizer *)recognizer{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]+1 animated:YES];
}
-(void)swipePrev:(UISwipeGestureRecognizer *)recognizer{
[_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]-1 animated:YES];
}
-(void) handleSingleTap:(UITapGestureRecognizer *)recognizer{
if ([_categorymAr count] > 0) {
ProductCategoriesViewController *prodCatView = [[ProductCategoriesViewController alloc] initWithNibName:IS_IPAD ?
#"ProductCategoriesView~iPad" : #"ProductCategoriesView" bundle:nil];
Category *categoryObj = [_categorymAr objectAtIndex:[self.deptCarousel currentItemIndex]];
[prodCatView setStrTitle:categoryObj.categoryName];
[prodCatView setCategoryId:categoryObj.categoryId];
[Flurry logEvent:#"Category List" withParameters:[NSDictionary dictionaryWithObjectsAndKeys:categoryObj.categoryName,[NSString stringWithFormat:#"%d",categoryObj.categoryId], nil]];
[self.navigationController pushViewController:prodCatView animated:YES];
[prodCatView release];
}
}
//-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
// pageControl.currentPage = [self.deptCarousel currentItemIndex] ;
//}
#pragma mark
#pragma mark NavigationBarViewDelegate metho
- ( void ) navigationBackClicked {
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark -
#pragma mark iCarousel methods
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
return [_carouselItems count];
}
- (NSUInteger)numberOfVisibleItemsInCarousel:(iCarousel *)carousel
{
//limit the number of items views loaded concurrently (for performance reasons)
return NUMBER_OF_VISIBLE_ITEMS;
}
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index
{
Category *categoryObj = [_categorymAr objectAtIndex:index];
//create a numbered view
UIView *view = nil;
NSString *imagePath = [[APP_CACHES_DIR stringByAppendingPathComponent:#"catalogues"] stringByAppendingString:[NSString stringWithFormat:#"/%d.jpg", categoryObj.categoryId]];
if (![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
view = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:IS_IPAD?#"Gallery Placeholder.png":#"Gallery Placeholder.png"]] autorelease];
} else {
view = [[[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[APP_CACHES_DIR stringByAppendingPathComponent:#"catalogues"] stringByAppendingString:[NSString stringWithFormat:#"/%d.jpg", categoryObj.categoryId]]]] autorelease];
}
if (IS_IPAD) {
view.frame = CGRectMake(0, 0, 420, 420);
} else {
view.frame = CGRectMake(0, 0, 200, 200);
}
// UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(view.bounds.origin.x, view.bounds.origin.y+view.bounds.size.height, view.bounds.size.width, 44)] autorelease];
// label.text = categoryObj.categoryName;
// label.textColor = [UIColor blackColor];
// label.backgroundColor = [UIColor clearColor];
// label.textAlignment = UITextAlignmentCenter;
// label.font = [UIFont fontWithName:#"Helvetica-Bold" size:IS_IPAD?26:14];
// [view addSubview:label];
return view;
}
- (NSUInteger)numberOfPlaceholdersInCarousel:(iCarousel *)carousel
{
//note: placeholder views are only displayed on some carousels if wrapping is disabled
return INCLUDE_PLACEHOLDERS? 2: 0;
}
- (UIView *)carousel:(iCarousel *)carousel placeholderViewAtIndex:(NSUInteger)index
{
//create a placeholder view
UIView *view = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#""]] autorelease];
UILabel *label = [[[UILabel alloc] initWithFrame:view.bounds] autorelease];
label.text = (index == 0)? #"[": #"]";
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.font = [label.font fontWithSize:50];
_spacePageControl.currentPage = index;
// [view addSubview:label];
return view;
}
- (CGFloat)carouselItemWidth:(iCarousel *)carousel
{
//usually this should be slightly wider than the item views
return ITEM_SPACING;
}
- (CATransform3D)carousel:(iCarousel *)_carousel transformForItemView:(UIView *)view withOffset:(CGFloat)offset
{
//implement 'flip3D' style carousel
//set opacity based on distance from camera
view.alpha = 1.0 - fminf(fmaxf(offset, 0.0), 1.0);
//do 3d transform
CATransform3D transform = CATransform3DIdentity;
transform.m34 = _deptCarousel.perspective;
transform = CATransform3DRotate(transform, M_PI / 8.0, 0, 1.0, 0);
return CATransform3DTranslate(transform, 0.0, 0.0, offset * _deptCarousel.itemWidth);
}
- (BOOL)carouselShouldWrap:(iCarousel *)carousel
{
//wrap all carousels
// return NO;
return wrap;
}
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index {
if (index == [self.deptCarousel currentItemIndex]) {
ProductCategoriesViewController *prodCatView = [[ProductCategoriesViewController alloc] initWithNibName:IS_IPAD ?
#"ProductCategoriesView~iPad" : #"ProductCategoriesView" bundle:nil];
Category *categoryObj = [_categorymAr objectAtIndex:index];
[prodCatView setStrTitle:categoryObj.categoryName];
[prodCatView setCategoryId:categoryObj.categoryId];
[Flurry logEvent:#"Category List" withParameters:[NSDictionary dictionaryWithObjectsAndKeys:categoryObj.categoryName,[NSString stringWithFormat:#"%d",categoryObj.categoryId], nil]];
[self.navigationController pushViewController:prodCatView animated:YES];
[prodCatView release];
}
}
-(void) carouselDidScroll:(iCarousel *)carousel{
// [_deptCarousel scrollToItemAtIndex:[self.deptCarousel currentItemIndex]+3 animated:YES];
// [_deptCarousel scrollByNumberOfItems:1 duration:1];
}
- (void)carouselCurrentItemIndexUpdated:(iCarousel *)carousel{
_spacePageControl.currentPage = [self.deptCarousel currentItemIndex];
}
- ( IBAction ) myCart {
if ( [[DBModel database] isShoppingListEmpty] ) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"at_shopping_cart", #"")
message:NSLocalizedString(#"amsg_shopping_cart_empty", #"")
delegate:nil cancelButtonTitle:NSLocalizedString(#"ok", #"") otherButtonTitles:nil];
[alert show];
[alert release];
return;
}
MyCartViewController *myCartView = [[MyCartViewController alloc] initWithNibName:IS_IPAD ? #"MyCartView~iPad" : #"MyCartView" bundle:nil];
[self.navigationController pushViewController:myCartView animated:YES];
[myCartView release];
}
First, as noted before, use ARC. There is no single thing you could do that will more improve memory management.
Whether you use ARC or not, you should always use accessors to access your ivars (except in init and dealloc). As noted by #LombaX, you're setting your ivars incorrectly in viewDidLoad. Using accessors would help this.
You should run the static analyzer, which will help you find other memory mistakes.
I would suspect that you have an IBOutlet that is configured as retain and that you are not releasing in dealloc. That is the most likely cause of the leaks I'm seeing in your screenshots. ARC will generally make such problems go away automatically.
It is very possible that you have a retain loop. This generally would not show up as a leak. You should use heapshot to investigate that. Your leaks are pretty small; they may not be the actual cause of memory warnings. What you want to investigate (with the Allocations instrument) is what is actually significantly growing your memory use.
But first ARC. Then accessors. Then remove all build warnings. Then remove all Static Analyzer warnings. Then use the Allocations instrument.
Side note: the fact that it says the responsible party is "UIKit" does not mean that this is a bug in UIKit. It just means that UIKit allocated the memory that was later leaked. The cause of the leak could be elsewhere. (That said, UIKit does have several small leaks in it. In general they should not give you trouble, but you may never be able to get rid of 100% of small leaks in an iOS app.)
First:
you have a possible and visible leak, but I'm not sure if it is the same leak you have found in instruments:
These two lines are in your viewDidLoad method
_carouselItems = [[NSMutableArray alloc] initWithCapacity:1];
_categorymAr = [[NSMutableArray alloc] initWithCapacity:1];
But: viewDidLoad: is called every time the view is loaded by it's controller. If the controller purges the view (for example after a memory warning), at the second viewDidLoad your _carouselItems and _categorymAr instance variables will lost the reference to the previously created NSMutableArray, causing a leak
So, change that lines and use the syntesized setters:
self.carouselItems = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
self.categorymAr = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];
the syntesized setter is configured to release the previous object before assignin a new one.
However: it's possible that you have another leak.
If you can reproduce the leak simply (if I understand, the leak appears simply moving from a VC to another), you can use the "heapshot" function of instruments.
Assuming that your leak appears moving from the first VC to the second and coming back:
open instruments with the allocations tool
go from the first VC to the second and come back.
press "mark heap" on the left. A line will appear.
go again from the first VC to the second and come back.
press "heapshot" again
do this several times (9-10)
the heapshot tool takes a "snapshot" of the living objects at the time you pushed the button and shows you only the difference.
If there are 2-3 new objects, you will see it in the list.
This is a good starting point to investigate a leak.
Look at the attached image:
Consider that you must mark the heap several time and discriminate "false positive" by looking at the object created, in my example you can se a possible leak (heapshot5, 1,66KB), but after looking at the content it's not --> it was a background task that started in that moment.
Moreover, delays of the autorelease pool and the cache of some UIKit objects can show something in the heapshot, this is why I say to try it several times.
One easy way to detect where your leaks come from is to use the Extended Detail view of the Instruments.
To do that click on "View"->"Extended detail" and a right menu with the stack trace of the "leak" will appear. There you will easily find the leaking code for each leak and if they come from your app.
I want my whole project to run in portrait mode only and only the view that's for viewing the photo's can turn on landscape same as if using the facebook (we view photo's they turn landscape also but other view's remains in portrait) i want to know that how it's done as i have a table view that has images that i get from the DB from the server and every particular data contains different number's of photo's so now i want that after the user select's the photo's they should open up fully and can be viewed in landscape and in portrait as well i did tried
I am working with ios6
- (BOOL)shouldAutorotate
{
return NO;
}
implementing in all the view's so that they can remain in portrait but still they turn in landscape how should i restrict it and please can any one tell me that in one of my class i have images in table view(loaded from the DB) and i have another class that open's up the selected photo from the table
My PhotoView.m class
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dic = [photos objectAtIndex:indexPath.row];
NSLog(#" *** url is %#",[dic objectForKey:#"url"]);
[self.delegate showPhotoAtUrl:[dic objectForKey:#"url"]];
}
My PhotoViewController.h class
#import <UIKit/UIKit.h>
#interface PhotoViewController : UIViewController <UIScrollViewDelegate>
{
NSString *url;
UIButton *doneButton;
}
#property (nonatomic, retain) UIImageView *imageView;
- (id) initWithPhotoUrl:(NSString *)photoUrl;
#end
and PhotoViewController.m class
#import "PhotoViewController.h"
#interface PhotoViewController ()
#end
#implementation PhotoViewController
#synthesize imageView;
- (id) initWithPhotoUrl:(NSString *)photoUrl
{
self = [super init];
if(self) {
url = [photoUrl retain];
}
return self;
}
- (void)dealloc
{
[url release];
self.imageView = nil;
[doneButton release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.tag = 1;
spinner.center = self.view.center;
[spinner startAnimating];
[self.view addSubview:spinner];
[spinner release];
[self performSelectorInBackground:#selector(loadPhotoData) withObject:nil];
doneButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
[doneButton addTarget:self action:#selector(doneTouched) forControlEvents:UIControlEventTouchUpInside];
[doneButton setTitle:#"done" forState:UIControlStateNormal];
[doneButton setBackgroundColor:[UIColor clearColor]];
doneButton.frame = CGRectMake(2, 2, 60, 30);
[self.view addSubview:doneButton];
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.title = #"";
self.navigationController.navigationBarHidden = YES;
}
- (void) doneTouched
{
[self.navigationController popViewControllerAnimated:YES];
}
- (void) loadComplete:(NSData *)imageData
{
if(!imageData) return;
UIActivityIndicatorView *spinner = (UIActivityIndicatorView *)[self.view viewWithTag:1];
if(spinner) {
[spinner stopAnimating];
[spinner removeFromSuperview];
}
UIImage *img = [UIImage imageWithData:imageData];
float scale = MIN(self.view.frame.size.width/img.size.width, self.view.frame.size.height/img.size.height);
self.imageView = [[[UIImageView alloc] initWithImage:img] autorelease];
self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width*scale, self.imageView.image.size.height*scale);
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.imageView.center = scrollView.center;
scrollView.delegate = self;
scrollView.contentSize = self.imageView.frame.size;
scrollView.minimumZoomScale = 1;
scrollView.maximumZoomScale = 2;
[scrollView addSubview:self.imageView];
[self.view addSubview:scrollView];
[scrollView release];
[self.view bringSubviewToFront:doneButton];
}
- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void) loadPhotoData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
[self performSelectorOnMainThread:#selector(loadComplete:) withObject:imageData waitUntilDone:NO];
[pool drain];
}
#end
and in the main class i have have this method that calls the PhotoViewController to load the selected photo
- (void) showPhotoAtUrl:(NSString *)url
{
PhotoViewController *vc = [[PhotoViewController alloc] initWithPhotoUrl:url];
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
Now my problem is how should i get the images after getting selected from the table to be open up in the same type of the view that open's up in FB app (open's the selected photo in portrait/landscape compatible view) i am only able to get one photo in my PhotoViewController class can any one tell me how can i add all the photo's to the PhotoViewController class so that i get the effect that i want ?... Any code help will be very helpful .. Thanks in Advance for contributing your time
In Short i have two things to do :
I have to restrict my project to only portrait mode leaving only the photo's view to have landscape/portrait compatibility.
I am currently having the photo's in my table view that i want on selection to open up in the same style(landscape/portrait compatibile) as FB or other app's do while viewing the photo's.
These only work on iOS 6.0
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationLandscapeLeft);
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
The method will return which orientation mode to use first.
Below are supportedInterfaceOrientations:
UIInterfaceOrientationMaskPortrait
UIInterfaceOrientationMaskLandscapeLeft
UIInterfaceOrientationMaskLandscapeRight
UIInterfaceOrientationMaskPortraitUpsideDown
UIInterfaceOrientationMaskLandscape
UIInterfaceOrientationMaskAll
UIInterfaceOrientationMaskAllButUpsideDown
For iOS > 4.0
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
Other ViewControllers will have
-(BOOL)shouldAutorotate { return NO; }
-(BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation{
return NO;
}
i have a custom cell for a table, is working fine,
Im showing a list of products in the cells, when the user touches a button "delete", i show an alert view to confirm deletion,
but I need to show the name of the product in the alert view: "are you sure you want to delete XXX?"
here the code for my custom cell
Please note the call to the alert view in deleteCartButtonPressed
#import "ShoppingCartProductsCell.h"
#import "Product.h"
#implementation ShoppingCartProductsCell
#synthesize categoryNameLabel = _categoryNameLabel;
#synthesize productNameLabel = _productNameLabel;
#synthesize quantityPicker = _quantityPicker;
#synthesize deleteCartButton = _deleteCartButton;
#synthesize product = _product;
- (void) dealloc {
[_deleteCartButton release];
[_categoryNameLabel release];
[_productNameLabel release];
[_quantityPicker release];
[super dealloc];
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
//self = [super initWithFrame:frame];
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
[self initQuantityPicker];
[self initLabels]; //y picker!
[self initButtons];
}
return self;
}
- (void) initQuantityPicker {
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
self.quantityPicker = [[[BDFDropDownList alloc] initWithFrame:CGRectMake(boundsX+220, 8, 61, 28) popupWidth:90]autorelease];
self.quantityPicker.delegate = self;
for (int i = 1; i<=20; i++) {
[self.quantityPicker addOptionWithName:[NSString stringWithFormat:#"%d",i] value:[NSNumber numberWithInt:i]];
}
[self.contentView addSubview:self.quantityPicker];
}
- (void) initLabels {
self.productNameLabel = [[[UILabel alloc]init] autorelease];
self.productNameLabel.textAlignment = UITextAlignmentLeft;
self.productNameLabel.backgroundColor = [UIColor clearColor];
self.productNameLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:15];
self.productNameLabel.textColor = [UIColor colorWithRed:102/255.0f green:102/255.0f blue:102/255.0f alpha:1];
[self.contentView addSubview:self.productNameLabel];
}
- (void) initButtons {
self.deleteCartButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.deleteCartButton addTarget:self action:#selector(deleteCartButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.deleteCartButton setImage:[UIImage imageNamed:#"deleteCartButton.png"] forState:UIControlStateNormal];
[self.contentView addSubview:self.deleteCartButton]; //Calculations For stage 2
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
CGRect frame;
frame= CGRectMake(boundsX+10 ,10, 200, 20);
self.productNameLabel.frame = frame;
frame= CGRectMake(boundsX+330 ,8, 30, 29); //310
self.deleteCartButton.frame = frame;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void) setProduct:(Product*)product {
[self setProduct:product withQuantity:0];
}
- (void) setProduct:(Product*)product withQuantity:(NSInteger)quantity {
[_product release];
_product = product;
[_product retain];
self.productNameLabel.text = product.SKU;
self.quantityPicker.delegate = nil;
[self.quantityPicker setSelectedIndex:quantity-1]; //testa
self.quantityPicker.delegate = self;
}
- (void) deleteCartButtonPressed:(id) sender {
NSLog(#"Delete ");
UIAlertView *deleteAlert = [[UIAlertView alloc]initWithTitle:#"Attention" message:#"Are you sure you want to delete this record?" delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[deleteAlert show];
[deleteAlert release];
}
#end
Thanks a lot!
string literals are your friend.
- (void) deleteCartButtonPressed:(id) sender {
NSLog(#"Delete ");
UIAlertView *deleteAlert = [[UIAlertView alloc]initWithTitle:#"Attention" message:[NSString stringWithFormat:#"Are you sure you want to delete %#?", [myTableDatasource objectAtIndex:idx]], delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok", nil];
[deleteAlert show];
[deleteAlert release];
}
It's probably best to move this out of your cell subclass and into your datasource and delegate so as to facilitate cleaner code.