Call Function When WebView Changes - objective-c

So, I've been looking at the documentation and Googling, but I can't figure out how to call a method when my WebView (OSX, not iOS), changes... All the examples seem to be for iOS. My code looks like this:
SNAFAppDelegate.h
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
#interface SNAFAppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet WebView *browser;
- (IBAction)forwards:(id)sender;
#end
SNAFAppDelegate.m
#import "SNAFAppDelegate.h"
#implementation SNAFAppDelegate
#synthesize window = _window;
#synthesize browser = _b;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[_b mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"https://google.com"]]];
}
#end
SNAFBrowser.h
#import <Cocoa/Cocoa.h>
#import <WebKit/WebView.h>
#import <WebKit/WebFrame.h>
#import <WebKit/WebEditingDelegate.h>
#import <WebKit/WebKit.h>
#interface SNAFBrowser : WebView
#property (assign) IBOutlet WebView *browser;
#end
SNAFBrowser.m
#import "SNAFBrowser.h"
#implementation SNAFBrowser
#synthesize browser = _b;
- (void)webViewDidChange:(NSNotification *)notification
{
NSLog(#"Hello World");
}
#end
Then, in my MainMenu.xib file, I linked the Outlet "browser" from the AppDelegate to the WebView and set the WebView's custom class to SNAFBrowser.
Essentially, I just want to know when the webview loads another page.
I'm probably doing something ridiculously stupid, so any help is appreciated.

Implement the WebFrameLoadDelegate protocol, and see which methods are suitable to implement, for example webView:didFinishLoadForFrame:.
Example:
#interface SNAFBrowser : WebView <WebFrameLoadDelegate>
...
#end
#implementation SNAFBrowser
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
NSLog(#"Something got loaded!");
}
...
#end

Related

"missing setter or instance variable" log message occurs initializing NSWindowController with Objective-C in Xcode:

Here is an abstract I took from an app that already works in which a parent window and sheet are processed. The abstract here compiles, launches, and displays the parent window without having received the message I sent to its text field. The run produces 'missing setter or instance variable' log messages for the text field, the button, and the window itself. For some reason I have not gotten the parent window to be properly initialized, and I suspect I will have the same problem with the sheet window but I can't get past this problem to debug the rest of the app.
I believe I have omitted something fundamental in the process of connecting the window to its File's Owner, even though when looking at the connections inspector for the .xib it shows the custom class to be the ParentClass and the various connections are made. I can find no instructions in Apple's labyrinthine documentation nor here in StackOverflow to guide me through the connection process that would allow me to discover the part(s) I'm missing.
Anything you can offer will be gratefully studied.
ParentDelegate.h
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#class ParentClass;
#interface ParentDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow * window;
#property (weak, nonatomic) ParentClass * parentController;
#end
ParentDelegate.m
#import "ParentDelegate.h"
#implementation ParentDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { }
- (void)applicationDidBecomeActive:(NSNotification *)aNotification { }
- (void)applicationDidResignActive:(NSNotification *)aNotification { }
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
{ return YES; }
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{ return NSTerminateNow; }
#end
ParentClass.h
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#interface ParentClass : NSWindowController {
}
#property (assign) IBOutlet NSWindow * window;
#property IBOutlet NSTextField * messageTextField;
#property IBOutlet NSButton * proceedButton;
#property (strong) NSMutableString * parentPropInfo;
- (IBAction) awakeFromNib;
- (IBAction) doProceed:(id)sender;
#end
ParentClass.m
#import "ParentClass.h"
#import "ParentDelegate.h"
#import "SheetClass.h"
#implementation ParentClass
ParentDelegate * parentDelegate;
SheetClass * sheetController;
- (IBAction)awakeFromNib {
parentDelegate = [NSApplication sharedApplication].delegate;
parentDelegate.parentController = self;
sheetController = [[SheetClass alloc] initWithWindowNibName: #"SheetClass"];
_messageTextField.stringValue = #"Click Proceed button";
}
- (IBAction)doProceed:(id)sender {
_parentPropInfo = #"Hello!".mutableCopy;
[NSApp runModalForWindow:sheetController.window];
// Sheet active now until it issues endModal, then:
_messageTextField.stringValue = sheetController.sheetPropInfo;
[NSApp endSheet: sheetController.window];
[sheetController.window orderOut:self];
}
#end
SheetClass.h
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#interface SheetClass : NSWindowController {
}
#property (assign) IBOutlet NSWindow * window;
#property (weak) IBOutlet NSTextField * propTextField;
#property (weak) IBOutlet NSButton * returnButton;
#property (strong) NSMutableString * sheetPropInfo;
- (IBAction)awakeFromNib;
- (IBAction)doReturn:(id)sender;
#end
SheetClass.m
#import "SheetClass.h"
#import "ParentClass.h"
#implementation SheetClass
ParentClass * parent;
- (IBAction)awakeFromNib {
parent.window = self.window.sheetParent;
_propTextField.stringValue = parent.parentPropInfo;
}
- (IBAction)doReturn:(id)sender {
_sheetPropInfo = #"Done!".mutableCopy;
[NSApp stopModal];
}
#end
Ultimately I would like to use this mini-app as a starting template for several other apps.

