2012-02-08 21 views
0
def leopardRemoveWireless(networkName): 
    plistPath = '/Library/Preferences/SystemConfiguration/preferences.plist' 
    # Sanity checks for the plist 
    if os.path.exists(plistPath): 
    try: 
     pl = NSMutableDictionary.dictionaryWithContentsOfFile_(plistPath) 
    except: 
     print 'Unable to parse file at path: %s' % plistPath 
     sys.exit(1) 
    else: 
    print 'File does not exist at path: %s' % plistPath 
    sys.exit(1) 
    # Create a copy of the dictionary due to emuration 
    copy = NSDictionary.dictionaryWithDictionary_(pl) 
    # Iterate through network sets 
    for Set in copy['Sets']: 
    UserDefinedName = copy['Sets'][Set]['UserDefinedName'] 
    print 'Processing location: %s' % UserDefinedName 

    for enX in copy['Sets'][Set]['Network']['Interface']: 
     print 'Processing interface: %s' % enX 
     # I think this will always be a single key but this works either way 
     for key in copy['Sets'][Set]['Network']['Interface'][enX]: 
     print 'Processing Service: %s' % key 
     # Try to grab the PreferredNetworks key if any 
     try: 
      # Iterate through preferred network sets 
      index = 0 
      for PreferredNetwork in copy['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks']: 
      SSID_STR = PreferredNetwork['SSID_STR'] 
      print 'Processing SSID: %s' % SSID_STR 
      # If the preferred network matches our removal SSID 
      if SSID_STR == networkName: 
       print 'Found SSID %s to remove' % SSID_STR 
       # Delete our in ram copy 
       print 'Processing Set: %s' % Set 
       print 'Processing enX: %s' % enX 
       print 'Processing key: %s' % key 
       del pl['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks'][index] 
      index += 1 
     except KeyError: 
      print 'Skipping interface without PreferredNetworks' 

当我在编辑一个相当复杂的(字典)的plist,然后写更改回原来的文件后,我找到一个特定的键值对错误。问题是,即使我做物业的副本列表的字典:“NSCFArray突变而被枚举”枚举副本

copy = NSDictionary.dictionaryWithDictionary_(pl) 

这是给我的标准“的突变,同时列举了”错误,当我编辑原始的,只是循环键作为独立插件(注意缺乏引号)。

del pl['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks'][index] 

是我的语法在某种程度上导致它尝试和编辑pl的字典那么copy?下面是输出:

... Processing Set: D5C0A0F4-613A-4121-B6AE-4CBA6E2635FF Processing enX: en1 Processing key: AirPort Traceback (most recent call last): File "/Users/tester/Desktop/wifiutil", line 1164, in sys.exit(main()) File "/Users/tester/Desktop/wifiutil", line 1135, in main removeWireless(osVersion,network) File "/Users/tester/Desktop/wifiutil", line 1051, in removeWireless leopardRemoveWireless(network)
File "/Users/tester/Desktop/wifiutil", line 528, in leopardRemoveWireless for PreferredNetwork in copy['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks']: File "/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjC/objc/_convenience.py", line 431, in enumeratorGenerator yield container_unwrap(anEnumerator.nextObject(), StopIteration) objc.error: NSGenericException - * Collection was mutated while being enumerated.

回答

1

我认为这个问题是字典的嵌套性质。 dictionaryWithDictionary_()不会执行任何操作,如深度复制;它所做的就是创建一个新的NSDictionary并复制值的指针(它自己复制密钥,因为这是NSDictionary的性质)。

这意味着,虽然你有一个新的顶层,你可以使用枚举,内部字典和数组是完全一样的对象为在原。

你的最后一个循环:

for PreferredNetwork in copy['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks']: 

被列举出这些内部数组,然后尝试用del声明变异之一:

del pl['Sets'][Set]['Network']['Interface'][enX][key]['PreferredNetworks'][index] 

这是不可复制的;它与for中使用的数组对象相同,这会导致异常。您可以通过将这两个表达式传递给id()来测试。

你必须要么是原始字典的全深拷贝,或(可能更好),你列举的前几天最后一级的副本。

+0

我尝试切换它来复制= NSMutableDictionary.alloc()。initWithDictionary_copyItems_(PL,真) 但仍然有同样的错误。也许我应该制作NSArray的副本? – acidprime 2012-02-08 19:29:38

+0

是的,这仍然不会做一个完整的副本 - 如果你看[文档](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class /Reference/Reference.html#//apple_ref/doc/uid/20000140-BABECHBH)你会看到它只复制第一层;这是你必须自己编码的东西。幸运的是,在Python中这比ObjC容易得多,但我仍然认为最好的方法是在枚举它之前复制最后一个元素。 – 2012-02-08 19:37:17

+0

copy = NSMutableDictionary.dictionaryWithContentsOfFile_(plistPath)虽然对内存管理来说不是最好的。 – acidprime 2012-02-08 19:58:06