switch.hidden = YES not working, outlets all correctly set up - iphone

I am having a problem that is totally confounding me. Please look at the code below, it is from the book "Beginning iPhone 4 Development" chapter 4. I'm new to this :)
- (IBAction)toggleControls:(id)sender
{
if([sender selectedSegmentIndex] == kSwitchesSegmentIndex)
{
NSLog(#"Show switches");
[self.leftSwitch setHidden:NO];
[self.rightSwitch setHidden:NO];
[self.doSomethingButton setHidden:YES];
}
else
{
NSLog(#"Hide switches");
[self.leftSwitch setHidden:YES];
[self.rightSwitch setHidden:YES];
[self.doSomethingButton setHidden:NO];
}
}
The strange thing is that it logs this correctly but the ui controls aren't hiding/showing.
I also tried this (original in book):
- (IBAction)toggleControls:(id)sender
{
if([sender selectedSegmentIndex] == kSwitchesSegmentIndex)
{
NSLog(#"Show switches");
leftSwitch.hidden = NO;
rightSwitch.hidden = NO;
doSomethingButton.hidden = YES;
}
else
{
NSLog(#"Hide switches");
leftSwitch.hidden = YES;
rightSwitch.hidden = YES;
doSomethingButton.hidden = NO;
}
}

It sounds like you may have forgotten to wire up your outlets in Interface Builder. Check the values of leftSwitch and rightSwitch when this method is called by using a break point or an NSLog.

Related

UIViewController shouldAutorotateToInterfaceOrientation - would like to add hysteresis

I would like to defer auto rotating the user interface until the device has settled on an orientation for a number of seconds, rather than driving the user insane and flicking willy nilly whenever they tilt the device a few degrees off axis by mistake.
the closest i can get to this (which is by no means what I want, as it locks the UI) is:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
[NSThread sleepForTimeInterval:2.0];
return YES;
}
what i would like to do is use something like this - which works in principle, by checking the console log, but i need the appropriate line of code that has been commented out.
-(void) deferredAutorotateToInterfaceOrientation:(NSTimer *) timer {
autoRotationTimer = nil;
UIInterfaceOrientation interfaceOrientation = (UIInterfaceOrientation)[timer.userInfo integerValue];
NSLog(#"switching to new orientation %d now",interfaceOrientation);
// replace this with code to induce manual orientation switch here.
//[self forceAutoRotateToInterfaceOrientation:interfaceOrientation];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
[autoRotationTimer invalidate];
autoRotationTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self
selector:#selector(deferredAutorotateToInterfaceOrientation:) userInfo:[NSNumber numberWithInt:(int)interfaceOrientation ] repeats:NO];
NSLog(#"denying autorotate, deffering switch to orientation %d by 2 seconds",interfaceOrientation);
return NO;
}
I realize there are sometimes many ways to do things, so if this approach is not the most efficient, and someone can suggest another way to do this, I am all ears. My main criteria is I want to delay the onset of autorotation, whilst keeping a responsive user interface if indeed they have only leaned to the left slightly because they are in a bus that just went around a corner etc.
EDIT: I found a solution which may not be app store friendly, however i am a few weeks away from completion, and someone may answer this in the meantime. this works calls an undocumented method. the (UIPrintInfoOrientation) typecast is just to suppress the compiler warning, and does not affect the value being passed.
-(void ) forceUIOrientationInterfaceOrientation:(UIDeviceOrientation) interfaceMode {
[(id)[UIDevice currentDevice] setOrientation:(UIPrintInfoOrientation) interfaceMode];
}
full implementation which includes re-entrance negation is as follows:
- (void)viewDidLoad {
[super viewDidLoad];
acceptNewAutoRotation = YES;
}
-(void ) forceUIOrientationInterfaceOrientation:(UIDeviceOrientation) interfaceMode {
[(id)[UIDevice currentDevice] setOrientation:(UIPrintInfoOrientation) interfaceMode];
}
-(void) deferredAutorotateToInterfaceOrientation:(NSTimer *) timer {
autoRotationTimer = nil;
acceptNewAutoRotation = YES;
[self forceUIOrientationInterfaceOrientation:[[UIDevice currentDevice] orientation]];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
[autoRotationTimer invalidate];
if (acceptNewAutoRotation) {
autoRotationTimer = nil;
acceptNewAutoRotation = NO;
return YES;
} else {
autoRotationTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self
selector:#selector(deferredAutorotateToInterfaceOrientation:) userInfo:[NSNumber numberWithInt:(int)interfaceOrientation ] repeats:NO];
return NO;
}
}
To do this with public APIs, you probably would have to forget about autorotation, and do all your own view transforms manually based on filtered (not just delayed!) accelerometer input.
I have not tested this and it may not work at all but you can try this out:
start out self.rotate = NO; then:
- (void)shouldRotateTo:(UIInteraceOrientation *)interfaceOrientation {
self.rotate = YES;
// or test interfaceOrientation and assign accordingly.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
bool rot = self.rotate;
self.rotate = NO
[self performSelector:selector(shouldRotateTo:) withObject:[NSNumber numberWithInt:interfaceOrientation] afterDelay:2.0];
return rot;
}
Parameter interfaceOrientation is an enum (UIInteraceOrientation) so wrap it in an NSNumber when passing.

i have a problem in UIImageView's animating

-(IBAction) change {
self.imageView.animationImages = myImages;
self.imageView.animationDuration = 2;
if(self.imageView.isAnimating == NO){
[self.imageView startAnimating];
NSLog(#"if bool = %d", self.imageView.isAnimating);
}
else {
self.imageView stopAnimating];
NSLog(#"else bool = %d", self.imageView.isAnimating);
}
}
hello, i'm studying iOS programming.
but i have a question.
i have a button and when i click the button, then this method will be called.
first i click the button, then this code will start the if statement. that's what i want.
i click the button again, i think that will execute the else statement.
but it always execute the if statement only.
why is that?
i really don't know why is that. please help me
I think setting the properties like animationImages or animationDuration will stop the animation, so that by clicking, you every time stop and then just after (re)start it in the if part. Try setting these two properties outside the action method you wrote, and just let the if/else sequence.
-(IBAction) change {
// set these two anywhere else
//self.imageView.animationImages = myImages;
//self.imageView.animationDuration = 2;
if(self.imageView.isAnimating == NO){
[self.imageView startAnimating];
NSLog(#"if bool = %d", self.imageView.isAnimating);
}
else {
self.imageView stopAnimating];
NSLog(#"else bool = %d", self.imageView.isAnimating);
}
}

MKAnnotation shows it's Custom Marker graphic in simulator but not on device

I had this working very early, but then it stopped and I have no idea why. Here is the code:
- (void)updateMarkers:(NSMutableArray *)myAudioLocationVOArray
{
[self cleanupMarkers];
NSLog(#"UPDATE ALL MARKERS");
int tArrayCount = [myAudioLocationVOArray count];
for (int i=0; i< tArrayCount; i = i + 1)
{
AudioLocationVO* tAudioLocVO = [myAudioLocationVOArray objectAtIndex:i];
AudioAnnotation *tNewAnn = [[AudioAnnotation alloc] init];
tNewAnn.coordinate = CLLocationCoordinate2DMake(tAudioLocVO.latitude, tAudioLocVO.longitude);
// add current track if available
tNewAnn.audioLocationVORef = tAudioLocVO;
[self.mapView addAnnotation:tNewAnn];
[tNewAnn release];
}
}
- (void)cleanupMarkers
{
NSLog(#"REMOVE ALL MARKERS");
NSArray *tExistingPoints = self.mapView.annotations;
if ([tExistingPoints count] > 0)
{
[self.mapView removeAnnotations:tExistingPoints];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)myMapView viewForAnnotation:(id <MKAnnotation>)myAnnotation
{
if ([myAnnotation isKindOfClass:[AudioAnnotation class]])
{
AudioAnnotation *tAnnotation = (AudioAnnotation *)myAnnotation;
MKAnnotationView *tNewMarkerView = [[[MKAnnotationView alloc] initWithAnnotation:tAnnotation reuseIdentifier:nil] autorelease];
if(tAnnotation.audioLocationVORef.state == ANNOTATION_STATE_DROPPING)
{
NSLog(#"ADD DROP MARKER");
[tNewMarkerView setImage:[UIImage imageNamed:#"greenmarker.png"]];
tNewMarkerView.draggable = YES;
}
else
{
NSLog(#"ADD NEW MARKER");
[tNewMarkerView setImage:[UIImage imageNamed:#"newMarker.png"]];
tNewMarkerView.draggable = NO;
}
tNewMarkerView.frame = CGRectMake(tNewMarkerView.frame.origin.x,tNewMarkerView.frame.origin.y,20,26);
tNewMarkerView.canShowCallout = YES;
tNewMarkerView.enabled = YES;
// callout button
UIButton *tButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
tNewMarkerView.rightCalloutAccessoryView = tButton;
// cover art and title/subtitle
UIButton *tCover = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
if(tAnnotation.audioLocationVORef.trackVO==nil)
{
tAnnotation.title = #"Drop a Track";
tAnnotation.subtitle = #"Choose a track to drop";
[tCover setImage:[UIImage imageNamed:#"preCover.png"] forState:UIControlStateNormal];
}
else
{
tAnnotation.title = tAnnotation.audioLocationVORef.trackVO.songTitle;
tAnnotation.subtitle = tAnnotation.audioLocationVORef.trackVO.artist;
NSLog(#"ADD DATA MARKER %#", tAnnotation.title);
if(tAnnotation.audioLocationVORef.state==ANNOTATION_STATE_DROPPING){
tAnnotation.subtitle = #"Touch submit to Drop";
}
[tCover setImage:[tAnnotation.audioLocationVORef.trackVO getCoverArt] forState:UIControlStateNormal];
}
// make cover enabled to see song detail?
tCover.enabled = NO;
tNewMarkerView.leftCalloutAccessoryView = tCover;
[tCover release];
return tNewMarkerView;
}
return nil;
}
I tried to delete and add again the graphics as assets. I have been playing around a bit with the frame property. So far no luck.
And why the difference between simulator and device. I am using SDK 4.2... on iPhone 4
Make sure the image filenames match exactly with the resource names including upper/lower-case.
For example, if the resource is "GreenMarker.png", then "greenmarker.png" will only work on the simulator and not on the device.
Apple QA1697 (Why doesn't my device load a file that loads fine in the Simulator?) says:
Case-sensitivity: iPhone OS uses a
case-sensitive file system, unlike the
Simulator which uses a
case-insensitive file system by
default. Make sure the
case-sensitivity of resources accessed
within code matches the filename
case-sensitivity.
True, they should, but the Mac is case-preserving but also case-insensitive. The simulator runs on the Mac, so that's what you get.

What is the problem with the back button in my UIWebView?

I have an issue in my application that i wrote coding for the back button in my webView setEnabled = NO, but when the application is launched and webViewDidFinishLoad the back button setEnabled = YES. I tried all possibility to set the back button enabled is equal false but it not works.
-(IBAction) backButton : (id) sender{
backTapped = YES;
[webView goBack];
}
-(IBAction) fwdButton : (id) sender{
forwardTapped = YES;
[webView goForward];
}
- (void)webViewDidStartLoad:(UIWebView *)thisWebView{
NSLog(#"webViewDidStartLoad");
[progressWheel startAnimating];
progressWheel.hidden = NO;
if(!backTapped){
back.enabled = NO;
}
if (!forwardTapped) {
forward.enabled = NO;
}
}
- (void)webViewDidFinishLoad:(UIWebView *)thisWebView
{
[progressWheel stopAnimating];
progressWheel.hidden = YES;
if (!backTapped) {
[back setEnabled:thisWebView.canGoBack];
back.showsTouchWhenHighlighted = YES;
}
if (!forwardTapped) {
[forward setEnabled:thisWebView.canGoForward];
forward.showsTouchWhenHighlighted = YES;
}
}
I can't actually quite understand the problem you are having, but I can see two potential issues:
1) You set backTapped and forwardTapped to YES, but never set them to NO anywhere.
2) Perhaps you don't have "back" or "forward" buttons wired in you xib - if they are nil then back.enabled = NO will do nothing.
Edit:
This logic seems backwards:
if (!backTapped)
back.enabled = NO;
In your code you set backTapped to YES, then this code is hit so !backTapped is ! YES which is NO.
Try
if (backTapped)
back.enabled = NO;

MPMoviePlayerController play error on iPad

I'm writing an app that will be playing videos alot using the MPMoviePlayerController on the iPad. The problem is the app was working fine and playing the videos when I stopped working about 15 hours ago but now the videos do not play. The MPMoviePlayerController will show the first frame from the video, and in full screen view I can scrub through the movie fine but when I hit play it just pauses right away. I have the code below, when debugging i noticed that when I call play it sends an MPMoviePlayerPlaybackStateDidChangeNotification with the playbackState being MPMoviePlaybackStatePlaying and then right away it sends another MPMoviePlayerPlaybackStateDidChangeNotification notification with playbackState being MPMoviePlaybackStatePaused. Not sure if that helps but please let me know if you see anything wrong in my code or have an ideas, thanks.
- (void)handleNotification:(NSNotification *)notification {
if ([[notification name] isEqualToString:MPMoviePlayerPlaybackStateDidChangeNotification]) {
if (_videoPlayer.playbackState == MPMoviePlaybackStatePlaying) {
_playButtonLarge.hidden = YES;
_scrubber.maximumValue = _videoPlayer.duration;
[_playPauseButton setBackgroundImage:[UIImage imageNamed:#"video_controls_pause.png"] forState:UIControlStateNormal];
if (_updateScrubberTimer == nil) {
_updateScrubberTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateScrubber) userInfo:nil repeats:YES];
}
} else if (_videoPlayer.playbackState == MPMoviePlaybackStatePaused || _videoPlayer.playbackState == MPMoviePlaybackStateStopped) {
[_playPauseButton setBackgroundImage:[UIImage imageNamed:#"video_controls_play.png"] forState:UIControlStateNormal];
_playButtonLarge.hidden = NO;
if (_updateScrubberTimer != nil) {
[_updateScrubberTimer invalidate];
_updateScrubberTimer = nil;
}
if (_videoPlayer.playbackState == MPMoviePlaybackStateStopped) {
_scrubber.value = 0.0f;
_timePlayedLabel.text = #"0:00";
_timeRemainingLabel.text = #"-0:00";
_videoPlayerBG.hidden = NO;
}
}
} else if ([[notification name] isEqualToString:MPMoviePlayerPlaybackDidFinishNotification]) {
NSNumber *reason = [[notification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
if ([reason intValue] == MPMovieFinishReasonPlaybackEnded) {
_videoPlayerBG.hidden = NO;
}
_scrubber.value = _scrubber.maximumValue;
}
}
- (void)playPause {
if ([_videos count] > 0) {
if (_videoPlayer.playbackState == MPMoviePlaybackStatePaused || _videoPlayer.playbackState == MPMoviePlaybackStateStopped) {
_playButtonLarge.hidden = YES;
_videoPlayerBG.hidden = YES;
if ([_videoPlayer contentURL] == nil) {
Video *video = [_videos objectAtIndex:0];
[_videoPlayer setContentURL:video.videoURL];
}
if (![_videoPlayer isPreparedToPlay]) {
[_videoPlayer prepareToPlay];
}
[_videoPlayer play];
} else if (_videoPlayer.playbackState == MPMoviePlaybackStatePlaying) {
_playButtonLarge.hidden = NO;
[_videoPlayer pause];
}
}
}
I think I figured it out, I put the following code before every call to play
if (![_videoPlayer isPreparedToPlay]) {
[_videoPlayer prepareToPlay];
}
works now, if anyone else has any input let me know