Ios UIButton在添加到子视图后是否返回UIView?

Ios UIButton在添加到子视图后是否返回UIView?,ios,uiview,uibutton,Ios,Uiview,Uibutton,将UIButton作为子视图添加到后,访问它时遇到问题。当我试图调整视图上的按钮位置时,我总是得到一个UIView,而不是UIButton,只有我添加的第一个按钮。当我使用Is类时,其余的返回为UIButton。下面是一段代码片段,如下所示 首先,我从viewDidload调用createTiles方法,将按钮添加为子视图,然后在检测到设备方向后,通过调用adustLandscapeTiles/Grait方法调整按钮布局 我不知道为什么会发生这样的事有什么想法 // Adding buttons

将UIButton作为子视图添加到后,访问它时遇到问题。当我试图调整视图上的按钮位置时,我总是得到一个UIView,而不是UIButton,只有我添加的第一个按钮。当我使用Is类时,其余的返回为UIButton。下面是一段代码片段,如下所示

首先,我从viewDidload调用createTiles方法,将按钮添加为子视图,然后在检测到设备方向后,通过调用adustLandscapeTiles/Grait方法调整按钮布局

我不知道为什么会发生这样的事有什么想法

// Adding buttons to view 
- (void)createTiles
{    
   for(int i=0;i<[self.contentList count];i++)
  {
       UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
       [button addTarget:self action:@selector(buttonSelection:)forControlEvents:UIControlEventTouchDown];
       [button setTitle:[ [contentList objectAtIndex:i] valueForKey:@"nameKey"]  forState:UIControlStateNormal];
        button.tag=i;

        [self.view insertSubview:button atIndex:0];
        NSLog(@"adding %i %@",i , [ [contentList objectAtIndex:i] valueForKey:@"nameKey"]);
        [button release];

   }
  }

- (void)adustLandscapeTiles
{
    for (int row = 0; row < Portrait_TILE_ROWS; ++row)
    {
        for (int col = 0; col < Portrait_TILE_COLUMNS; ++col)
        {
            int index = (row * Portrait_TILE_COLUMNS) + col;      
            CGRect frame = CGRectMake(LandScape_TILE_MARGIN + col * (LandScape_TILE_MARGIN + LandScape_TILE_WIDTH),
                                  LandScape_TILE_MARGIN + row * (LandScape_TILE_MARGIN + LandScape_TILE_HEIGHT),
                                  LandScape_TILE_WIDTH, LandScape_TILE_HEIGHT);
  /// check subview is a button      
  NSLog(@"index: %i tag : %i Is of type UIButton?: %@",index,[[self.view viewWithTag:index] tag], ([ [self.view viewWithTag:index] isKindOfClass: [UIButton class]])? @"Yes" : @"No");

        /// Only the first button added with tag zero return UView instead of UIButton ??
            UIButton *tmb= (UIButton *)[self.view viewWithTag:index];
           if([tmb isKindOfClass:[UIButton class]]) //isKindOfClass
            {   
                [  [self.view viewWithTag:index] setFrame:frame];

            }

        }
    }

}
//添加要查看的按钮
-(void)createTiles
{    

对于(int i=0;i当我为您的问题添加一个更健壮的解决方案时,我注意到您过度释放了
按钮
。您不应该调用
[按钮释放]
您不拥有它!但这不是您唯一的问题

如果未将标记指定给
ui视图
,则该视图的标记将为零,因此,如果您的视图中有其他未指定标记的子视图,则可能会获得其中一个子视图。请尝试为标记添加偏移量,例如:

// Somewhere early in your .m file
const NSInteger kButtonTagOffset 256

// In your createTiles
button.tag = (kButtonTagOffset + i);
显然,在检索平铺时也需要添加此偏移量

这样说,你现在的方法是一个更有经验的程序员可能称之为易碎的,如果有人曾经对你的类进行分类,或者即使你在某个时候编辑,你可能会分配冲突的标签并引起一些问题。你可以考虑一个更健壮的解决方案。

既然您真正想要做的是将其维护为可以通过索引访问的按钮数组,那么为什么不在不依赖标记的情况下完全这样做呢

因此,在
UIViewController
中添加一个
NSMutableArray
来按住按钮

// In your .h or with private methods:
@property (nonatomic, retain) NSMutableArray* buttons;

// At the top of your @implementation
@synthesize buttons;

// A modified createTiles 
// Adding buttons to view 
- (void)createTiles
{     
    self.buttons = nil; /* in case viewDidUnload id not do this. */
    self.buttons = [[[NSMutableArray alloc] init] autorelease]; 
    for(int i=0;i<[self.contentList count];i++)
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button addTarget:self    
                   action:@selector(buttonSelection:)
         forControlEvents:UIControlEventTouchDown];
        [button setTitle:[[contentList objectAtIndex:i] valueForKey:@"nameKey"]  
                forState:UIControlStateNormal];

        [self.view insertSubview:button atIndex:0];
        NSLog(@"adding %i %@", i, 
                        [[contentList objectAtIndex:i] valueForKey:@"nameKey"]);
        [self.buttons insertObject:button atIndex:0];
    }
}

