不需要的财产变更

时间:2014-10-21 21:37:22

标签: objective-c cocoa

使用在Yosemite上运行的XCode 6.0.1。我有一个属性被设置为用户键入文本框的值,例如“090”。

//
//  AppController.h
//

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "ORSSerialPort.h"
#import "ORSSerialPortManager.h"

@class ORSSerialPortManager;

#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_7)
  @protocol NSUserNotificationCenterDelegate <NSObject>
@end
#endif

@interface AppController : NSObject <ORSSerialPortDelegate,NSUserNotificationCenterDelegate>

@property (nonatomic, retain) NSString *hdgVal;

- (void)printHdg;
@end

稍后,我需要整数值进行比较。在标记为“CRASH HERE”的行中,当我点击hdgVal时,气泡会显示“class name = _NSArrayI”。点击眼球,表示值为10,10,0。

//
//  AppController.m
//


#import "AppController.h"
@implementation AppController

@synthesize hdgVal;

- (void)startTimer
{
    hdgTimer = [NSTimer scheduledTimerWithTimeInterval:0.6 
                                                target:self
                                              selector:@selector(printHdg)
                                              userInfo:nil
                                               repeats:YES];
}

- (void)printHdg
{
    NSInteger currH = [labelCurrHdg integerValue];
    NSInteger wantedH = [hdgVal integerValue];  <== CRASH HERE
    NSData *dataToSend;
    NSString *str;
    if (currH > wantedH - 3 && currH  < wantedH + 3) {
        [hdgTimer invalidate];
        hdgTimer = nil;
        [labelCurrHdg setStringValue:hdgVal];
        [labelCurrHdg needsDisplay];
        NSLog(@"Stopping timer");
        return;
    }

填写hdgVal的代码

- (IBAction)send:(id)sender
{

NSString *sendString = @"";
NSString *tmpStr;
NSString *tmpVal;
NSData *dataToSend;
int i;
int c;
char j;
if([sender tag] ==1)
{
    NSButton *btn=(NSButton *)sender;
  [btn setTitle:([btn.title isEqualToString:@"LP"] ? @"SP" : @"LP")];
    i = [inputTextField intValue];
    if(i < 181)
    {
        i = i + 180;
    }
    else if (i > 180)
    {
        i = i - 180;
    }
    NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setPaddingPosition:NSNumberFormatterPadBeforePrefix];
    [numberFormatter setPaddingCharacter:@"0"];
    [numberFormatter setMinimumIntegerDigits:3];
    NSNumber * number = [NSNumber numberWithInt:i];
    tmpStr = [numberFormatter stringFromNumber:number];
    [numberFormatter release];
    [inputTextField setStringValue:tmpStr];
    hdgVal = tmpStr;
}
else if([sender tag] == 0)
{
    [buttonLP setTitle:@"LP"];
    tmpStr = [inputTextField stringValue];
    while([tmpStr length] < 3)
    {
      tmpStr = [@"0" stringByAppendingString:tmpStr];
    }
    [inputTextField setStringValue:tmpStr];
    hdgVal = tmpStr;
}
else if([sender tag] ==3)
{
    NSButton *btn=(NSButton *)sender;
  [btn setTitle:([btn.title isEqualToString:@"LP"] ? @"SP" : @"LP")];

    i = [inputTextField2 intValue];
    if(i < 181)
    {
        i = i + 180;
    }
    else if (i > 180)
    {
        i = i - 180;
    }
    NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setPaddingPosition:NSNumberFormatterPadBeforePrefix];
    [numberFormatter setPaddingCharacter:@"0"];
    [numberFormatter setMinimumIntegerDigits:3];
    NSNumber * number = [NSNumber numberWithInt:i];
    tmpStr = [numberFormatter stringFromNumber:number];
    [numberFormatter release];
    [inputTextField2 setStringValue:tmpStr];
    hdgVal = tmpStr;
}
else if([sender tag] == 2)
{
    [buttonLP2 setTitle:@"LP"];
    tmpStr = [inputTextField2 stringValue];
    while([tmpStr length] < 3)
    {
      tmpStr = [@"0" stringByAppendingString:tmpStr];
    }
    [inputTextField2 setStringValue:tmpStr];
    hdgVal = tmpStr;
}
switch(rotorSelected)
{
    case 1:    //Alfaspid and Yaesu
    case 7:
        sendString = @"M";
        sendString = [sendString stringByAppendingString:(hdgVal)];
        sendString = [sendString stringByAppendingString:@"\r\n"];
        dataToSend = [sendString dataUsingEncoding:NSUTF8StringEncoding];
        [serialPort sendData:dataToSend];
        break;
    case 2:    //DCU
        sendString = @"AP1";
        sendString = [sendString stringByAppendingString:(hdgVal)];
        sendString = [sendString stringByAppendingString:@";AM1;"];
        NSLog(@"SendString = %@", sendString);
        dataToSend = [sendString dataUsingEncoding:NSUTF8StringEncoding];
        [serialPort sendData:dataToSend];
        if (!hdgTimer)
        {
            [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
            [self startTimer];
        }
        break;
    case 3: //Prosistel A B C
        c = 2;
        j = (char)c;
        tmpVal = [NSString stringWithFormat:@"%c", j];
        dataToSend = [tmpVal dataUsingEncoding:NSUTF8StringEncoding];
        [self.serialPort sendData:dataToSend];

        tmpStr = [inputTextField stringValue];
        for (i = 0 ; i < [tmpStr length]; i++)
        {
            NSLog(@"Iteration: %d", i);
            tmpVal = [tmpStr substringWithRange:NSMakeRange(i, 1)];
            c = [tmpVal intValue];
            j = (char)c;
            tmpVal = [NSString stringWithFormat:@"%c", j];
            dataToSend = [tmpVal dataUsingEncoding:NSUTF8StringEncoding];
            [self.serialPort sendData:dataToSend];
        }
        c = 13;
        j = (char)c;
        dataToSend = [tmpVal dataUsingEncoding:NSUTF8StringEncoding];
        [self.serialPort sendData:dataToSend];
        break;
    case 4: //Prosistel CBOX/D
        //char c = 0x02; dataToSend = [NSData dataWithBytes:&c length:1]
        j = 0x02;
        dataToSend = [NSData dataWithBytes:&j length:1];
        [self.serialPort sendData:dataToSend];
        tmpStr = @"AG";
        tmpStr = [tmpStr stringByAppendingString:(hdgVal)];
        dataToSend = [tmpStr dataUsingEncoding:NSUTF8StringEncoding];
        [self.serialPort sendData:dataToSend];
        j = 0x0d;
        dataToSend = [NSData dataWithBytes:&j length:1];
        [self.serialPort sendData:dataToSend];
        break;
    case 5: //RC-2800PX
        sendString = @"A#";
        sendString = [sendString stringByAppendingString:(hdgVal)];
        sendString = [sendString stringByAppendingString:@"\r"];
        dataToSend = [sendString dataUsingEncoding:NSUTF8StringEncoding];
        [self.serialPort sendData:dataToSend];
        break;
    case 6: //SARTEK
        sendString = @"P";
        sendString = [sendString stringByAppendingString:(hdgVal)];
        sendString = [sendString stringByAppendingString:@"\r\n"];
        dataToSend = [sendString dataUsingEncoding:NSUTF8StringEncoding];
        [self.serialPort sendData:dataToSend];
        break;
    default:
        break;
}

1 个答案:

答案 0 :(得分:0)

问题是一个简单的内存管理问题。由于您使用的是MRC(为什么不使用ARC?),您需要确保正确保留分配给hdgVal ivar的值。

最简单的解决方案(除了使用ARC)是将hdgVal ivar的所有直接用法替换为对hdgVal属性的引用。

变化:

hdgVal = tmpStr; // direct ivar access, no retain called

为:

self.hdgVal = tmpStr; // use the property, value retained

您拥有的代码是将自动释放的字符串直接分配给ivar。一旦原始字符串被释放,您的ivar指向垃圾,然后指向其他一些任意值。在你发布的情况下,NSArray恰巧正在使用该内存。