【问题标题】:Objective-c and using NSString as a function parameterObjective-c 并使用 NSString 作为函数参数
【发布时间】:2011-09-27 11:25:49
【问题描述】:

我有一个奇怪的问题(对我来说,无论如何)。

我在我的 Objective-C 程序中调用一个函数并传入三个参数...一个自制对象、一个 NSMutableArray 和一个 NSString。

函数原型长这样......

 int LoadNoteTableArray (Entryfile* EntryfileName, 
      NSMutableArray* NSMutableArrayInputEntry, NSString* title_string);

我像这样从 main 内部调用它...

 Entryfile* Entryfile1 = [[Entryfile alloc] init];
 NSMutableArray *NoteTableArray = [[NSMutableArray alloc] initWithCapacity:1];
 NSString*          title_string;

title_string = @"test string";

checkerror = LoadNoteTableArray (Entryfile1, NoteTableArray, title_string);

而且在函数中是这样设置的......

 int LoadNoteTableArray (Entryfile* Entryfile1, NSMutableArray* NoteTableArray,
   NSString* title_string) {

我可以使用对象 Entryfile1 并使用对象的各种方法在函数中更改它,这些更改在主程序中可见。我可以将条目添加到 NoteTableArray 中,然后在主程序中查看。但是,对 NSString 的更改不会反映在主程序中。我可以在函数的开头看到 title_string 为 @"test string" 。它在函数中设置为其他值,但该值永远不会返回到主程序。

我对这些符号和对象之间的区别感到困惑。

想法?

好的....代码剪辑器...来自主程序...

checkerror = LoadConfigTableArray (Configfile1, ConfigEntryArray);
title_string = @"test string";
checkerror = LoadNoteTableArray (Entryfile1, NoteTableArray, &title_string);
[NoteTableArray sortUsingSelector:@selector(compareNoteEntryTime:)];
checkerror = RemediateNoteTableArray (NoteTableArray);
checkerror = WriteOutTimeFromNoteTableArray (NoteTableArray, ConfigEntryArray,       title_string);
[NoteTableArray sortUsingSelector:@selector(compareNoteIDandMarkTime:)];
checkerror = WriteOutNotesFromNoteTableArray (NoteTableArray, ConfigEntryArray);

请注意,在我解决此问题后,将使用检查错误来捕获各种功能报告的错误情况...

您要求...您得到它...丰田...这是功能...我不会清理此发布站点的间距。一些代码是播放代码,所以如果你想继续它,那没关系,但要知道你对我帮助不大。它读取文本文件(Mac 或 Windows),将某些行解析为对象,并将它们加载到对象数组中。

int LoadNoteTableArray (Entryfile* Entryfile1, NSMutableArray* NoteTableArray, NSString** title_string) {

NSString* tokenclass;
NSString* previous_tokenclass;
NSString* token;
NSString* savedheaderid;
NSString* response;
NSString* tempstring;
NSString* tempstring2;
NSString* token_xx;
NSString* entryfile1path;
NSString* entryfile1name;
NSString* responseok;
NSNumber*   temp_MarkTime;

NoteTableEntry* NoteTableEntrytemp;

char firstline;
char first_id_found;
int duplicate_count;
int arrayCount;
int loop_count;

entryfile1path = [NSString stringWithString: @"PATH"];
entryfile1name = [NSString stringWithString: @"notes"];
responseok = [Entryfile1 OpenEntryFile: entryfile1path withdatafilename: entryfile1name];
if ([responseok isEqualToString:@"ERROR"]) {return 1;};
if ([responseok isEqualToString:@"LAST"]) {return 2;};

firstline = 'N';
first_id_found = 'N';
tokenclass = nil;
*title_string = nil;

do {
    if (tokenclass == nil) {previous_tokenclass = nil;}
    if (tokenclass != nil) {previous_tokenclass = [NSMutableString stringWithString: tokenclass];}
    tokenclass = nil;
    token = [Entryfile1 GetNextToken];
    if (token == nil) {break;};

    tokenclass = [Entryfile1 ClassifyToken:token];

    if ([tokenclass isEqualToString: @"i"]) {
        [NoteTableArray addObject:[NoteTableEntry initNoteTableEntryForID:token]];
        firstline = 'Y';
        first_id_found = 'Y';
        savedheaderid = response;
        duplicate_count = 0;
        previous_tokenclass = nil;
        continue;};

    if (([tokenclass isEqualToString: @"s"]) & (first_id_found == 'N')) {
        *title_string = token;
        continue;};

    if (first_id_found == 'N') {continue;};

    if (([tokenclass isEqualToString: @"t"]) & ([previous_tokenclass isEqualToString: @"t"] == FALSE)) {
        arrayCount = [ NoteTableArray count ];
        arrayCount--;
        NoteTableEntrytemp = [NoteTableArray objectAtIndex:arrayCount];
        [NoteTableEntrytemp AddTimeEntry:savedheaderid withtimestring:token];
        continue;};

    if (([tokenclass isEqualToString: @"t"]) & ([previous_tokenclass isEqualToString: @"t"] == TRUE)) {
        duplicate_count++;
        arrayCount = [ NoteTableArray count ];
        arrayCount--;
        NoteTableEntrytemp = [NoteTableArray objectAtIndex:arrayCount];
        [NoteTableArray addObject:[NoteTableEntry initNoteTableEntryForID:[NoteTableEntrytemp NoteID]]];
        arrayCount = [ NoteTableArray count ];
        arrayCount--;
        NoteTableEntrytemp = [NoteTableArray objectAtIndex:arrayCount];
        [NoteTableEntrytemp AddTimeEntry:savedheaderid withtimestring:token];
        [NoteTableEntrytemp AddNoteType:savedheaderid withnotetype:@"t"];
        continue;};     

    if ([tokenclass isEqualToString: @"d"]) {
        arrayCount = [ NoteTableArray count ];
        arrayCount--;
        NoteTableEntrytemp = [NoteTableArray objectAtIndex:(arrayCount - duplicate_count)];
        [NoteTableEntrytemp AddNoteType:savedheaderid withnotetype:token];
        if ([token isEqualToString: @"n"] & (arrayCount > 0)) {
            NoteTableEntrytemp = [NoteTableArray objectAtIndex:(arrayCount - duplicate_count - 1)];
            temp_MarkTime = NoteTableEntrytemp.TimeMark;
            NoteTableEntrytemp = [NoteTableArray objectAtIndex:(arrayCount - duplicate_count)];
            [NoteTableEntrytemp setTimeMark: temp_MarkTime];
        }
        continue;};

    if (([tokenclass isEqualToString: @"s"]) & (firstline == 'Y')) {
        arrayCount = [ NoteTableArray count ];
        arrayCount--;
        loop_count = 0;
        do {
            NoteTableEntrytemp = [NoteTableArray objectAtIndex:(arrayCount - loop_count)];
            [NoteTableEntrytemp AddNoteHeader:savedheaderid withnoteheader:token];
            if (loop_count == duplicate_count) {
                tempstring = [NSString stringWithString: @" - XX:XX"];
                tempstring2 = [token stringByAppendingString:tempstring];
                token_xx = tempstring2;
                [NoteTableEntrytemp AddNoteBody:savedheaderid withnotebody:token_xx];}
            else {
                [NoteTableEntrytemp AddNoteBody:savedheaderid withnotebody:token];};
            loop_count++;

        } while (loop_count <= duplicate_count);
        firstline = 'N';
        continue;};

    if (([tokenclass isEqualToString: @"s"]) & (firstline == 'N')) {
        arrayCount = [ NoteTableArray count ];
        arrayCount--;
        NoteTableEntrytemp = [NoteTableArray objectAtIndex:(arrayCount - duplicate_count)];
        [NoteTableEntrytemp AddNoteBody:savedheaderid withnotebody:token];
        firstline = 'N';
        continue;};

} while (token);

return 0;

}

【问题讨论】:

  • 因为我的问题真的没有得到回答。我能够通过使用指针传递 NSString 来使代码工作。但是,Entryfile 不需要指针,并且传递的样式不同。如果您对此有答案,我将放弃金色的“答案”框顶。

标签: objective-c function pass-by-reference


【解决方案1】:

因为字符串是不可变的!

您无法更改字符串在内存中当前位置的值。在您的main program 中,您有一个指向内存中存储值"test string" 的位置的指针。在您的方法中,当您为title_string 分配新值时,您将本地变量指向内存中的新位置。但是,main program 中的 title_string 的值仍然指向原始位置。

如果在你的方法中,你说:Entryfile1 = [[Entryfile1 alloc] init];,我猜你不会期望你的main program 中的EntryfileName 的值会改变。您会直观地理解,在您的 main application 中,您仍在引用“旧的”Entryfile - 而不是您刚刚创建的新 Entryfile。这本质上就是您将title_string 设置为新值时所做的事情。您只是在更改局部变量的指针...而不是您在 main program 中的指针。

编辑: 解决 OP 关于在数组中传递 NSString 的评论

考虑以下应用:

#import <Foundation/Foundation.h>

void foo (NSString ** stringRef);

int main (int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSString * myString = @"Testing";

    NSLog(@"%@", myString);

    foo(&myString);

    NSLog(@"%@", myString);

    [pool drain];
    return 0;
}

void foo (NSString ** stringRef)
{
    *stringRef = @"Bar";
}

我相信这里的结果就是您所期望的。我希望你能看到这与你所做的有什么不同,以及为什么会这样(根据我上面的解释)。

【讨论】:

  • 在我看来,您描述的是范围,而不是可变性。您描述的相同行为也会发生在可变对象上。
  • 很公平,但为什么 NSMutableArray 在主程序中被视为开始更改?如果我想成为一个 dufus,我可以将我的 NSString 放入一个 NsMutableArray 中,以这种方式来回传递它。这对我来说似乎很奇怪。
  • @Jim - 我正在描述 both 范围 可变性(因为他提出的问题涉及两者)。首先,这些指针的范围在这两种情况下都是本地的,其次,指针的值——而不是指针引用的内存中的值——是字符串的变化。只有解决这两个概念的解释才能完全回答他的问题。
  • @joseph,关于此声明:“我可以将我的 NSString 放入 NsMutableArray 中,以这种方式来回传递。”不对。你会传递一个reference。不是实际的 NSStrings。通过更改 NSMutableArray,您所要做的就是使用循环方式来回传递指向指针的指针。
  • @Steve,我根本看不出可变性是如何影响您的答案的——正如我所说,您所描述的错误无论可变性如何都是同样错误的。您假设问题在于他正在分配给局部变量,而事实并非如此。如果是这样,他可能也会在其他变量上犯同样的错误。我见过很多人认为像stringByAppendingString: 这样的方法会改变原始实例——他很可能会这样做。字符串并不像你说的那样不可变——只有 NSStrings 是。
【解决方案2】:

您无法更改NSStrings。甚至在您调用的方法中也不行。它们是不可变的。如果你在字符串上调用stringByAppendingString: 之类的东西,它不会修改字符串,它会返回一个新的NSString 对象。

你可能想要NSMutableString

【讨论】:

  • 线程变得有点混乱,但你说得通,史蒂夫。我将为 NSString 添加该代码,我希望它可以正常工作。我剩下的唯一问题是为什么 NSMutableArray 会在不使用传递指针的情况下被更改?我认为这是我大部分困惑的根源。
  • 我认为您的意思是将其发布为对另一个答案的回复。您的原始代码将数组和字符串作为指针传递。你在函数中做错了什么——我们不能在没有看到它的情况下说出什么——这导致字符串没有被修改。 Steve 的解决方案是在字符串的情况下传递一个指向指针的指针,因此您最终会得到一个全新的字符串对象,而不是尝试更改已有的对象。
猜你喜欢
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 2018-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多