How do I make sure a documents window remembers its position - nspersistentdocument

I am using a standard AppKit NSPersistentDocument document base application and would like a document's window to remember its location and open in the same position it was last closed in.
Note that setting the autosavename in IB on the Window will result in all documents opening in the same position. I want a document to remember its position based on the documents filename.
I have subclassed NSPersistentDocument and currently set the autosave name in the windowControllerDidLoadNib: function. This almost works fine, except that if I open and close the same document repeatedly without closing the App then each time its window's height is increased a small amount (26 pixels), almost like its doing the cascade thing. However if I close the App completely and reopen it then the document remembers its previous position exactly. Am I doing something wrong or is this a bug. Is there some cleanup I should be doing perhaps to ensure that the window is not being resized each time its re-opened.
// NSPersistentDocument subclass
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
LOG(#"windowControllerDidLoadNib called...");
[super windowControllerDidLoadNib:aController];
if ([self autoSaveName] != nil) {
[aController setWindowFrameAutosaveName:[self autoSaveName]];
}
[aController setShouldCascadeWindows:NO];
}
- (NSString*)autoSaveName
{
return [[self fileURL] lastPathComponent];
}
If I add the following code to add 22 pixels to its height
- (NSRect)windowPositionPreference {
LOG(#"printUserDefaults called");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *autosaveNameKey = [NSString stringWithFormat:#"NSWindow Frame %#", [self autoSaveName]];
NSString *frameString = [defaults objectForKey:autosaveNameKey];
NSArray *array = [frameString componentsSeparatedByString:#" "];
CGFloat x = [[array objectAtIndex:0] floatValue];
CGFloat y = [[array objectAtIndex:1] floatValue];
CGFloat width = [[array objectAtIndex:2] floatValue];
CGFloat height = [[array objectAtIndex:3] floatValue];
NSRect rect = CGRectMake(x, y, width, height+22);
FLOG(#" window frame = %fx, %fy, %fw, %fh", x, y, width, height);
return rect;
}
and then set the frame like so in - (void)windowControllerDidLoadNib:(NSWindowController *)aController
NSRect rect = [self windowPositionPreference];
[aController.window setFrame:rect display:YES];
The position seems to be retained exactly. Surely autosavename is just meant to work.

The above was still not working but after some messing about I gave up on using autosavename because of the automatic cascading that seems to be impossible to disable.
Now I just keep my own preferences and set the window frame using the code below. So far it seems to be working perfectly and I have not had to create my own subclasses of NSWindowController or NSWindow.
// Methods in subclassed NSPersistentDocument
- (void)windowControllerDidLoadNib:(NSWindowController *)aController {
[aController setShouldCascadeWindows:NO];
_mainWindow = aController.window;
[self restoreSavedWindowPosition];
}
- (void)close {
[self saveWindowPosition];
[super close];
}
- (void)saveWindowPosition {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *autosaveNameKey = [NSString stringWithFormat:#"OSWindow Frame %#", [self autoSaveName]];
[defaults setObject:[self stringFromFrame] forKey:autosaveNameKey];
}
- (void)restoreSavedWindowPosition {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *autosaveNameKey = [NSString stringWithFormat:#"OSWindow Frame %#", [self autoSaveName]];
NSString *frameString = [defaults objectForKey:autosaveNameKey];
// Do nothing if it has not been set
if (frameString) {
[_mainWindow setFrame:[self rectFromString:frameString] display:YES animate:YES];
}
else {
// Set the default for new docs
NSRect rect = CGRectMake(70, 350, 1000, 760);
[_mainWindow setFrame:rect display:YES animate:YES];
}
return;
}
// Use the filename as the preferences key
- (NSString*)autoSaveName {
return [[self fileURL] lastPathComponent];
}
- (NSString *)stringFromFrame {
NSRect rect = _mainWindow.frame;
rect.origin.y = rect.origin.y + 26;
rect.size.height = rect.size.height - 26;
return [self stringFromRect:rect];
}
- (NSString *)stringFromRect:(NSRect)rect {
return [NSString stringWithFormat:#"%f %f %f %f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height];
}
- (NSRect)rectFromString:(NSString*)string {
NSRect rect;
NSArray *array = [string componentsSeparatedByString:#" "];
rect.origin.x = [[array objectAtIndex:0] floatValue];
rect.origin.y = [[array objectAtIndex:1] floatValue];
rect.size.width = [[array objectAtIndex:2] floatValue];
rect.size.height = [[array objectAtIndex:3] floatValue];
return rect;
}

Related

Obtaining origin of Text from UITextView

-Goal: Get the Origin of a particular section of Text in a UITextView
Below is a link to a Screenshot of an app I am working on. Please view it as it is easier to explain with it.
Image Link: ScreenShot
This is a start to a Fill in the Blanks style game. I am currently trying to get the x,y coordinates of each of the underscores. When a word on the bottom of the screen is tapped it will move to the next available underscore space.
Currently I have written this code to do what I need, but it is very ugly, barely works AND is not very flexible. See Below:
// self.mainTextView is where the text with the underscores is coming from
NSString *text = self.mainTextView.text;
NSString *substring = [text substringToIndex:[text rangeOfString:#"__________"].location];
CGSize size = [substring sizeWithFont:self.mainTextView.font];
CGPoint p = CGPointMake((int)size.width % (int)self.mainTextView.frame.size.width, ((int)size.width / (int)self.mainTextView.frame.size.width) * size.height);
// What is going on here is for some reason everytime there is a new
// line my x coordinate is offset by what seems to be 10 pixels...
// So was my ugly fix for it..
// The UITextView width is 280
CGRect mainTextFrame = [self.mainTextView frame];
p.x = p.x + mainTextFrame.origin.x + 9;
if ((int)size.width > 280) {
NSLog(#"width: 280");
p.x = p.x + mainTextFrame.origin.x + 10;
}
if ((int)size.width > 560) {
NSLog(#"width: 560");
p.x = p.x + mainTextFrame.origin.x + 12;
}
if ((int)size.width > 840) {
p.x = p.x + mainTextFrame.origin.x + 14;
}
p.y = p.y + mainTextFrame.origin.y + 5;
// Sender is the button that was pressed
newFrame = [sender frame];
newFrame.origin = p;
[UIView animateWithDuration:0.2
delay:0
options:UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationCurveEaseInOut
animations:^{
[sender setFrame:newFrame];
}
completion:^(BOOL finished){
}
];
So the the best question for me to ask is
What is a better way of going about this? And or do you have any suggestions? How would you go about this?
Thank you for your time in advance.
Rather than manually searching each occurrence of the underscore. make use of NSRegularExpression Which makes your task so simple and easy. After the matched Strings are found then make use of the NSTextCheckingResult to get the location of each matched strings.
More Explaination:
You can make use of the regular expression inorder get all the occurence of the underscore.This is obtanied using the following code.
NSError *error = NULL;
NSString *pattern = #"_*_"; // pattern to search underscore.
NSString *string = self.textView.text;
NSRange range = NSMakeRange(0, string.length);
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *matches = [regex matchesInString:string options:NSMatchingProgress range:range];
Once you get all the Matching Patterns you can get the location of the matched strings using the following code.
[matches enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[NSTextCheckingResult class]])
{
NSTextCheckingResult *match = (NSTextCheckingResult *)obj;
CGRect rect = [self frameOfTextRange:match.range inTextView:self.textView];
//get location of all the matched strings.
}
}];
Hope this answers all your concerns!

Local high scores reporting/Display

Please can anyone refer me to a tutorial or help me out with this problem. I wish to display high scores and other games statistics at game Over but I don't seem to get a headway despite looking at tutorials and trying stuff out. I don't seem to understand how to use NSUserdefaults to achieve this.
My codes are as follows:
Gameplaylayer.mm
- (id)initWithHUDLayer:(HUDLayer *)hudLayer {
if ((self = [super init]))
{
score = 0;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *defaultArray = [NSDictionary dictionaryWithObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:0],
[NSNumber numberWithInt:0],
[NSNumber numberWithInt:0],
[NSNumber numberWithInt:0],
[NSNumber numberWithInt:0],
nil]
forKey:#"Scores"];
[defaults registerDefaults:defaultArray];
[defaults synchronize];
}
return self;
}
-(void)gameOver:(id)sender{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *HighScores = [NSMutableArray arrayWithArray:[defaults arrayForKey:#"Scores"]];
for (unsigned int i = 0; i < [HighScores count]; i++)
{
if (dist >= [[HighScores objectAtIndex:i] intValue])
{
[HighScores insertObject:[NSNumber numberWithInt:dist] atIndex:i];
[HighScores removeLastObject];
[defaults setObject:HighScores forKey:#"Scores"];
[defaults synchronize];
NSLog(#"Saved new high score of %i", dist);
break;
}
}
}
-(void)update:(ccTime)dt {
CGSize winSize = [CCDirector sharedDirector].winSize;
score += (int)delta;
dist = score - 18;
if (!gameOver )
{
if (!lives)
{
gameOver = true;
[self gameOver];
}
}
}
my game over layer is as follows
-(id)init {
self = [super init];
if (self != nil)
{
self.isTouchEnabled = YES;
CGSize windowSize = [CCDirector sharedDirector].winSize;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *HighScores = [defaults arrayForKey:#"Scores"];
CLabelTTF *title = [CCLabelTTF labelWithString:#"high scores" fontName:#"Courier" fontSize:32.0];
[title setPosition:ccp(screenSize.width / 2, screenSize.height - title.contentSize.height)];
[self addChild:title];
NSMutableString *scoresString = [NSMutableString stringWithString:#""];
for (unsigned int i = 0; i < [HighScores count]; i++)
{
[scoresString appendFormat:#"%i. %i\n", i + 1, [[HighScores objectAtIndex:i] intValue]];
}
CCLOG(#"scores saved %i", dist);
CCLabelTTF *scoresLabel = [CCLabelTTF labelWithString:scoresString dimensions:CGSizeMake(screenSize.width, screenSize.height / 3) alignment:CCTextAlignmentCenter fontName:#"Courier" fontSize:40.0];
[scoresLabel setPosition:ccp(screenSize.width / 2, screenSize.height / 2)];
scoresLabel.color = ccc3(0, 0, 0);
[self addChild:scoresLabel z:9];
}
return self;
}
It's hard to understand your code, please look at this small example below.
Ok, that's saving new score, assuming you have GameController singleton, where scores mutable array is declared and currentScore in that singleton also displays current player's score.
-(void) saveScores {
GameController * controller = [GameController sharedController];
for(int i=0; i<5;i++)
{
if([[[controller.scores objectAtIndex:i] objectForKey:#"score"] intValue] == controller.finalscore)
{
break;
}
if([[[controller.scores objectAtIndex:i] objectForKey:#"score"] intValue] < controller.finalscore) {
for(int j=5;j>i+1;j--)
{
[controller.scores replaceObjectAtIndex:j-1 withObject:[controller.scores objectAtIndex:j-2]];
}
NSMutableDictionary *newEntry = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:controller.finalscore],#"score",#"Local player",#"name", nil];
[controller.scores replaceObjectAtIndex:i withObject:newEntry];
break;
}
}
controller.currentScore=0;
[[NSUserDefaults standardUserDefaults] setObject:controller.scores forKey:#"OurScores"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
You can see, that we are saving updated scores in NSUserDefaults. So, at our game start we shoul load them. I added this code to GameController init method:
- (void) loadScores {
if([[NSUserDefaults standardUserDefaults] objectForKey:#"OurScores"] == nil)
{
NSMutableDictionary *empty = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:0],#"score",#"empty",#"name", nil];
for(int i=0;i<5;i++)
[scores addObject:empty];
}
else
{
NSLog(#"Loading scores");
scores = [[NSUserDefaults standardUserDefaults] objectForKey:#"OurScores"];
}
}
And that's how we can show this scores using cocos2d:
-(void) drawScores {
for(int i=0; i<5; i++)
{
CCLabelTTF* score = [CCLabelTTF labelWithString:
[NSString stringWithFormat:#"%#",[[controller.scores objectAtIndex:i] objectForKey:#"name"]] fontName:#"Marker Felt" fontSize:30];
score.anchorPoint=ccp(0,0);
score.position = ccp(115, 180-i*35);
CCLabelTTF* score2 = [CCLabelTTF labelWithString:
[NSString stringWithFormat:#"%d",[[[controller.scores objectAtIndex:i] objectForKey:#"score"] intValue] ] fontName:#"Marker Felt" fontSize:35];
score2.anchorPoint=ccp(0,0);
score2.position = ccp(280, 180-i*35);
score.color=currentClr;
score2.color=currentClr;
[self addChild: score z:3 tag:i];
[self addChild: score2 z:3 tag:i+15];
}
}
Your code has a number of problems, some of which just break with convention but all together they make your program quite unreadable. I have not been able to make sense of it. You are not using comments, nor are you telling us, what exactly is not working.
For instance, you might consider following the convention of having instance variables start with small letters, reserving capitalized names for classes. It is generally a bad idea to give misleading names, such as calling an NSDictinoary "defaultArray". Also, try to use empty lines more sparingly to structure your code for better readability.
That being said, this is how you set a default value:
[[NSUserDefaults standardUserDefaults] setValue:scoreArray
forKey:#"Score"];
I see you know how to retrieve the score.
As for your updating routine, consider that it is normally not a good idea to modify the array your iterating through (in your particular case it could still work, but it is not guaranteed). Also, there is no need to store the whole array in the loop. Just save it once you have contructed the complete new high score array.
Otherwise your code is working, right?

How to save MKMapRect in a plist

I am creating a MKMapView application and in need to save a couple MKMapRect type variables in a plist so as to refer them when need.
I know that MKMapRect has MKMapPoint origin and MKMapSize size. And they each have 2 double values that can be saved as nsnumber but saving all of them seems to be a lot of work and top of that i have to read the values back and convert them into a MKMapRect variable.
So my question is that, is there any easy way to store a MKMapRect and retrive it back from a plist.
Thanks,
Robin.
Use MKStringFromMapRect to turn it into a string.
There:
- (NSString *)save:(MKMapRect)rect
{
return MKStringFromMapRect(rect);
}
- (MKMapRect)load:(NSString *)str
{
MKMapRect mapRect;
CGRect rect = CGRectFromString(str);
mapRect.origin.x = rect.origin.x;
mapRect.origin.y = rect.origin.y;
mapRect.size.width = rect.size.width;
mapRect.size.height = rect.size.height;
return mapRect;
}
I made a category to save the map rect to the user defaults:
NSUserDefaults+MKMapRect.h
#interface NSUserDefaults (MKMapRect)
//stores a map rect in user defaults
-(void)setMapRect:(MKMapRect)mapRect forKey:(NSString*)key;
//retrieves the stored map rect or returns the world rect if one wasn't previously set.
-(MKMapRect)mapRectForKey:(NSString*)key;
#end
NSUserDefaults+MKMapRect.m
#implementation NSUserDefaults (MKMapRect)
-(void)setMapRect:(MKMapRect)mapRect forKey:(NSString*)key{
NSMutableDictionary *d = [NSMutableDictionary dictionary];
[d setObject:[NSNumber numberWithDouble:mapRect.origin.x] forKey:#"x"];
[d setObject:[NSNumber numberWithDouble:mapRect.origin.y] forKey:#"y"];
[d setObject:[NSNumber numberWithDouble:mapRect.size.width] forKey:#"width"];
[d setObject:[NSNumber numberWithDouble:mapRect.size.height] forKey:#"height"];
[self setObject:d forKey:key];
}
-(MKMapRect)mapRectForKey:(NSString*)key{
NSDictionary *d = [self dictionaryForKey:key];
if(!d){
return MKMapRectWorld;
}
return MKMapRectMake([[d objectForKey:#"x"] doubleValue],
[[d objectForKey:#"y"] doubleValue],
[[d objectForKey:#"width"] doubleValue],
[[d objectForKey:#"height"] doubleValue]);
}
#end
You could probably copy the MKMapRect data in a CGRect, then store the CGRect as a string with NSStringFromgCGRect() and CGRectFromString()

iphone - SetNeedsDisplay not working

I'm trying to refresh my main view in this code. It shows the right sub-view, but it's keeping the other views already shown. I already tried setNeedsDisplay and setNeedsLayout but no success.
Any ideas?
Code:
-(void)setViewsForLecture:(NSString *)date{
int scrollHeight = 0;
[self.view setNeedsDisplay];
FMDatabase* db = [DatabaseManager openDatabase];
NSString *query = [NSString stringWithFormat:#"select * from tbl_lectures where day like \"%%%#%%\" ", date];
FMResultSet *rs= [db executeQuery:query];
//Counts how many lectures
int position = 0;
while ([rs next]) {
NSMutableArray *speakers = [[NSMutableArray alloc] initWithCapacity:30];
NSString *lectureName = [rs stringForColumn:#"lecturename"];
FMResultSet *speakersList = [db executeQuery:#SELECT_SPEAKER_FOR_LECTURE, lectureName];
while ([speakersList next]) {
[speakers addObject:[speakersList stringForColumn:#"speaker"] ];
}
if ([speakers count] % 2 == 0)
{
scrollHeight += [speakers count]*40;
}
else
{
scrollHeight += (1 + ([speakers count] -1)/2)*40;
}
NSLog(#"Csantos: speakers for %#: %i",lectureName, [speakers count]);
UIView *aLecture = [CustomInterface viewForLecture:[rs stringForColumn:#"lecturename"]
onPosition:position
withSpeakers:speakers];
[self.scroll addSubview:aLecture];
[aLecture release];
[speakers release];
scrollHeight += 280;
position++;
}
self.scroll.contentSize = CGSizeMake(300, scrollHeight);
[db release];
}
Regards!
Try calling
[self.view setNeedsDisplay];
at the end of the method, after you've made the changes.
I got it working!
I think I didn't understand exactly how setNeedsDisplay works. In this case, was it supposed to redraw my ScrollView too?
Anyway, here is the code that works now:
-(IBAction)clickOnDate1{
for (UIView *view in [self.scroll subviews]) {
[view removeFromSuperview];
}
NSLog(#"Date1 clicked");
[self setViewsForLecture:#"4"];
}
and thanks PengOne for trying to help!

UIImage problem

I am loading the images of size 450KB in UIImage view and then adding it to UIscrollview. while am scrolling the 30 images continously,its getting crashed.. what may be the reason..is this memory leak issue...or image size is the problem...? thanks in advance..
here is my code ..
#try{
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
//NSArray *array = [global_ContentString componentsSeparatedByString:#"###"];
NSArray *array1 = [catalogURL componentsSeparatedByString:#"&"];
//**NSLog(#"array1****** = %#",array1);
NSLog(#"loading catalog image(method: loadCatalogImage).......%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]);
//NSLog(#"baseURL = %#",baseURL);
NSLog(#"loading catalog image.......%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]);
zoomedImageURL = [NSString stringWithFormat:#"%#%#", baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:1]];
[zoomedImageURL retain];
NSLog(#"aaaaaaaaaaaaaa = %#",zoomedImageURL);
//UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",baseURL, [[[array1 objectAtIndex:0] componentsSeparatedByString:#"##"] objectAtIndex:0]]]]];
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]];
imgView.contentMode = UIViewContentModeScaleAspectFit;
imgView.image = img;//[GPSTripTracking generatePhotoThumbnail:img:109];
[pool release];
[global_imgProgress stopAnimating];
}
#catch (NSException *e) {
[global_imgProgress stopAnimating];
NSLog(#"Exception....");
}
#finally {
}
am releasing my imgView in dealloc method..
i imlemented the following code in "scrollviewdidscroll"
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
// which a scroll event generated from the user hitting the page control triggers updates from
// the delegate method. We use a boolean to disable the delegate logic when the page control is used.
if (pageControlUsed) {
// do nothing - the scroll was initiated from the page control, not the user dragging
//pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage +1), pageControl.numberOfPages];
pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage ), pageControl.numberOfPages];
//NSLog(#"not scrollling page....");
return;
}
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
//NSLog(#"scrolling page....%d", page);
// A possible optimization would be to unload the views+controllers which are no longer visible
}
and my code for " loadScrollViewWithPage" is
- (void)loadScrollViewWithPage:(int)page
{
//page--;
if (page < 0) return;
if (page >= numberOfPages) return;
if(!isViewCatalog && searchId == 1)
{
//NSLog(#"curre page = %d",pageControl.currentPage);
NSArray *array1 = [global_ContentString componentsSeparatedByString:#"###"];
if(searchInCatalogFlag == 1)
{
pageControl.currentPage=0;
NSArray *urlArray = [[array1 objectAtIndex:pageControl.currentPage] componentsSeparatedByString:#"##"];
//NSLog(#"url array** = %#",urlArray);
headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
pageText.text = [NSString stringWithFormat:#"%d/%d", pageControl.currentPage, (pageControl.numberOfPages - 1)];
}
else
{
NSArray *urlArray = [[array1 objectAtIndex:pageControl.currentPage] componentsSeparatedByString:#"##"];
//NSLog(#"url array** = %#",urlArray);
headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
pageText.text = [NSString stringWithFormat:#"%d/%d", pageControl.currentPage, (pageControl.numberOfPages - 1)];
}
if(page == selectedPage && ![global_imgProgress isAnimating])
[global_imgProgress startAnimating];
}
else
{
headerText.text = [NSString stringWithString:global_SelectedCatalogName];
pageText.text = [NSString stringWithFormat:#"%d/%d", (pageControl.currentPage + 1), (pageControl.numberOfPages - 1)];
if(page == selectedPage + 1 && ![global_imgProgress isAnimating] )
[global_imgProgress startAnimating];
// NSLog(#"header text = %#", headerText.text);
//headerText.text = [NSString stringWithString:[urlArray objectAtIndex:0]];
}
FullPageView *controller = [viewControllers objectAtIndex:page];
if ((NSNull *)controller == [NSNull null] ) {
//NSLog(#"Loading page =========== %d, %d", page, selectedPage);
//voucherPageNo = page;
//[voucherImage retain];
if(universalApp==2)
{
controller = [[FullPageView alloc] initWithNibName:#"FullPageView_iphone" bundle:nil];//:page];
[controller.view setFrame:CGRectMake(0, 0, 320,332)];
}
else
{
controller = [[FullPageView alloc] initWithNibName:#"FullPageView" bundle:nil];//:page];
[controller.view setFrame:CGRectMake(0, 192, 768, 691)];
}
//[controller.view setFrame:CGRectMake(0, 0, 320,480)];
//[controller.view setFrame:CGRectMake(0, 192, 768, 691)];
if((!isViewCatalog && searchId < 2 && searchInCatalogFlag == 0))// || searchInCatalogFlag == 1)
{
// NSLog(#">>>>>>>>>>>>>>>>>> LOADING IMAGE >>>>>>>>>>>>>>>>>>>>");
[controller setPageNo:page];
// if(page >= selectedPage - 1)
[NSThread detachNewThreadSelector:#selector(loadImage) toTarget:controller withObject:nil];
}
else //if((page >= (selectedPage - 1) && page <= (selectedPage + 1)) || !isFirstTimeLoading)
{
NSLog(#"Loading CATALOG IMAGE = %d, %d, %#", page, selectedPage, (isFirstTimeLoading ?#"YES" : #"NO"));
[controller setCatalogURL:[NSString stringWithFormat:#"%#", [catalogArray objectAtIndex:page+(searchId< 2 && !isViewCatalog && searchInCatalogFlag == 0?0:1)]]];
NSLog(#"loading image ipad= %#", [catalogArray objectAtIndex:page+(searchId< 2 && !isViewCatalog && searchInCatalogFlag == 0?0:1)]);
// if(page >= selectedPage - 1)
[NSThread detachNewThreadSelector:#selector(loadCatalogImage) toTarget:controller withObject:nil];
// if(page == (selectedPage + 1))
//isFirstTimeLoading = NO;
}
[viewControllers replaceObjectAtIndex:page withObject:controller];
[controller release];
}
// add the controller's view to the scroll view
if (nil == controller.view.superview)
{
// NSLog(#"Voucher view addead at page..... %d", page);
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
// NSLog(#">>>>>>>>> %f, %f", frame.size.width, frame.origin.x);
[scrollView addSubview:controller.view];
}
//if(page == pageControl.currentPage)
//[imgProgress startAnimating];
//else
//pageControlUsed = YES;
}
where wil be the problem..?
450KB is the compressed image size. When an image is loaded into memory, it is uncompressed.
A rule of thumb for working out how much memory an uncompressed image will occupy is:
width * height * 4
With 30 images it is very likely that you're running out of memory.
You should write your code to only keep images in memory if they are visible on screen.
It very likely that your program gets terminated by iOS because it consumes too much memory. Start it from XCode and look at the console - it will probably print that it receives memory warnings.
You will have to load the images on demand, i.e. only when the user gets close to seeing them, and you will have to release the ones that move out of view again. To that end, implement the
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
delegate method, look at the scroll view's content offset and load/release the appropriate images. Alternatively, you can choose to not release them there but instead wait for a memory warning to do so. To do so, implement the
- (void)didReceiveMemoryWarning
method in your view controller.
This might be the issue of memory leaks.
Try to replace this line
UIImage *img = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]]
and use this
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",zoomedImageURL]]]];
<<<<<YOUR CODE>>>>
[img release];
I hope this helps