我一直在开发通用 iOS 应用程序的前端,将单独的 iPhone 和 iPad 视图控制器设置为无 XIB 视图控制器的子类(如 http://www.kotancode.com/2011/04/05/ios-universal-apps/)。每个子类视图控制器都包含一个特定于设备的 XIB,每个 XIB 都包含纵向和横向 UIView,这些 UIView 在方向更改时切换(我遵循 http://aseriesoftubes.com/articles/ipad-development-101-orientation/ )。所有四个 UIView 共有的控件与通过 IBOutletCollections 链接的 IBAction 方法同步。
就在今天,我为自己的滑块设计创建了一个 UISlider 子类,除了一个大问题之外,它似乎工作正常:当在模拟器中从纵向开始使用 iPhone 进行测试时,滑块工作正常;当切换到横向时也很好;然而,当我切换回纵向时,滑块最多可进行两次操作,然后冻结,同时进行一些其他视图控制;更奇怪的是,如果我切换回横向,滑块就可以正常工作!这只发生在 iPhone 模拟器上,而不是 iPad 上。
我尝试过打开和关闭 IB 的“连续”选项,并尝试了滑块发送事件中的“Touch Up Inside”和“Value Changed”连接,没有任何变化(因为它将用于音量控制,我需要“值已更改为工作)。我的滑块的实现代码是这样的:
@implementation VolumeSlider
- (id)initWithCoder:(NSCoder *)decoder
{
if((self = [super initWithCoder: decoder])) // Double paretheses to silence warning
{
// Instantiate slider images
UIImage *thumbImage = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"volume thumb" ofType: @"png"]];
UIImage *trackImage = [[UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"volume track" ofType: @"png"]] stretchableImageWithLeftCapWidth: 20 topCapHeight: 0];
// Set control elements with images
[self setThumbImage: thumbImage forState: UIControlStateNormal];
[self setMinimumTrackImage: trackImage forState: UIControlStateNormal];
[self setMaximumTrackImage: trackImage forState: UIControlStateNormal];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
@end
滑块触发的两个操作方法是:
- (IBAction)volumeChange:(id)sender
{
NSLog(@"VOLUME slider changing");
// VOLUME slider action
}
- (IBAction)volumeChangeFinish:(id)sender
{
NSLog(@"VOLUME change finished");
VolumeSlider *incomingVolume = sender;
for(VolumeSlider *volumeSlider in self.volumeSliders)
{
volumeSlider.value = incomingVolume.value;
}
}
(volumeChange将使用滑块值实时改变音量,volumeChangeFinished将在触摸时更新视图中的其他滑块。)
这个有我难住了——感觉像是内存问题,但我不知道到底在哪里。有谁知道这可能是什么原因造成的?
(Mac OS 10.6.8,Xcode 4.0.2,为 iOS 4.3 构建)
更新 ---
我尝试在 iPhone 视图中实例化一个新的、库存的 UISlider,这遇到了同样的问题,但没有连接到任何东西。这表明视图控制器存在问题,甚至是一些错误。
I have been working on the front-end to a universal iOS app, setting up separate iPhone and iPad view controllers as subclasses of a XIB-less view controller (as described in http://www.kotancode.com/2011/04/05/ios-universal-apps/). Each subclassed view controller contains a device-specific XIB, with each XIB containing portrait and landscape UIViews which are switched upon orientation change (I followed http://aseriesoftubes.com/articles/ipad-development-101-orientation/ for this). The controls common to all four UIViews are synchronised with an IBAction method linked through IBOutletCollections.
Just today I have created a UISlider subclass for my own slider design, which appears to work fine, apart from one large issue: when testing with the iPhone in the simulator starting in portrait orientation the slider works fine; when switched to landscape it is also fine; however when I switch back to portrait the slider works for up to two operations and then freezes, taking some other controls of the view with it; stranger still, if I switch back to landscape the slider works fine! This happens only with the iPhone simulator, not the iPad.
I have tried switching IB's 'Continuous' option on and off, and tried both the 'Touch Up Inside' and 'Value Changed' connections from my slider's Sent Events, with no change (as it will be for a volume control I will need 'Value Changed' to work). My slider's implementation code is thus:
@implementation VolumeSlider
- (id)initWithCoder:(NSCoder *)decoder
{
if((self = [super initWithCoder: decoder])) // Double paretheses to silence warning
{
// Instantiate slider images
UIImage *thumbImage = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"volume thumb" ofType: @"png"]];
UIImage *trackImage = [[UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"volume track" ofType: @"png"]] stretchableImageWithLeftCapWidth: 20 topCapHeight: 0];
// Set control elements with images
[self setThumbImage: thumbImage forState: UIControlStateNormal];
[self setMinimumTrackImage: trackImage forState: UIControlStateNormal];
[self setMaximumTrackImage: trackImage forState: UIControlStateNormal];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
@end
The two action methods that the sliders trigger are:
- (IBAction)volumeChange:(id)sender
{
NSLog(@"VOLUME slider changing");
// VOLUME slider action
}
- (IBAction)volumeChangeFinish:(id)sender
{
NSLog(@"VOLUME change finished");
VolumeSlider *incomingVolume = sender;
for(VolumeSlider *volumeSlider in self.volumeSliders)
{
volumeSlider.value = incomingVolume.value;
}
}
(volumeChange will use the slider value to change volume in real time, volumeChangeFinished will update the other sliders in the view on touch inside up.)
This one has me stumped – it feels like a memory issue but I can't figure out exactly where. Does anyone have an idea what could be causing this?
(Mac OS 10.6.8, Xcode 4.0.2, building for iOS 4.3)
UPDATE ---
I have tried instantiating a new, stock UISlider into the iPhone view and this suffers the same problem, without having been connected up to anything. This points towards an issue with the view controller, or even some bug.
发布评论
评论(1)
尽管我没有明确的原因,但我已经设法解决了这个问题。基本上,我在 Interface Builder 中为 iPhone 纵向创建了一个新的 UIView,重建了界面并将其连接起来以代替不可靠的界面,然后问题就消失了。我不知道我是否在 XIB 中看到了损坏的视图,这是我能提供的唯一答案。
Although I have no definitive reason for the issue, I have managed to fix this. Basically I created a new UIView for the iPhone portrait orientation in Interface Builder, rebuilt the interface and connected it up in place of the dodgy one and the issue was gone. I don't know if I could have had a corrupted view in the XIB, that's the only answer I can proffer.