EXEC_BAD_ACCESS when clicking on a button in objective C

I am just learning and trying to put forth some of the knowledge with objective c and cocoa. I have a little program that has a login screen which then displays a main menu. On the main menu view, there is a button that should load a view to be able to add some data to the app. When I click on the button, it doesn't fire the IBAction but throws an error
EXC_BAD_ACCESS [StartMenuViewController performSelector:withObject:]: message sent to deallocated instance 0x6080195e9f90
I know that it is because there is an object that is not instantiated when the message is being sent, but I cannot find out why. Sorry for the code and the novice level here is the main menu view controller StartMenuViewController.m file:
#import "StartMenuViewController.h"
#import "AppDelegate.h"
#import "MasterViewController.h"
#interface StartMenuViewController ()
#end
#implementation StartMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
}
-(IBAction)showStrainView:(id)sender{
AppDelegate *delegate = nil;
delegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
MasterViewController *addStrainView = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[delegate swapView:self.view toView:addStrainView.view];
}
#end
here is the StartMenuViewController.h
#import <Cocoa/Cocoa.h>
#interface StartMenuViewController : NSViewController
#property (weak) IBOutlet NSButton *showStrainViewButton;
#end
Here is the AppDelegate.h
#import <Cocoa/Cocoa.h>
#class loginView, MasterViewController,StartMenuViewController;
#interface AppDelegate : NSObject <NSApplicationDelegate>{
loginView *loginView;
MasterViewController *masterViewController;
}
#property (assign) IBOutlet NSWindow *window;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (strong) loginView *loginView;
#property (strong) MasterViewController *masterViewController;
#property (strong) StartMenuViewController *starMenuViewController;
-(void)swapView:(NSView *)view1 toView:(NSView *)view2;
#end
Here is the AppDelegate.m
#import "AppDelegate.h"
#include "MasterViewController.h"
#import "ScaryBugDoc.h"
#import "Strains.h"
#import "loginView.h"
#interface AppDelegate()
#end
#implementation AppDelegate
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
#synthesize loginView;
#synthesize masterViewController;
#synthesize starMenuViewController;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// 1. Create the master View Controller
self.loginView = [[loginView alloc] initWithNibName:#"loginView" bundle:nil];
// 2. Add the view controller to the Window's content view
[self.window.contentView addSubview:self.loginView.view];
self.loginView.view.frame = ((NSView*)self.window.contentView).bounds;
}
-(void)swapView:(NSView *)view1 toView:(NSView *)view2{
//[view1 removeFromSuperview];
[self.window.contentView addSubview:view2];
view2.frame = ((NSView*)self.window.contentView).bounds;
}
#end
If you need the loginView.h and loginView.m files I can add them as well. I would appreciate any and all help. Thanks in advance
The problem is here:
MasterViewController *addStrainView = [[MasterViewController alloc]initWithNibName:#"MasterViewController" bundle:nil];
[delegate swapView:self.view toView:addStrainView.view];
You don't keep a reference to the MasterViewController so it gets deallocated even though its view is kept around. Now anytime the view tries to access methods from the view controller, things fail.
You should make addStrainView a child view controller of self in the above code so the view controller sticks around as long as its view.

Xcode (creating app for mac os). WebView does't download page

library file (AppDelegate.h) :
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
#private
__unsafe_unretained NSWindow *window;
__unsafe_unretained WebView *wview;
}
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet WebView *wview;
#end
Xcode did not compile my code, before i add __unsafe_unretained in private (Existing instance variable 'window' for property 'window' with assign attribute must be __unsafe_unretained).
main file (AppDelegate.m) :
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window;
#synthesize wview;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[wview mainFrame]loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: #"http://vk.com"]]];
}
- (IBAction)wview:(id)sender {
[[wview mainFrame]loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString:#"http://vk.com"]]];
}
#end

Setting up the App Delegate to Manage Data

I'm working on an app with a Split View controller and would like to store the main data class in the App Delegate so I can access it from multiple views (MasterView, DetailView, and several PopUps).
I'm a bit of a noob and can't figure out why Im getting the error:
AppDelegate.m:31:26: Property 'dataController' not found on object of type 'MasterViewController'
Below is the relevant code - any help is much appreciated. Thanks.
AppDelegate.h
#import <UIKit/UIKit.h>
#class EventClassDataController;
#class MasterViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
AppDelegate.m
#import <UIKit/UIKit.h>
#class EventClassDataController;
#class MasterViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
MasterViewController.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#class EventClassDataController;
#interface MasterViewController : UITableViewController
#property (strong, nonatomic) EventClassDataController *dataController;
#property (strong, nonatomic) DetailViewController *detailViewController;
#end
MasterViewController.m
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "EventClassDataController.h"
#import "EventClass.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
#synthesize detailViewController, dataController;
- (void)awakeFromNib
{
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
[super awakeFromNib];
// Initialize event data
self.dataController = [[EventClassDataController alloc] init];
}
EventClassDataController.h
#import <Foundation/Foundation.h>
#class EventClass;
#interface EventClassDataController : NSObject
#property (nonatomic, copy) NSMutableArray *masterEventList;
-(NSUInteger)countOfList;
-(EventClass *)objectInListAtIndex:(NSUInteger)theIndex;
-(void)addNewEvent:(EventClass *)event;
-(void)removeEvent:(EventClass *)event;
#end
You need to add
#import "MasterViewController.h"
to AppDelegate.m.
Explantation:
From your error message I can tell that you're trying to access a property of MasterViewController on line 26 of your AppDelegate. However, in your AppDelegate class you only have a forward declaration ("#class MasterViewController") and you don't include the actual header file for MasterViewController. What this means is that AppDelegate knows there exists a class named MasterViewController somewhere in your project... but that's all it knows. AppDelegate doesn't know anything about the contents of MasterViewController, i.e. properties or methods MasterViewController declares.
The reason to use #class in a header file is so that you can have properties in an #interface such as
#property (nonatomic, strong) MasterViewController * appDelegatesReferenceToMasterViewController;
without having to import MasterViewController.h in AppDelegate.h. This way, other files in your project can import AppDelegate.h without also inadvertently importing MasterViewController.h.
Translation:
You writing the code:
#class MasterViewController;
is like saying to the compiler:
Yo... compiler. I'm going to be talking about something called MasterViewController in this header file and you don't know what a MasterViewController is... but don't trip out bro. It's all good.
But then, later in the .m file after you write the code:
... masterViewController.dataController ...
the compiler responds:
Whoa, whoa, whoa. I was cool with you just having a variable with the type MasterViewController in the header file because you told me it was all good and not to worry. But now here you are trying to use some aspect of MasterViewController that I know nothing about. How am I supposed to know if this is legal or not? Not cool bro.

Method in objective-c never called

I've got this class.
.h:
#import
#class GLEngine;
#interface opengl_engineAppDelegate : NSObject {
// Pointer to engine
GLEngine * myGLEngine;
UIWindow * window;
}
#property (nonatomic, retain) IBOutlet GLEngine * myGLEngine;
#property (nonatomic, retain) IBOutlet UIWindow * window;
#end
Here is .m:
#import "opengl_engineAppDelegate.h"
#import "GLEngine.h"
#implementation opengl_engineAppDelegate
#synthesize window;
#synthesize myGLEngine;
// Creating Application
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[myGLEngine activateEngine];
return YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[myGLEngine activateEngine];
}
// Destroying Application
- (void)dealloc {
[window release];
[myGLEngine release];
[super dealloc];
}
#end
And GLEngine looks like:
#import
#import
#import
#import
#import
#import
#interface GLEngine : UIView {
}
- (void)activateEngine;
#end
Why activateEngine never calls?
It looks like you are never allocing myGLEngine or setting it to anything. You should set a breakpoint at the activateEngine call and check that myGLEngine is actually the object you think it is.