- (void)adustLandscapeTiles
{
    for (int row = 0; row < Portrait_TILE_ROWS; ++row)
    {
        for (int col = 0; col < Portrait_TILE_COLUMNS; ++col)
        {
            int index = (row * Portrait_TILE_COLUMNS) + col;    
            UIView* buttonView = [self.buttons objectAtIndex:index];

            CGRect frame = CGRectMake(LandScape_TILE_MARGIN + col *    
                                 (LandScape_TILE_MARGIN + LandScape_TILE_WIDTH),
                               LandScape_TILE_MARGIN + row *    
                                 (LandScape_TILE_MARGIN + LandScape_TILE_HEIGHT),
                               LandScape_TILE_WIDTH, 
                               LandScape_TILE_HEIGHT);
            // check subview is a button      
            NSLog(@"index: %i Is of type UIButton?: %@", index, 
                    ([ [buttonView viewWithTag:index] isKindOfClass: [UIButton class]])?
                        @"Yes" : @"No");

            UIButton *tmb= (UIButton *)buttonView;
            if([tmb isKindOfClass:[UIButton class]]) //isKindOfClass
            {   
                [buttonView setFrame:frame];
            }
        }
    }
}
//在.h中或使用私有方法:
@属性(非原子,保留)NSMutableArray*按钮;
//在@implementation的顶部
@合成按钮;
//一种改进的createTiles
//向视图中添加按钮
-(void)createTiles
{     
self.buttons=nil;/*以防viewDidUnload id不执行此操作*/
self.buttons=[[NSMutableArray alloc]init]autorelease];

对于(int i=0;i当我为您的问题添加一个更健壮的解决方案时,我注意到您过度释放了
按钮
。您不应该调用
[按钮释放]
您不拥有它!但这不是您唯一的问题

如果未将标记指定给
ui视图
,则该视图的标记将为零,因此,如果您的视图中有其他未指定标记的子视图,则可能会获得其中一个子视图。请尝试为标记添加偏移量,例如:

// Somewhere early in your .m file
const NSInteger kButtonTagOffset 256

// In your createTiles
button.tag = (kButtonTagOffset + i);
显然,在检索平铺时也需要添加此偏移量

这样说,你现在的方法是一个更有经验的程序员可能称之为易碎的,如果有人曾经对你的类进行分类,或者即使你在某个时候编辑,你可能会分配冲突的标签并引起一些问题。你可以考虑一个更健壮的解决方案。

既然您真正想要做的是将其维护为可以通过索引访问的按钮数组,那么为什么不在不依赖标记的情况下完全这样做呢

因此,在
UIViewController
中添加一个
NSMutableArray
来按住按钮

// In your .h or with private methods:
@property (nonatomic, retain) NSMutableArray* buttons;

// At the top of your @implementation
@synthesize buttons;

// A modified createTiles 
// Adding buttons to view 
- (void)createTiles
{     
    self.buttons = nil; /* in case viewDidUnload id not do this. */
    self.buttons = [[[NSMutableArray alloc] init] autorelease]; 
    for(int i=0;i<[self.contentList count];i++)
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [button addTarget:self    
                   action:@selector(buttonSelection:)
         forControlEvents:UIControlEventTouchDown];
        [button setTitle:[[contentList objectAtIndex:i] valueForKey:@"nameKey"]  
                forState:UIControlStateNormal];

        [self.view insertSubview:button atIndex:0];
        NSLog(@"adding %i %@", i, 
                        [[contentList objectAtIndex:i] valueForKey:@"nameKey"]);
        [self.buttons insertObject:button atIndex:0];
    }
}

