Hello i'm trying to write a method that update a UIProgressbar !
The problem is that when both of values arrive fine to the method (NSLog display values)
the division operation generate a bad_access when i run the application !!
I tried many messages from both value like intValue/inValue ...
Help me to solve this issue and how can I print values of NSNumber
-(void)UpdateProgressbar:(NSNumber *)currentOperationNumer TotalOperationNumber:(NSNumber*)n
{
NSLog(#" operation : %i",currentOperationNumer);
NSLog(#" total : %i",n);
if (currentOperationNumer<=n)
{
[downloadBar setProgress:(currentOperationNumer/n )];
NSLog(#"progress !");
}
else
{
[self.view removeFromSuperview];
}
}
try [currentOperationNumber intValue] in place of currentOperationNumber (or floatValue if setProgress expects a float). So....
int myProgress = [currentOperationNumber intValue] / [n intValue];
[downloadBar setProgress:myProgress];
Actually, isn't it a float value it expects in there?
NSNumber is an object wrapper for various primitive types, with what you are doing you are trying to divide a pointer by a pointer..
maybe try chaining the code to..
[downloadBar setProgress:([currentOperationNumer intValue] / [n intValue])];
You can print value by using following code
-(void)UpdateProgressbar:(NSNumber *)currentOperationNumer TotalOperationNumber:(NSNumber*)n
{
NSLog(#" operation : %#",currentOperationNumer);
NSLog(#" total : %#",n);
if (currentOperationNumer<=n)
{
[downloadBar setProgress:(currentOperationNumer/n )];
NSLog(#"progress !");
}
else
{
[self.view removeFromSuperview];
}
}
The best way to debug EXC_BAD_ACCESS:
If you are not using XCode 4, then upgrade.
In XCode 4, press CMD-I to run Instruments.
Select the Zombies profile. (Background: EXC_BAD_ACCESS means you are sending a message to a deallocated object. Zombies turns on the zombie feature, so that objects with a retain count of 0 are not deallocated, but kept as a zombie. The NSZombie class raises an exception whenever a message is sent to it - thus it can be trapped, and identified the point of origin.)
Run your app via Instruments. When it crashes, Instruments will be brought to the foreground with a pop-up callout that indicates the memory that was freed but accessed.
You can click the little arrow in the lower right corner, this will give you that memory's alloc/retain/release history, and the code that performs the action. Click on the source column, it will take you to that line in the code.
make it sure downloadBar.progress is a float and it's from 0.0 to 1.0 inclusive.
Please, try this:
float current = 0.0f;
float count = 100.0f;
while (stuff..) {
downloadBar.progress = current / count;
}
it should work without problems.
Related
I'm handling RemoteIO to get mic inputs and modify them little.
Sometimes it crashes with EXC_BAD_ACCESS and there is no more message.
The lines that make crashes are these;
int currPower = [[powers objectAtIndex:i] intValue];
int prevPower = [[powers objectAtIndex:i - 1] intValue];
explaining the code,
"powers" is NSMutableArray.
[powers count] was always bigger than variable "i"
Struggling for a while, I found a good way to fix it.
A environment variables.
So I set NSZombieEnabled and also NSDebugEnabled so that I could see the reason of the crashes.
But even though I set the variables, Xcode shows no message.
(But it correctly shows messages when a crash occurs from other line.)
Also a weird thing is that it doesn't crash just after the start of run;
it crashes in a minute in average. (But the times really varied.)
And this is a little guess. When I decreased the rate to half than before,
it was more stable.
So, is it a problem with NSMutableArray, because NSMutableArray method couldn't catch up the speed of the rate?
or do you see some other possible reasons?
=========================================================================================
There are some more codes.
I allocated powers in this way..
powers = [[NSMutableArray alloc] initWithCapacity:POWER_ARRAY_SIZE];
where I release the powers array is..
- (void)dealloc {
[powers release];
[super dealloc];
}
and no where else.
more detailed code is this.
- (void)drawRect:(CGRect)rect
{
...//Do Something
...//Check "endindex" and "startindex" not to exceed boundary
for (int i = endindex; i > startindex; i-=1)
{
int currPower = [[powers objectAtIndex:i] intValue];
int prevPower = [[powers objectAtIndex:i - 1] intValue];
...//Doing something
}
}
this drawRect: method is calling from Main Thread(By Timer) in every millisecond.
--
updating(more specifically adding) powers in this method
- (void)setPower:(int)p
{
[powers addObject:[NSNumber numberWithInt:p]];
while ([powers count] > POWER_ARRAY_SIZE){
[powers removeObjectAtIndex:0];
}
}
and also this method is calling in every millisecond.
and this is calling in background thread.
so without #autoreleasepool XCode Shows message of alert of leaking
for this reason I blocked the method(setPower) with #autoreleasepool{..}
If NSZombies solved your problem it means that your NSMutableArray is being released somewhere, or it's in an autorelease pool. Also you could be trying to write outside the bounds of your array.
If the NSMutableArray is in an autorelease pool (it was created by a convenience method or you explicitly autoreleased it) manually retain it and release it when you no longer need it.
If the object is not in an autorelease pool check when the release is called for that object.
Write a simple warning before the assignment:
if( i <= 0 || i >= [powers count] ) NSLog(#"Here's the problem. i = %d", i);
I found the answer.
Crashes are occurred because NSMutableArray of objected-C sometimes ack wrong.
That's when I try to do something in every milliseconds with it.
So I changed the Objective-C array to C array, like
int power[ARRAYSIZE];
and after I changed it, it works fine.
May be NSMutableArray isn't that light to do something really fast.
I'm trying to get the basics of iOS programming down. I have an app that shows a random number when I click a button.. At least, that's what I wanted to make. However, it doesn't seem to be working out.
I have the following basic method which should set the text of myLabel to the return value of generateRandomNumber. However, it always returns 0. I think the syntax I'm using here is correct since it works for the commented parts:
-(IBAction)myBtnPressed:(UIButton *)sender
{
//[myLabel setText:#"test"];
//[myLabel setText:[NSString stringWithFormat:#"%g / 15", 3.14]];
[myLabel setText:[NSString stringWithFormat:#"%g / 15", [myModel generateRandomNumber]]];
}
The last line sets the label to display 0/15. However, in my model, I have the following code ('static' for now):
-(double)generateRandomNumber
{
randomNumber = 1.34;
return randomNumber;
}
It doesn't return the 1.34 and I don't understand why it doesn't. Can someone clear this up?
Update
This is the code for my viewcontroller.m file:
#import "myViewController.h"
#implementation myViewController
-(MyModel *)myModel
{
if (! myModel) {
myModel = [[MyModel alloc] init];
}
return myModel;
}
-(IBAction)myBtnPressed:(UIButton *)sender
{
[myLabel setText:[NSString stringWithFormat:#"%g / 15", [myModel generateRandomNumber]]];
}
#end
Also, in the end, I want to make generateRandomNumber return a random number between 0 and 15. How would I do this? Would a simple line like:
int x = arc4random() % 16;
work for this? Or do I have to seed it in some way so it doesn't always return the same values when I run the application?
Thanks in advance.
It doesn't return the 1.34 and I don't understand why it doesn't. Can someone clear this up?
Almost certainly, you haven't allocated and initialised the myModel object. You can send messages to nil without crashing but the return value will be 0.
arc4random() doesn't need a seed.
Edit
Your init code looks OK but you are not calling int, in your myBtnPressed: method, you need
[myLabel setText:[NSString stringWithFormat:#"%g / 15", [[self myModel] generateRandomNumber]]];
Are you instantiating an object of your model type? I'm asking because you say that you have declared the function in myModel.h (Could be a typo).
And yes - to get a random number between 0 and X:
int rand = arc4random() % X;
And you don't need to seed the generator.
To return a double between 0 and 15:
// define this somewhere
#define ARC4RANDOM_MAX 0x100000000
// and then use this
double val = floorf(((double)arc4random() / ARC4RANDOM_MAX) * 15.0f);
random-thoughts-rand-vs-arc4random.html for more.
Did you ever alloc/create the myModel object?
I'm guessing that you didn't, and you're just trying to use the class as a 'methods' class that doesn't store anything (I know there's a name for it, but I'm self taught so my terminology is pretty horrible!)
You can do this in objective-c, but you've got to use different syntax. Instead of using minus signs for the method declaration, use "+":
+(double)generateRandomNumber;
and now your method should be usable!
I have a set of animations that need to operate sequentially with various checking done at each step. Because the size of the set is determined at run time, I expected to utilize a recursive call... but I am having trouble getting it to function within the 'block' paradigm.
The result is an EXEC_BAD_ACCESS regardless of whether I predeclared the block using
__block void (^myBlock)(BOOL) = ^(BOOL finished){ if (finished) [self nextStep];};
or not, as seen in the following code snippet. Upon debugging, it appears that the 'self' variable is indeed valid.
NSEnumerator* stepEnumerator;
-(void) mainRoutine {
stepEnumerator = [myArray objectEnumerator];
[self nextStep];
}
-(void) nextStep {
id obj;
if ((obj = [stepEnumerator nextObject])) {
// Do my checking at each location
....
// we have another spot to move to
[UIView animateWithDuration:animationDuration
animations:^{self.frame = newFrame;}
completion:^(BOOL finished){ if (finished) [self nextStep];}];
}
}
else {
// we are done, finish house cleaning
}
}
Any help is greatly appreciated.
Thanks!
The answer to the question posed is, yes, recursive calls within a block completion are valid.
#BillBrasky brought up a good point about the block losing scope. I do not know enough to say if this is required or not as I have not found it to be an issue with my situation. Everything appears to work correctly for me on each successive iteration through my recursive function.
The core issue with the code as I originally wrote it and submitted it is the use of the FastEnumerator. This is DEFINITELY lost when you leave the current function and venture out into another event loop / new section of the stack frame. I realized as I thought more about it that there is probably quite a bit going on behind the scenes to make FastEnumeration work and it is quite logical that leaving the method would destroy the setup.
As a fix, I replaced the NSEnumerator with a simple integer that I then increment each time through the recursive function. I am not a big fan of this as it could lead to Out of Bounds style issues where as the FastEnumerator will not, nor will for (obj in array), but I don't know of another solution. I think I will post that as a separate question...
Corrected code:
int index;
-(void) mainRoutine {
index = 0;
if (index < [myArray count]) {
[self nextStep];
}
}
-(void) nextStep {
// obtain the object from the array
id obj = [myArray objectAtIndex:index++];
// do my checking on the object
...
[UIView animationWithDuration:animationDuration
animations:^{self.frame = [view frame];}
completions:^(BOOL finished) {
if (finished && index < [myArray count]) {
[self nextStep];
}
else {
// We are done, clean up
...
}
}];
}
Thanks again #BillBrasky, you helped point me down the correct path to resolve this. I was too focused on the recursion and my quick analysis of my 'self' object looked fine because everything except for one item was fine. Couple that with the debugger breaking on the block, not the actual offending line and who knows how long I would have been staring at the code without seeing the real issue.
Cheers.
I'm new to blocks too, but I just got done with a similar issue. In my case, the EXEC_BAD_ACCESS was caused because the block had gone out of scope. I suspect that sometime in your 2nd recursion, the block gets created with an odd stack frame because it's executing inside another block.
My solution was to keep the blocks in a property marked copy, e.g.
#property (nonatomic,copy) BOOL (^callback)(DownloadProgress*);
This ensures that everything is retained in a copy in case the original block object goes out of scope and is GC'd.
OK, This is a method from my program that keeps giving the EXC_BAD_ACCESS error and crashing. I indicated the line below. questionsShown is a readwrite property and points to an NSMutableArray that I initialize with a capacity of 99 at an earlier point in the program. When I debug everything appears normal in terms of the property being allocated. I assumed there must be some issue with memory management but I am having serious trouble finding the problem. Thanks in advance for any help.
#synthesize questionList;
#synthesize questionLabel;
#synthesize questionsShown;
-(IBAction)next{
int numElements = [questionList count];
int r;
if (myCount == numElements){
[questionLabel setText:#"You have seen all the questions, click next again to continue anyways."];
[questionsShown release];
questionsShown = [[NSMutableArray alloc] initWithCapacity:99];
myCount = 0;
}
else {
do {
r = rand() % numElements;
} while ([questionsShown indexOfObjectIdenticalTo:r] != NSNotFound);
NSString *myString = [questionList objectAtIndex:(NSUInteger)r];
[questionLabel setText:myString];
myCount++;
[questionsShown addObject:r]; //results in crash with message EXC_BAD_ACCESS
myCount++;
}
}
The EXC_BAD_ACCESS is coming from dereferencing r, which is just an integer. Your compiler should be giving you a warning (make pointer from integer without a cast) on that line.
If questionsShown is supposed to be some kind of index set for you (which it appears to be), you might want to either use that class, or you will have to box your integer in an NSNumber object. So:
[questionsShown addObject:[NSNumber numberWithInt:r]];
and when you read it:
[questionsShown indexOfObjectIdenticalTo:[NSNumber numberWithInt:r]]
I recommend, however, that you take a look at the NSIndexSet documentation.
With a mutable index set, you could do:
[questionsShownIndexSet containsIndex:r]
and
[questionsShownIndexSet addIndex:r]
I have looked at other answers and the docs. Maybe I am missing something, or maybe I have another issue. I am trying to save a number on exiting the app, and then when the app is loaded I want to check if this value exists and take action accordingly. This is what I have tried:
To save on exiting:
- (void)applicationWillTerminate: (UIApplication *) application
{
double save = [label.text doubleValue]; // This could be the issue
//double save = 3.5; // This works, it saves the value and loads it fine, so that is not the problem here.
[[NSUserDefaults standardUserDefaults] setDouble: save forKey: #"savedNumber"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
To check:
- (IBAction)buttonclickSkip{
double save = [[NSUserDefaults standardUserDefaults] doubleForKey: #"savedNumber"];
if (save == 0) {
[self performSelector:#selector(displayAlert) withObject:nil];
test.enabled = YES;
test.alpha = 1.0;
skip.enabled = NO;
skip.alpha = 0.0;
}
else {
label.text = [NSString stringWithFormat:#"%.1f %%", save];
}
}
The problem is I always get my alert message displayed, the saved value is not put into the label so somehow == 0 is always true. Why would:
double save = [label.text doubleValue];
always equal zero? Before I close the app the number in that label is roughly 0.5% (it varies). If it makes any difference I am testing this on the iPhone simulator.
Many thanks,
Stu
The fact that you can hard-code the value and fetch it back means the problem definitely revolves around your interaction with the label.text and not your use of NSUserDefaults.
Make sure that the label has not already been destroyed at the time you go to fetch its value. As the application is terminating it may have already brought down the view from which you are fetching the value.
Another thing to try would be to get the actual text itself instead of asking the OS to convert the text value into a number first. If you print that out you may get some clue as to what is going on.
Make sure that your applicationWillTerminate: implementation is in your app delegate class.
My guess would be that the text in your label is not a valid double value. From the Apple docs for NSString -doubleValue:
Returns 0.0 if the receiver doesn’t
begin with a valid text representation
of a floating-point number.
Make sure you are passing it something like #"13.2". The best way to check this is to stick a NSLog call right after you create the variable save.