Is it just me or has the action sheet on <img> tags been disabled in UIWebView? In Safari, e.g, when you want to save an image locally, you touch and hold on the image to get an action sheet shown. But it's not working in my custom UIWebView. I mean, it is still working for <a> tags, i.e, when I touch and hold on html links, an action sheet shows up. But not for the <img> tags.
I've tried things like putting img { -webkit-touch-callout: inherit; } in css, which didn't work. On the other hand, when I double-tap and hold on the images, a copy-balloon shows up.
So the question is, has the default action sheet callout for <img> tags been disabled for UIWebView? Is so, is there a way to re-enable it? I've googled around and saw many Q&As on how to disable it in UIWebView, so is it just me who aren't seeing the popup?
Thanks in advance!
Yes apple has disabled this feature (among others) in UIWebViews and kept it for Safari only.
However you can recreate this yourself by extending this tutorial, http://www.icab.de/blog/2010/07/11/customize-the-contextual-menu-of-uiwebview/.
Once you've finished this tutorial you'll want to add a few extra's so you can actually save images (which the tutorial doesn't cover).
I added an extra notification called #"tapAndHoldShortNotification" after 0.3 seconds which calls a method with just the disable callout code in it (to prevent both the default and your own menu popping while the page is still loading, a little bug fix).
Also to detect images you'll need to extend the JSTools.js, here's mine with the extra functions.
function MyAppGetHTMLElementsAtPoint(x,y) {
var tags = ",";
var e = document.elementFromPoint(x,y);
while (e) {
if (e.tagName) {
tags += e.tagName + ',';
}
e = e.parentNode;
}
return tags;
}
function MyAppGetLinkSRCAtPoint(x,y) {
var tags = "";
var e = document.elementFromPoint(x,y);
while (e) {
if (e.src) {
tags += e.src;
break;
}
e = e.parentNode;
}
return tags;
}
function MyAppGetLinkHREFAtPoint(x,y) {
var tags = "";
var e = document.elementFromPoint(x,y);
while (e) {
if (e.href) {
tags += e.href;
break;
}
e = e.parentNode;
}
return tags;
}
Now you can detect the user clicking on images and actually find out the images url they are clicking on, but we need to change the -(void)openContextualMenuAtPoint: method to provide extra options.
Again here's mine (I tried to copy Safari's behaviour for this):
- (void)openContextualMenuAt:(CGPoint)pt{
// Load the JavaScript code from the Resources and inject it into the web page
NSString *path = [[NSBundle mainBundle] pathForResource:#"JSTools" ofType:#"js"];
NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString:jsCode];
// get the Tags at the touch location
NSString *tags = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:#"MyAppGetHTMLElementsAtPoint(%i,%i);",(NSInteger)pt.x,(NSInteger)pt.y]];
NSString *tagsHREF = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:#"MyAppGetLinkHREFAtPoint(%i,%i);",(NSInteger)pt.x,(NSInteger)pt.y]];
NSString *tagsSRC = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:#"MyAppGetLinkSRCAtPoint(%i,%i);",(NSInteger)pt.x,(NSInteger)pt.y]];
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
selectedLinkURL = #"";
selectedImageURL = #"";
// If an image was touched, add image-related buttons.
if ([tags rangeOfString:#",IMG,"].location != NSNotFound) {
selectedImageURL = tagsSRC;
if (sheet.title == nil) {
sheet.title = tagsSRC;
}
[sheet addButtonWithTitle:#"Save Image"];
[sheet addButtonWithTitle:#"Copy Image"];
}
// If a link is pressed add image buttons.
if ([tags rangeOfString:#",A,"].location != NSNotFound){
selectedLinkURL = tagsHREF;
sheet.title = tagsHREF;
[sheet addButtonWithTitle:#"Open"];
[sheet addButtonWithTitle:#"Copy"];
}
if (sheet.numberOfButtons > 0) {
[sheet addButtonWithTitle:#"Cancel"];
sheet.cancelButtonIndex = (sheet.numberOfButtons-1);
[sheet showInView:webView];
}
[selectedLinkURL retain];
[selectedImageURL retain];
[sheet release];
}
(NOTES: selectedLinkURL and selectedImageURL are declared in the .h file to let them be accessed throughout the class, for saving or opening the link latter.
So far we've just been going back over the tutorials code making changes but now we will move into what the tutorial doesn't cover (it stops before actually mentioning how to handle saving the images or opening the links).
To handle the users choice we now need to add the actionSheet:clickedButtonAtIndex: method.
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:#"Open"]){
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:selectedLinkURL]]];
}
else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:#"Copy"]){
[[UIPasteboard generalPasteboard] setString:selectedLinkURL];
}
else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:#"Copy Image"]){
[[UIPasteboard generalPasteboard] setString:selectedImageURL];
}
else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:#"Save Image"]){
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(saveImageURL:) object:selectedImageURL];
[queue addOperation:operation];
[operation release];
}
}
This checks what the user wants to do and handles /most/ of them, only the "save image" operation needs another method to handle that. For the progress I used MBProgressHub.
Add an MBProgressHUB *progressHud; to the interface declaration in the .h and set it up in the init method (of whatever class you're handling the webview from).
progressHud = [[MBProgressHUD alloc] initWithView:self.view];
progressHud.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Tick.png"]] autorelease];
progressHud.opacity = 0.8;
[self.view addSubview:progressHud];
[progressHud hide:NO];
progressHud.userInteractionEnabled = NO;
And the -(void)saveImageURL:(NSString*)url; method will actually save it to the image library.
(A better way would be to do the download through an NSURLRequest and update the progress hud in MBProgressHUDModeDeterminate to deflect how long it'll actually take to download, but this is a more hacked together implementation then that)
-(void)saveImageURL:(NSString*)url{
[self performSelectorOnMainThread:#selector(showStartSaveAlert) withObject:nil waitUntilDone:YES];
UIImageWriteToSavedPhotosAlbum([UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]], nil, nil, nil);
[self performSelectorOnMainThread:#selector(showFinishedSaveAlert) withObject:nil waitUntilDone:YES];
}
-(void)showStartSaveAlert{
progressHud.mode = MBProgressHUDModeIndeterminate;
progressHud.labelText = #"Saving Image...";
[progressHud show:YES];
}
-(void)showFinishedSaveAlert{
// Set custom view mode
progressHud.mode = MBProgressHUDModeCustomView;
progressHud.labelText = #"Completed";
[progressHud performSelector:#selector(hide:) withObject:[NSNumber numberWithBool:YES] afterDelay:0.5];
}
And of cause add [progressHud release]; to the dealloc method.
Hopefully this shows you how to add some of the options to a webView that apple left out.
Of cause though you can add more things to this like a "Read Later" option for instapaper or a "Open In Safari" button.
(looking at the length of this post I'm seeing why the original tutorial left out the finial implementation details)
Edit: (updated with more info)
I was asked about the detail I glossed over at the top, the #"tapAndHoldShortNotification", so this is clarifying it.
This is my UIWindow subclass, it adds the second notification to cancel the default selection menu (this is because when I tried the tutorial it showed both menus).
- (void)tapAndHoldAction:(NSTimer*)timer {
contextualMenuTimer = nil;
UIView* clickedView = [self hitTest:CGPointMake(tapLocation.x, tapLocation.y) withEvent:nil];
while (clickedView != nil) {
if ([clickedView isKindOfClass:[UIWebView class]]) {
break;
}
clickedView = clickedView.superview;
}
if (clickedView) {
NSDictionary *coord = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:tapLocation.x],#"x",
[NSNumber numberWithFloat:tapLocation.y],#"y",nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"TapAndHoldNotification" object:coord];
}
}
- (void)tapAndHoldActionShort:(NSTimer*)timer {
UIView* clickedView = [self hitTest:CGPointMake(tapLocation.x, tapLocation.y) withEvent:nil];
while (clickedView != nil) {
if ([clickedView isKindOfClass:[UIWebView class]]) {
break;
}
clickedView = clickedView.superview;
}
if (clickedView) {
NSDictionary *coord = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:tapLocation.x],#"x",
[NSNumber numberWithFloat:tapLocation.y],#"y",nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"TapAndHoldShortNotification" object:coord];
}
}
- (void)sendEvent:(UIEvent *)event {
NSSet *touches = [event touchesForWindow:self];
[touches retain];
[super sendEvent:event]; // Call super to make sure the event is processed as usual
if ([touches count] == 1) { // We're only interested in one-finger events
UITouch *touch = [touches anyObject];
switch ([touch phase]) {
case UITouchPhaseBegan: // A finger touched the screen
tapLocation = [touch locationInView:self];
[contextualMenuTimer invalidate];
contextualMenuTimer = [NSTimer scheduledTimerWithTimeInterval:0.8 target:self selector:#selector(tapAndHoldAction:) userInfo:nil repeats:NO];
NSTimer *myTimer;
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(tapAndHoldActionShort:) userInfo:nil repeats:NO];
break;
case UITouchPhaseEnded:
case UITouchPhaseMoved:
case UITouchPhaseCancelled:
[contextualMenuTimer invalidate];
contextualMenuTimer = nil;
break;
}
} else { // Multiple fingers are touching the screen
[contextualMenuTimer invalidate];
contextualMenuTimer = nil;
}
[touches release];
}
The notification is then handled like this:
// in -viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(stopSelection:) name:#"TapAndHoldShortNotification" object:nil];
- (void)stopSelection:(NSNotification*)notification{
[webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.style.webkitTouchCallout='none';"];
}
It's only a little change but it fixes the annoying little bug where you get 2 menus appear (the standard one and yours).
Also you could easily add iPad support by sending the touches location as the notification fires and then showing the UIActionSheet from that point, though this was written before the iPad so doesn't include support for that.
After struggling for, like 2 or 3 days non-stop on this problem, it seems like the position is computed "relatively" to the UIWebView's "TOP-LEFT" corner (I am programing for iOS 7).
So, to make this work, when you get the position, on the controller where your WebView is (i'll put a snippet of my code below), don't add the "scroll-offset"
SNIPPET - ContextualMenuAction:
- (void)contextualMenuAction:(NSNotification*)notification {
// Load javascript
[self loadJavascript];
// Initialize the coordinates
CGPoint pt;
pt.x = [[[notification object] objectForKey:#"x"] floatValue];
pt.y = [[[notification object] objectForKey:#"y"] floatValue];
// Convert point from window to view coordinate system
pt = [self.WebView convertPoint:pt fromView:nil];
// Get PAGE and UIWEBVIEW dimensions
CGSize pageDimensions = [self.WebView documentSize];
CGSize webviewDimensions = self.WebView.frame.size;
/***** If the page is in MOBILE version *****/
if (webviewDimensions.width == pageDimensions.width) {
}
/***** If the page is in DESKTOP version *****/
else {
// convert point from view to HTML coordinate system
CGSize viewSize = [self.WebView frame].size;
// Contiens la portion de la page visible depuis la webview (en fonction du zoom)
CGSize windowSize = [self.WebView windowSize];
CGFloat factor = windowSize.width / viewSize.width;
CGFloat factorHeight = windowSize.height / viewSize.height;
NSLog(#"factor: %f", factor);
pt.x = pt.x * factor; // ** logically, we would add the offset **
pt.y = pt.y * factorHeight; // ** logically, we would add the offset **
}
NSLog(#"x: %f and y: %f", pt.x, pt.y);
NSLog(#"WINDOW: width: %f height: %f", [self.WebView windowSize].width, [self.WebView windowSize].height);
NSLog(#"DOCUMENT: width: %f height: %f", pageDimensions.width, pageDimensions.height);
[self openContextualMenuAt:pt];
}
SNIPPET - in openContextualMenuAt:
To load the correct JS function:
- (void)openContextualMenuAt:(CGPoint)pt {
// Load javascript
[self loadJavascript];
// get the Tags at the touch location
NSString *tags = [self.WebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"getHTMLTagsAtPoint(%li,%li);",(long)pt.x,(long)pt.y]];
...
}
SNIPPET - in JSTools.js:
This is the function I use to get the element touched
function getHTMLTagsAtPoint(x,y) {
var tags = ",";
var element = document.elementFromPoint(x,y);
while (element) {
if (element.tagName) {
tags += element.tagName + ',';
}
element = element.parentNode;
}
return tags;
}
SNIPPET - loadJavascript
I use this one to inject my JS code in the webview
-(void)loadJavascript {
[self.WebView stringByEvaluatingJavaScriptFromString:
[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"JSTools" ofType:#"js"] encoding:NSUTF8StringEncoding error:nil]];
}
This part (everything I did to overrride the default UIActionSheet) is HEAVILY (should I say completely) based on
this post
#Freerunning's answer is complete (i did almost everything he said in my other classes, like on the post my code is based on), the snippets i posted is just to show you more "completely" how my code is.
Hope this helps! ^^
First of all thanks to Freerunnering for the great solution!
But you can do this with an UILongPressGestureRecognizer instead of a custom LongPressRecognizer. This makes things a bit easier to implement:
In the Viewcontroller Containing the webView:
Add UIGestureRecognizerDelegate to your ViewController
let mainJavascript = "function MyAppGetHTMLElementsAtPoint(x,y) { var tags = \",\"; var e = document.elementFromPoint(x,y); while (e) { if (e.tagName) { tags += e.tagName + ','; } e = e.parentNode; } return tags; } function MyAppGetLinkSRCAtPoint(x,y) { var tags = \"\"; var e = document.elementFromPoint(x,y); while (e) { if (e.src) { tags += e.src; break; } e = e.parentNode; } return tags; } function MyAppGetLinkHREFAtPoint(x,y) { var tags = \"\"; var e = document.elementFromPoint(x,y); while (e) { if (e.href) { tags += e.href; break; } e = e.parentNode; } return tags; }"
func viewDidLoad() {
...
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(CustomViewController.longPressRecognizerAction(_:)))
self.webView.scrollView.addGestureRecognizer(longPressRecognizer)
longPressRecognizer.delegate = self
...
}
func longPressRecognizerAction(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizerState.Began {
let tapPostion = sender.locationInView(self.webView)
let tags = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetHTMLElementsAtPoint(\(tapPostion.x),\(tapPostion.y));")
let href = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetLinkHREFAtPoint(\(tapPostion.x),\(tapPostion.y));")
let src = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetLinkSRCAtPoint(\(tapPostion.x),\(tapPostion.y));")
print("tags: \(tags)\nhref: \(href)\nsrc: \(src)")
// handle the results, for example with an UIDocumentInteractionController
}
}
// Without this function, the customLongPressRecognizer would be replaced by the original UIWebView LongPressRecognizer
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
And thats it!
I am working on with a simple animation that I have 10 button and "on click" of one button ( for example 5) all button should start animate one by on but they are animating the same time, please let me know what can be done or ..... Thanks
NSMutableArray* imagesArray = [[NSMutableArray alloc] init];
for (int images = 0; images < 15; images++) {
UIImage* buttonImage = [UIImage imageNamed:[NSString stringWithFormat:#"aaqqq00%02d.png", images]];
[imagesArray addObject:buttonImage];
}
NSArray* reversedAnim = [[imagesArray reverseObjectEnumerator] allObjects];
int buttonTag = button.tag;
for (int images = 1; images <= 10; images++) {
UIButton *animButton = (UIButton *)[self.view viewWithTag:images];
if (images <= buttonTag) {
animButton.imageView.animationImages = imagesArray;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0014.png"] forState:UIControlStateNormal];
animButton.adjustsImageWhenHighlighted = NO;
animButton.imageView.animationDuration = 1; //whatever you want (in seconds)
animButton.imageView.animationRepeatCount = 1;
[animButton.imageView startAnimating];
} else {
if (currentButtonTag_ >= images) {
animButton.imageView.animationImages = reversedAnim;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0000.png"] forState:UIControlStateNormal];
animButton.adjustsImageWhenHighlighted = NO;
animButton.imageView.animationDuration = 0.2; //whatever you want (in seconds)
animButton.imageView.animationRepeatCount = 1;
[animButton.imageView startAnimating];
}
}
}
As you iterate through your loop, have a variable that holds the desired delay, and add to it at the end of each loop. We'll call this delay.
Now, instead of calling:
[animButton.imageView startAnimating];
Do this:
[animButton.imageView performSelector:#selector(startAnimating) withObject:nil afterDelay:delay];
And each button will start animating after the accumulated delay.
You need to give some delay time and duration time.
[UIView animateWithDuration:0.6
delay:2.0
options: UIViewAnimationCurveEaseOut
animations:^{S1Button.frame = CGRectMake(20, 10, 50, 10);S1buttonA.alpha = 0;}
completion:nil];
Set this for every animation.
I have this simple function where i sap rate the button animation and then start animation for every button but i dont know why only one button animate not others which clicked, please help me with this
- (IBAction)startAnimation:(UIButton *)button {
NSMutableArray* imagesArray = [[NSMutableArray alloc] init];
for (int images = 0; images < 15; images++) {
UIImage* buttonImage = [UIImage imageNamed:[NSString stringWithFormat:#"aaqqq00%02d.png", images]];
[imagesArray addObject:buttonImage];
}
NSArray* reversedAnim = [[imagesArray reverseObjectEnumerator] allObjects];
int buttonTag = button.tag;
animButton.adjustsImageWhenHighlighted = NO;
for (int images = 0; images < 15; images++) {
UIButton *animButton = (UIButton *)[self.view viewWithTag:buttonTag];
if (images <= buttonTag) {
animButton.imageView.animationImages = imagesArray;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0014.png"] forState:UIControlStateNormal];
} else {
animButton.imageView.animationImages = reversedAnim;
[animButton setImage:
[UIImage imageNamed:#"aaqqq0000.png"] forState:UIControlStateSelected];
}
NSLog(#"%#", animButton.imageView.animationImages);
animButton.imageView.animationDuration = 1; //whatever you want (in seconds)
animButton.imageView.animationRepeatCount = 1;
[animButton.imageView startAnimating];
}
}
You're passing the button, so doing the tag lookup seem pointless and error prone (if there are multiple views with the same tag in the hierarchy).
Setting the buttons image view animation images (animButton.imageView.animationImages) and then after that setting a single image ([animButton setImage:...) is also pointless.
What does your log statement say about the animation images?
I am using a UIImageView to display both still and animated images. So sometimes, I'm using .image and sometimes I'm using .animationImages. This is fine.
Whether it's static or animated, I store the UIImages's in item.frames (see below)
The problem is that I'd like to display a UIActivityIndicatorView in the center of the view when the animation frames are loading. I would like this to happen with no images or frames in there. The line that isn't doing what it's supposed to is:
[self.imageView removeFromSuperview];
As a matter of fact, setting it to another image at this point doesn't do anything either. It seems like none of the UI stuff is happening in here. BTW,
NSLog(#"%#", [NSThread isMainThread]?#"IS MAIN":#"IS NOT");
prints IS MAIN.
The image that is in there will stick around until the new animation frames are all in there (1-2 seconds) and they start animating
This is all being run from a subclass of UIView with the UIImageView as a subview.
- (void)loadItem:(StructuresItem *)item{
self.imageView.animationImages = nil;
self.imageView.image = nil;
[self.spinner startAnimating];
self.item = item;
if (item.frameCount.intValue ==1){
self.imageView.image = [item.frames objectAtIndex:0];
self.imageView.animationImages = nil;
}else {
[self.imageView removeFromSuperview];
self.imageView =[[UIImageView alloc] initWithFrame:self.bounds];
[self addSubview:self.imageView ];
if( self.imageView.isAnimating){
[self.imageView stopAnimating];
}
self.imageView.animationImages = item.frames;
self.imageView.animationDuration = self.imageView.animationImages.count/12.0f;
//if the image doesn't loop, freeze it at the end
if (!item.loop){
self.imageView.image = [self.imageView.animationImages lastObject];
self.imageView.animationRepeatCount = 1;
}
[self.imageView startAnimating];
}
[self.spinner stopAnimating];
}
My ignorant assessment is that something isn't being redrawn once that image is set to nil. Would love a hand.
What I have found is not an answer to the question, but rather a much better approach to the problem. Simply, use NSTimer instead of animationImages. It loads much faster, doesn't exhaust memory and is simpler code. yay!
Do this:
-(void)stepFrame{
self.currentFrameIndex = (self.currentFrameIndex + 1) % self.item.frames.count;
self.imageView.image = [self.item.frames objectAtIndex:self.currentFrameIndex];
}
and this
-(void)run{
if (self.item.frameCount.intValue>1){
self.imageView.image = [self.item.frames objectAtIndex:self.currentFrameIndex];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1/24.0f target:self selector:#selector(stepFrame) userInfo:nil repeats:YES];
}else{
self.imageView.image = [self.item.frames objectAtIndex:0];
}
}
I am trying to check if a image of a subview is hidden or not, by clicking a button. The log does display but i cant get the hidden status of the image somehow.
Whats going wrong here? Hope u can help me!
Viewdidload:
SubSlide1Hoofdstuk3 *subslide1 = [[SubSlide1Hoofdstuk3 alloc] init];
CGRect frame = self.view.frame;
frame.origin.x = 0;
frame.origin.y = 0;
subslide1.view.frame = frame;
// This works finaly
UIImageView *zwart = subslide1.imageZwart;
[zwart setImage:[UIImage imageNamed:#"imageblack.jpg"]];
[subslide1.b1 addTarget:self action:#selector(switchImageZwart:) forControlEvents:UIControlEventTouchUpInside];
[_scrollView addSubview:subslide1.view];
The IBAction to check the image in subview is hidden:
-(IBAction)switchImageZwart:(id)sender
{
SubSlide1Hoofdstuk3 *switchactie = [[SubSlide1Hoofdstuk3 alloc] init];
UIImageView *wit = switchactie.imageWit;
UIImageView *zwart = switchactie.imageZwart;
if(zwart.hidden == YES) {
NSLog(#"Image black is hidden!");
} else if(wit.hidden == YES) {
NSLog(#"Image white is hidden!");
} else {
NSLog(#"Can't say... :(");
}
}
The problem here is that inside your -(IBAction)switchImageZwart:(id)sender method you create a new instance of SubSlide1Hoofdstuk3 and checking its properties (the UIImageViews) instead of checking the actual UIImageView objects you created on viewDidLoad:. What you want actually is to hold a reference to subslide1 and check that instead.
Ps. Since the button calling the check method is actually a subview of your subslide1, you could get a reference like:
SubSlide1Hoofdstuk3 *switchactie = [sender superView];
EDIT: An example on your actual code:
in your .h file:
#property(nonatomic, strong) SubSlide1Hoofdstuk3 *subslide1;
in your .m file:
#synthesize subslide1;
- (void)viewDidLoad
{
//...
self.subslide1 = [[SubSlide1Hoofdstuk3 alloc] init];
CGRect frame = self.view.frame;
frame.origin.x = 0;
frame.origin.y = 0;
self.subslide1.view.frame = frame;
// This works finaly
UIImageView *zwart = self.subslide1.imageZwart;
[zwart setImage:[UIImage imageNamed:#"imageblack.jpg"]];
[self.subslide1.b1 addTarget:self action:#selector(switchImageZwart:) forControlEvents:UIControlEventTouchUpInside];
[_scrollView addSubview:self.subslide1.view];
}
-(IBAction)switchImageZwart:(id)sender
{
SubSlide1Hoofdstuk3 *switchactie = self.subslide1;
UIImageView *wit = switchactie.imageWit;
UIImageView *zwart = switchactie.imageZwart;
if(zwart.hidden == YES) {
NSLog(#"Image black is hidden!");
} else if(wit.hidden == YES) {
NSLog(#"Image white is hidden!");
} else {
NSLog(#"Can't say... :(");
}
}