- (void)adustLandscapeTiles
{
    for (int row = 0; row < Portrait_TILE_ROWS; ++row)
    {
        for (int col = 0; col < Portrait_TILE_COLUMNS; ++col)
        {
            int index = (row * Portrait_TILE_COLUMNS) + col;    
            UIView* buttonView = [self.buttons objectAtIndex:index];

            CGRect frame = CGRectMake(LandScape_TILE_MARGIN + col *    
                                 (LandScape_TILE_MARGIN + LandScape_TILE_WIDTH),
                               LandScape_TILE_MARGIN + row *    
                                 (LandScape_TILE_MARGIN + LandScape_TILE_HEIGHT),
                               LandScape_TILE_WIDTH, 
                               LandScape_TILE_HEIGHT);
            // check subview is a button      
            NSLog(@"index: %i Is of type UIButton?: %@", index, 
                    ([ [buttonView viewWithTag:index] isKindOfClass: [UIButton class]])?
                        @"Yes" : @"No");

            UIButton *tmb= (UIButton *)buttonView;
            if([tmb isKindOfClass:[UIButton class]]) //isKindOfClass
            {   
                [buttonView setFrame:frame];
            }
        }
    }
}
//在.h中或使用私有方法:
@属性(非原子,保留)NSMutableArray*按钮;
//在@implementation的顶部
@合成按钮;
//一种改进的createTiles
//向视图中添加按钮
-(void)createTiles
{     
self.buttons=nil;/*以防viewDidUnload id不执行此操作*/
self.buttons=[[NSMutableArray alloc]init]autorelease];

对于(int i=0;iThanks Idz),当我试图在interface builder中更改视图的标记值时,它没有起作用,但使用您的偏移量建议,效果非常好…感谢纠正我,如果我错了,该语句[self.view insertSubview:button atIndex:0]是否会将按钮的保留计数增加一倍,与[self.buttons插入对象:按钮索引:0]?您的方法确保更易于维护,这是我最初打算实施的方法,但我担心的是增加按钮的保留计数?只要释放两次,就可以保留两次。因此,要想成为一名优秀的内存管理公民,您需要确保在
viewDidUnload设置
self.buttons=nil
并删除所有子视图。您应该已经在执行删除所有子视图步骤,因为您提到您正在从
viewDidLoad
调用
createTiles
。规则是,您在
viewDidLoad
中创建的任何内容都应该在
viewDidUnload
deal>中释放loc
。谢谢Idz,当我试图在interface builder中更改视图的标记值时,它没有工作,但使用您的偏移建议,效果非常好…谢谢如果我错了,请纠正我,该语句[self.view insertSubview:button atIndex:0]是否会将按钮的保留计数与[self.buttons插入对象:按钮索引:0]?您的方法确保更易于维护,这是我最初打算实施的方法,但我担心的是增加按钮的保留计数?只要释放两次,就可以保留两次。因此,要想成为一名优秀的内存管理公民,您需要确保在
viewDidUnload设置
self.buttons=nil
并删除所有子视图。您应该已经在执行删除所有子视图步骤,因为您提到您正在从
viewDidLoad
调用
createTiles
。规则是,您在
viewDidLoad
中创建的任何内容都应该在
viewDidUnload
deal>中释放loc