Singleton中的NSMutableArrays不保存值

| 任何帮助弄清楚这一点将不胜感激。我在一个单例中有3个NSMutableArrays(游戏管理器),当我访问尝试存储的数据时,即使其中的全部相同,它们中只有一个可以工作。 这是我在GameManager.h中初始化它们的地方
- (GameManager *)init
{
    if ((self = [super init]))
    {
        gameTexts = [[NSMutableArray alloc] init];
        gameDrawings = [[NSMutableArray alloc] init];
        playerNames = [[NSMutableArray alloc] init];
    }
    return self;
}
这是我要在其中存储值的地方。这似乎是我放入NSLogs的问题所在。
[[GameManager sharedManager].playerNames addObject:[NSString stringWithFormat:@\"%@\",nextPlayerName.text]];
[[GameManager sharedManager].gameTexts addObject:[NSString stringWithFormat:@\"%@\",inputText.text]];
[[GameManager sharedManager].gameDrawings addObject:([[GameManager sharedManager] previousDrawing])];
这是我尝试检索数据的地方。
names.text = [[GameManager sharedManager].playerNames objectAtIndex:(nameIndex)];
texts.text = [[GameManager sharedManager].gameTexts objectAtIndex:(textIndex)];
drawings.image = [[GameManager sharedManager].gameDrawings objectAtIndex:(drawingIndex)];
只有playerNames数组可以正常工作。当我尝试使用NSLog来查看其中的内容时,其他两个给我带来严重的访问错误。 任何想法都欢迎,因为我已经坚持了一段时间。谢谢     
已邀请:
        听起来
gameTexts
和ѭ4somewhere在某处过度释放。这几乎总是造成“ 5”的原因。     

bab

        您应该封装数组并为要提供的功能创建访问器,即e。有
- (void)addPlayerName:(NSString *)name
方法,等等。 这将使您的代码更具可读性,并且还允许您的经理使用值进行处理,例如拒绝它们,检查重复项等。     
        我刚刚研究了一组用于从多个线程处理NSMutableArrays的宏,并决定对堆栈溢出进行一些搜索,以查看导致我编写此代码的问题是否司空见惯,结果您的问题浮出水面。 这可能不是\“您正在寻找的机器人\”,所以,如果它不能回答您提出的问题,请随时“继续前进” :-) 这里有2个头文件(带有有关如何使用它们的注释),用于同一概念的多个版本-一种轻松的单行代码,可自动生成一些类/实例方法,这些方法执行线程安全数组操作的某些棘手方面。 StaticMutableArrays.h是一个全局的类范围的全局数组概念,该类的每个实例共享一个公共数组-多线程操作最有可能成为问题。 还有另一个变体(ThreadsafeMutableArrays.h),它用于创建该类的每个实例都具有其自己的数组的数组,该数组不同于任何其他实例(通常情况下,只是创建一个数组的方式)在您的代码中,由于您的问题是关于访问单例内数组的问题,因此我现在仅发布StaticMutableArrays.h,它们的工作方式相同,但包装了一个标准的ivar数组。 我将以公共领域的形式发布此代码,并欢迎就如何改进它或任何人看到的明显问题发表任何意见。 StaticMutableArrays.h
//
//  StaticMutableArrays.h
//
//  Created by Jonathan M Annett on 10/10/11.
//   The author has placed this work in the Public Domain, thereby relinquishing all copyrights. Everyone is free to use, modify, republish, sell or give away this work without prior consent from anybody.

//   This documentation is provided on an “as is” basis, without warranty of any kind. Use at your own risk! Under no circumstances shall the author(s) or contributor(s) be liable for damages resulting directly or indirectly from the use or non-use of this documentation.
//



/*

 StaticMutableArrays are thread safe arrays that are associated with a particular class of object 

 they are accessed via class methods in the class in which they are defined.
 each instance of the class sees the same physical array. 

 they are generated by insert a macro in the interface and implementation seconds of the class:

@interface myObject : NSObject {

 }

    staticMutableArray_interface(arrayName);


 @end


 @implementation myObject

    staticMutableArray_implementation(arrayName);

@end


 these arrays are syntactially identical to those generated by  ThreadsafeMutableArrays.h

 you can then access the array in your code as follows (using \"arrayName\" as the example)


 NSMutableArray *tempArray = [self.class arrayName_];

 note the trailing underscore - this indicates it\'s an autoreleased threadsafe mutable copy of the underlying array, that was \"correct\" at the time you called the method. you can safely iterate the contents, knowing the array you are holding won\'t be mutated by another thread whilst you have it - the underlying array may have been mutated, so if you need exclusive access to the array knowing it can\'t be changed use [self.class arrayName] instead. note that even if the underlying array is mutated, and some elements are removed, and as long as this object is around (ie the pool is not drained) they will be quite safe as this (copied) array has them retained. this array is an NSMutableArray, so you can chop and change it as you want (eg whilst processing it), and it won\'t affect the underlying array at all. be sure to call [array removeAllObjects] when you are done to explicitly release the retains it has for each member. you don\'t need to release the array itself as it is already autoreleased.  


 NSArray *tempArray = [self.class copyOf_arrayName]

 This is the same as [self.class arrayName_], however the returned copy is immutable, and a retained copy.
 you can (for example) iterate the contents, and then release it, knowing that no matter what another thread does to the array while you are iterating it, they won\'t mess with your copy of the array. again - if you need exclusive access to the array knowing it can\'t be changed use [self.class arrayName] instead. 



 [self.class arrayName]; 

 returns the raw underlying array - warning: if you call this directly only, you can only USE the returned value safely inside an @synchronized() block for the array itself. the easiest way to do this is something like:

 NSMutableArray *array;
 @synchronized(array = [self.class arrayName]){ 

 // do something with \"array\"

 }

 if you study the macros you will see a variant of this throughout. (the method wrapper arrayName omitted to save an extra message being sent, but for readability of your code it\'s suggested you use the above construct.


 [self.class addObjectTo_arrayName:object];

 this is a thread safe way of adding to the array, that you can use from anywhere (EXCEPT from inside and @synchronized block for the array! in that case just add the object as you would normally in a single threaded environment) 

[self.class removeObjectFrom_arrayName:object];

 this is a thread safe way of removing an object from an array, that you can use from anywhere (EXCEPT from inside and @synchronized block for the array! in that case just add the object as you would normally in a single threaded environment) 

if ([self.class objectExistsIn_arrayName:object]) {...}

 this is a thread safe way of testing if an object is in an array, that you can use from anywhere (EXCEPT from inside and @synchronized block for the array! in that case just add the object as you would normally in a single threaded environment) 


 now the clever stuff:

 @synchronzed exclusive unconditional iteration of each element, blocking all other threads.

 [self.class iterate_arrayName_withBlock:NSArrayIterateBlock {

    // do something with: element 

 }];

 in this code construct you get 3 variables defined. for convenience a macro - NSArrayIterateBlock is defined to save you having to type long hand the block header:

    ^void(id element, NSInteger index,NSInteger ofCount)

    element  - this is the item you are iterating. you just typecast it to whatever you expect it to be (or test it to see what it is, the choice is yours)
    index & count - for simple accounting purposes you can tell at any stage in the loop how many you have processed (index == 0 means this is first), or how many you have to go (index==count-1) means this is the  last. you get the idea.




 @synchronzed exclusive conditional iteration of each element, blocking all other threads.

 [self.class conditionallyIterate_arrayName_withBlock:NSArrayConditionallyIterateBlock {

 // do something with: element and..

    return NO;  // we have done looping.

 // or 

    return YES;  // we want to keep looping.

 }];

 in this code construct you get 3 variables defined. for convenience a macro - NSArrayConditionallyIterateBlock is defined to save you having to type long hand the block header:

 ^BOOL(id element, NSInteger index,NSInteger ofCount)

 element  - this is the item you are iterating. you just typecast it to whatever you expect it to be (or test it to see what it is, the choice is yours)
 index & count - for simple accounting purposes you can tell at any stage in the loop how many you have processed (index == 0 means this is first), or how many you have to go (index==count-1) means this is the  last. you get the idea.

 the BOOL return value from the block indicates if you want to keep iterating the array (YES) or not (NO)



 and the final Pièce de résistance - conditionally delete elements from an array, whilst blocking access to the array by other threads.


 [self.class conditionallyDeleteFrom_arrayName_withBlock:
         NSMutableConditionallyDeleteArrayBlock {


        if (<element is something i want to delete>) {
            return YES;
        }

    return NO;
 }]



internal method that holds the static variable for the singleton array:

 [self.class arrayNameAlloc:YES];   // creates/returns the array - you can call this in your +(void) load {} for the class to ensure it is created. if you don\'t do this however, it will automatically be called the first time you do it. 
 [self.class arrayNameAlloc:NO];    // dumps the array - once you do this, you can\'t re alloc, so only do it once!



*/


// custom block header macros where you can specify a name and class type for the array element
// for example NSArrayIterateBlock_(personsName,NSString *)
// for example NSArrayIterateBlock_(itemInfo,NSDictionary *)
# define NSArrayIterateBlock_(element,id) ^void(id element, NSInteger index,NSInteger ofCount)
# define NSArrayConditionallyIterateBlock_(element,id) ^BOOL(id element, NSInteger index,NSInteger ofCount)
# define NSMutableConditionallyDeleteArrayBlock_(element,id) ^BOOL(id element, NSInteger originalIndex)


// generic version that just defines each element as \"id element\"
# define NSArrayIterateBlock NSArrayIterateBlock_(element,id)
# define NSArrayConditionallyIterateBlock NSArrayConditionallyIterateBlock_(element,id)
# define NSMutableConditionallyDeleteArrayBlock NSMutableConditionallyDeleteArrayBlock_(element,id)



#define staticMutableArray_interface(arrayName)\\
+(NSMutableArray *) arrayName;\\
/*+(NSMutableArray *) arrayName##Alloc:(BOOL)alloc;*/\\
+(void) addObjectTo_##arrayName:(id) object;\\
+(void) removeObjectFrom_##arrayName:(id) object;\\
+(BOOL) objectExistsIn_##arrayName:(id) object;\\
+(NSMutableArray *) arrayName##_;\\
+(NSArray *) copyOf_##arrayName;\\
+(void) iterate_##arrayName##_withBlock:\\
(void (^)(id element,NSInteger index,NSInteger ofCount))codeBlock;\\
+(void) iterateCopyOf_##arrayName##_withBlock:\\
(void (^)(id element,NSInteger index,NSInteger ofCount))codeBlock ;\\
+(void) conditionallyIterate_##arrayName##_withBlock:\\
(BOOL (^)(id element,NSInteger index,NSInteger ofCount))codeBlock;\\
+(void) conditionallyIterateCopyOf_##arrayName##_withBlock:\\
(BOOL (^)(id element,NSInteger index,NSInteger ofCount))codeBlock;\\
+(void) conditionallyDeleteFrom_##arrayName##_withBlock:\\
    (BOOL (^)(id element,NSInteger originalIndex))codeBlock;


#define staticMutableArray_implementation(arrayName)\\
/*quasi singleton factory method*/ \\
+(NSMutableArray *) arrayName##Alloc:(BOOL)alloc {\\
    static NSMutableArray *result = nil;\\
    static BOOL dealloced = NO;\\
    if (alloc) {\\
            if (!result) {\\
               if (!dealloced) {\\
                  result = [[NSMutableArray alloc] init ];\\
                }\\
           }\\
    } else {\\
      if (!dealloced) {\\
          if(result) {\\
              @synchronized(result){ \\
                 [result removeAllObjects];\\
                 [result release];\\
              }\\
              result = nil;\\
           }\\
           dealloced = YES;\\
       }\\
    }\\
    return result;\\
}\\
/*  add an object the arrray */ \\
+(void) addObjectTo_##arrayName:(id) object   {\\
     NSMutableArray *array;\\
       @synchronized(array= [self.class arrayName##Alloc:YES]){ \\
       [array addObject:object];\\
     }\\
}\\
/*  add an object, if it is not already in the array */ \\
+(void) includeObjectIn_##arrayName:(id) object   {\\
    NSMutableArray *array;\\
    @synchronized(array= [self.class arrayName##Alloc:YES]){ \\
      if ([array indexOfObject:object]==NSNotFound){\\
         [array addObject:object];\\
     }\\
   }\\
}\\
/*  remove an object from the array */ \\
+(void) removeObjectFrom_##arrayName:(id) object   {\\
   NSMutableArray *array;\\
   @synchronized(array= [self.class arrayName##Alloc:YES]){ \\
      [array removeObject:object];\\
  }\\
}\\
/*  test object existance*/ \\
+(BOOL) objectExistsIn_##arrayName:(id) object   {\\
  NSInteger result = NSNotFound; \\
  NSMutableArray *array;\\
  @synchronized(array= [self.class arrayName##Alloc:YES]){ \\
    result = [array indexOfObject:object];\\
  }\\
  return result!=NSNotFound;\\
}\\
/*  raw underlying access - use inside @synchronized(array= [self.class arrayName##Alloc:YES]) only*/ \\
+(NSMutableArray *) arrayName { \\
    return [self.class arrayName##Alloc:YES];\\
}\\
/*  mutable  autoreleased copy of underlying array - ie snapshot which may contain objects that have been removed since snapshot was taken - you need to call removeAllObjects when done, to expedite adjusting affected retainCounts that the arrayWithArray process implies */ \\
+(NSMutableArray *) arrayName##_ { \\
    NSMutableArray *result = nil;\\
    NSMutableArray *array;\\
    @synchronized(array= [self.class arrayName##Alloc:YES]){ \\
        result = [NSMutableArray arrayWithArray:array];\\
    }\\
    return result ;\\
}\\
/*  immutable retained copy of underlying array - ie snapshot which may contain objects that have been removed since snapshot was taken - you need to call release when done, to expedite adjusting affected retainCounts that the initWithArray process implies */ \\
+(NSArray *) copyOf_##arrayName { \\
    NSArray *result = nil;\\
    NSMutableArray *array;\\
    @synchronized(array = [self.class arrayName##Alloc:YES]){ \\
        result = [[NSArray alloc] initWithArray:array];\\
    }\\
    return result ;\\
}\\
/*  iteration of the array for each element, using a thread safe snapshot copy*/\\
+(void) iterateCopyOf_##arrayName##_withBlock:\\
(void (^)(id element,NSInteger index,NSInteger ofCount))codeBlock  {\\
    NSArray *array = [self.class copyOf_##arrayName]; \\
    NSInteger index = 0;\\
    NSInteger count = array.count;\\
        for (id element in array) {\\
            codeBlock (element,index,count);\\
            index++;\\
        }\\
   [array release];\\
}\\
/*  @synchronized iteration the array for each element */\\
+(void) iterate_##arrayName##_withBlock:\\
(void (^)(id element,NSInteger index,NSInteger ofCount))codeBlock  {\\
   NSMutableArray *array;\\
   @synchronized(array = [self.class arrayName##Alloc:YES]){ \\
        NSInteger index = 0;\\
        NSInteger count = array.count;\\
        for (id element in array) {\\
            codeBlock (element,index,count);\\
            index++;\\
        }\\
    }\\
}\\
/* iteration of the array for each element, using a thread safe snapshot copy, with option to exit loop */ \\
+(void) conditionallyIterateCopyOf_##arrayName##_withBlock:\\
(BOOL (^)(id element,NSInteger index,NSInteger ofCount))codeBlock  {\\
    NSArray *array = [self.class copyOf_##arrayName];\\
    NSInteger index = 0;\\
    NSInteger count = array.count;\\
    for (id element in array) {\\
        if (!codeBlock (element,index,count)) break;\\
        index++;\\
    }\\
    [array release];\\
}\\
/*  @synchronized iteration the array for each element, with option to exit loop */ \\
+(void) conditionallyIterate_##arrayName##_withBlock:\\
(BOOL (^)(id element,NSInteger index,NSInteger ofCount))codeBlock  {\\
    NSMutableArray *array;\\
    @synchronized(array = [self.class arrayName##Alloc:YES]){ \\
        NSInteger index = 0;\\
        NSInteger count = array.count;\\
        for (id element in array) {\\
            if (!codeBlock (element,index,count)) break;\\
            index++;\\
        }\\
    }\\
}\\
/* conditionally delete each element */ \\
+(void) conditionallyDeleteFrom_##arrayName##_withBlock:\\
(BOOL (^)(id element,NSInteger originalIndex))codeBlock  {\\
NSArray *array = [self.class copyOf_##arrayName]; \\
NSInteger originalIndex = 0;\\
for (id element in array) {\\
    \\
    if (codeBlock (element,originalIndex)) [self.class removeObjectFrom_##arrayName:element];\\
    originalIndex++;\\
}\\
[array release];\\
}
    

要回复问题请先登录注册