Objective-C Can't Find Instance Method of Imported WKWebView - ios

I am using a WKWebView and I am trying to set its magnification with the setMagnification instance method in a class that the webView is a variable of. Whenever I try to compile I get:
No visible #interface for 'WKWebView' declares the selector 'setMagnification:centeredAt:'
despite the fact that WebKit is being imported.
-(void)zoomIn:(int) xCoord y:(int) yCoord
{
CGPoint myPoint = CGPointMake(xCoord, yCoord);
[_webView setMagnification:3 centeredAt:myPoint]
}
Edit:
Just learned why this does not work is because it is OSX only, and I need it for iOS. If you have an alternative for iOS, please let me know.

Related

Swift - Use of unresolved identifier error after update

I updated my OS to El Capitan and at the same time I guess XCode got updated (Now 7.2), prior to this when I would run my code in the simulator it worked fine. Now When I try to run the code for a calendar in my first view controller in a tabbed application it gives me the error "use of unresolved identifier 'SACalendar'" however everything else seems to be okay. I'm not sure if there was any syntax changes or something with the update, but it seems to be a common issue so I tried to review some other postings but was unable to find anything pertaining to my issue. Does anyone know whats going on? There error is in the code below, and SACalendar is a .m file that is included via bridging header. The bridging header does include all the necessary .h files, including the SACalendar.h
import UIKit
class FirstViewController: UIViewController, SACalendarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
/*
* Smooth scrolling in vertical direction
* - to change to horizontal, change the scrollDirection to ScrollDirectionHorizontal
* - to use paging scrolling, change pagingEnabled to true
* - the calendar works with any size
*/
//Get the width and the height of the device
let frameWidth = self.view!.frame.size.width
let frameHeight = self.view!.frame.size.height - 110
var calendar : SACalendar = SACalendar(frame: CGRectMake(0, 80, frameWidth, frameHeight), scrollDirection: ScrollDirectionVertical, pagingEnabled: true)
//error occurs due to the SACalendar on the righthand side of assignment operator
calendar.delegate = self
self.view!.addSubview(calendar)
}
}
The bridging header:
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#ifndef YogaAdmin_Bridging_Header_h
#define YogaAdmin_Bridging_Header_h
#import "DateUtil.h"
#import "DMLazyScrollView.h"
#import "SACalendar.h"
#import "SACalendarCell.h"
#import "SACalendarConstants.h"
#endif
I was facing same issue and I was finding that delegate functions names same as class name which was creating issues in swift so i was solved it by change Delegate functions name.
-(void) SACalendar:(SACalendar*)calendar didDisplayCalendarForMonth:(int)month year:(int)year;
-(void) SACalendar:(SACalendar*)calendar didSelectDate:(int)day month:(int)month year:(int)year;
TO
-(void) Calendar:(SACalendar*)calendar didDisplayCalendarForMonth:(int)month year:(int)year;
-(void) Calendar:(SACalendar*)calendar didSelectDate:(int)day month:(int)month year:(int)year;
And Replaced SACalendar to Calendar where delegate functions are called.
Thanks

How to use swift class in objective c (not an instance of the class)

All tutorials for using swift code in a primarily objective-c app goes through this process mentioned in this Apple document https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
But this methodology of importing a xyzProjectName-swift.h file and then using
MySwiftClass *swiftObject = [[MySwiftClass alloc] init];
[swiftObject swiftMethod];
required me to create an instance of that swift class. Is it possible to directly access the class itself like [MySwiftClass swiftMethod];
I have not been able to do this until now. Do I have to change my swift code in a certain way to achieve this?
Just tried the following:
class MySwiftClass: NSObject {
static func swiftMethod() -> String {
return "hello"
}
}
And in Objective-C:
NSLog(#"Received from Swift: %#", [MySwiftClass swiftMethod]);
Works for me - are you sure your swiftMethod is static, and not private? You could also try adding #objc in front of the static func – if nothing else, at least it might warn you if there is a reason it can't be accessed from Objective-C.

Cannot access variables in a Swift class from Objective-C file

I'm trying to continue with Swift in an existing project I had started in Objective-C. I followed the Apple documentation and I managed to access a Swift class from an Objective-C file, via including the "ProductModuleName-Swift.h" header in my Obj-C file.
At this point here's my code:
#include "Pianoconcert_App-Swift.h"
#interface ModelsVC ()
#end
#implementation ModelsVC
// And all that kind of stuff
// ...
-(IBAction)comanda:(UIButton *)sender {
ComandaTableVC *controller = (ComandaTableVC *)self.tabBarController.viewControllers[2];
// Here goes the problematic code
[self.tabBarController setSelectedIndex:2];
}
This piece of code has no problems. But now I just want to set one of the variables in the Swift class like this: controller.selectedModel = sender.tag, but Xcode just tells me the variable does not exist.
Here's an extract of my Swift class:
import UIKit
class ComandaTableVC: UITableViewController, UIPickerViewDataSource, UIPickerViewDelegate {
// Declaration of some constants and variables
// And here goes the one
var selectedModel: Int = 0
// And a bunch more of variables and functions
// ...
}
I don't know what I'm doing wrong. The class seems fully included and, actually, I can access that variable and all the others if I use the class from another Swift file, like this:
var controller: ComandaTableVC = self.tabBarController.viewControllers[2] as ComandaTableVC
controller.selectedModel = 2
It's been resolved finally, but I can't explain how.
Suddenly the compiler threw a build error telling me that the file Pianoconcert_App-Swift.h could not be found.
I changed it for PianoconcertApp-Swift.h, deleting the underscore that replaced the blank space, and now I can access all the variables and constants correctly.

How to use Objective-C code with #define macros in Swift

I'm trying to use a third-party Objective-C library in a Swift project of mine. I have the library successfully imported into Xcode, and I've made a <Project>-Bridging-Header.h file that's allowing me to use my Objective-C classes in Swift.
I seem to be running into one issue however: the Objective-C code includes a Constants.h file with the macro #define AD_SIZE CGSizeMake(320, 50). Importing Constants.h into my <Project>-Bridging-Header.h doesn't result in a global constant AD_SIZE that my Swift app can use.
I did some research and saw that the Apple documentation here under "Complex Macros" says that
β€œIn Swift, you can use functions and generics to achieve the same
results [as complex macros] without any compromises. Therefore, the
complex macros that are in C and Objective-C source files are not made
available to your Swift code.”
After reading that, I got it to work fine by specifying let AD_SIZE = CGSizeMake(320, 50) in Swift, but I want to maintain future compatibility with the library in the event that these values change without me knowing.
Is there an easy fix for this in Swift or my bridging header? If not, is there a way to replace the #define AD_SIZE CGSizeMake(320, 50) in Constants.h and keep things backwards-compatible with any existing Objective-C apps that use the old AD_SIZE macro?
What I did is to create a class method that returns the #define.
Example:
.h file:
#define AD_SIZE CGSizeMake(320, 50)
+ (CGSize)adSize;
.m file:
+ (CGSize)adSize { return AD_SIZE; }
And in Swift:
Since this is a class method you can now use it almost as you would the #define.
If you change your #define macro - it will be reflected in the new method you created
In Swift:
let size = YourClass.adSize()
I resolved this by replacing
#define AD_SIZE CGSizeMake(320, 50)
in the library's Constants.h with
extern CGSize const AD_SIZE;
and adding
CGSize const AD_SIZE = { .width = 320.0f, .height = 50.0f };
in the library's Constants.m file.
write your constants after Class declaration. like this...
class ForgotPasswrdViewController: UIViewController {
let IS_IPHONE5 = fabs(UIScreen.mainScreen().bounds.size.height-568) < 1;
let Tag_iamTxtf = 101

how do I make an objective-c delegate for a cpp class?

I'm stuck trying to combine openGL-es (xcode openGL game template with the ogles2tools library from powervr 3.0 sdk. My problem is the line of code where I load the effect file:
/*
Load the effect.
We pass 'this' as an argument as we wish to receive callbacks as the PFX is loaded.
This is optional and supplying NULL implies that the developer will take care
of all texture loading and binding to to the Effect instead.
*/
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, NULL, uiUnknownUniforms, &error) != PVR_SUCCESS)
{
NSLog(#"%s",error.c_str());
return;
}
I'm supposed to pass a "this" pointer so I can receive the callbacks. The delegate method I need to implement is:
EPVRTError OGLES2IntroducingPFX::PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags)
{
/*
This is an optional callback function for PVRTPFXEffect and can be used to automate
the texture loading process.
If multiple effects are to be loaded and they share textures it would be
prudent to have a caching system in place so texture memory is not wasted.
Please see OGLES2MagicLantern for an example of this.
*/
if(PVRTTextureLoadFromPVR(TextureName.String().c_str(), &uiHandle) != PVR_SUCCESS)
return PVR_FAIL;
return PVR_SUCCESS;
}
I guess the big issue for me is how do I go about providing a cpp delegate method in objective-c? I did some reading on this issue, but it seemed what I was reading was going the other way. That is, an objective-c delegate in cpp. It's pretty confusing, but here's my thought...
I create a cpp class the implements the method I need. I add that to my viewController class and pass the pointer to this cpp class in the m_pEffect->Load call. Does this seem correct?
Thanks.
P.S. Sorry if my code formatting is bad. I'm still learning.
Edit: Here's the example I found regarding mixing the objective-c and cpp. It seems really similar to what I want to do.
Update: Here's some additional info (requested by user1118321)
The CPP class which needs a delegate is CPVRTPFXEffect (PVRTPFXParserAPI.h - from powerVR SDK 3.0). I would add a link, but I'm not sure if this is allowed. Here's a link to the class header, but this version (and others on the web) did not include the pDelegate attribute for the load method. I'm assuming they are examples of a previous version. Let me know if it's okay to post this class file and I will do so.
I found a good example of what I think I'm supposed to do from reading this thread. So here's what I have so far:
My CPP delegate class...
class myCppDelegate : public PVRTPFXEffectDelegate {
public:
myCppDelegate() {};
EPVRTError PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags) {
return PVR_FAIL;
};
};
My Obj-C wrapper class (just modified from the example link above)...
struct RNWrapOpaque;
#interface RNWrap : NSObject {
struct RNWrapOpaque *_cpp;
}
- (id)init;
#end
implementation...
#import "RNWrap.h"
#import "Wrap.h"
#interface RNWrap ()
#property (nonatomic, readwrite, assign) RNWrapOpaque *cpp;
#end
#implementation RNWrap
#synthesize cpp = _cpp;
struct RNWrapOpaque
{
public:
RNWrapOpaque() : wrap() {};
myCppDelegate wrap;
};
- (id)init
{
self = [super init];
if (self != nil)
{
self.cpp = new RNWrapOpaque();
}
return self;
}
- (void)dealloc
{
delete _cpp;
_cpp = NULL;
// [super dealloc];
}
#end
Basically I am able to compile the code and debug, but when the the CPVRTPFEffect class makes this call:
if(pDelegate->PVRTPFXOnLoadTexture(pTexDesc->FileName, uiHandle, uiFlags) != PVR_SUCCESS)
I get EXC_BAD_ACCESS. I'm assuming it's not finding my callback method, because I set a breakpoint and the line never gets called.
Here's my updated code which calls CPVRTPFXEffect::Load using a bridge command for the delegate parameter.
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)
Thanks for your help!
Update 2: The project uses ARC. Here's what my viewController interface looks like:
#interface ViewController : GLKViewController {
...
RNWrap* opaqueCppWrap;
...
}
#property (strong) RNWrap *opaqueCppWrap;
Adding the #property didn't help with the EXC_BAD_ACCESS. I'm not sure how to "see" the value of pDelegate when I'm tracing the CPP code. Xcode doesn't reveal anything when I hover over the variable.
I added the following line of code to the CPVRTPFXEffect::Load method (just prior to the line where it crashes):
*pReturnError += PVRTStringFromFormattedStr("Here is your class typeid: %s.\n", typeid(pDelegate).name());
return PVR_FAIL;
This is what displayed in the debug output window:
Here is your class typeid: P21PVRTPFXEffectDelegate.
I'm not sure what the "P21" means (if anything), but it looks like I'm close to getting this working. I dunno, maybe this is as close as it gets. Still crashing and not finding my method.
First, you may want to look at the last article in the series on wrapping C++. Most of it has gotten much simpler in the latest versions of clang. You probably don't need half this code anymore. ObjC++ objects can now have private C++ properties without any tricks, while maintaining a pure-ObjC interface.
Here is how you want to think about this problem:
Build a C++ object that is the delegate. Write all the code involved in setting up the delegation, etc, in C++. So when it says "pass a this pointer" you should really be passing a this pointer (because you should be doing this in the C++ code). The fact that you're doing a _bridge cast in a C++ call is a real hint something is going wrong.
Let an ObjC own the C++ object as a property.
Write the delegate callbacks in C++ inside the C++ object. If useful, you can let the C++ object then make calls into the ObjC object as needed, but it may be easier if the C++ object does all the delegate work.
I finally got this working, but had to remove the obj-c wrapper class from my viewController in order to do so. Here's what the code looks like:
ViewController.h
struct Opaque;
#interface ViewController : GLKViewController {
...
//RNWrap* opaqueCppWrap; // this didn't work
struct Opaque *opaqueCpp; // try this
...
}
ViewController.mm
// declare the Opaque structure
struct Opaque {
public:
Opaque() : cppobject() {};
myCppDelegate cppobject;
};
viewDidLoad
// ... create opaque member on initialization
opaqueCpp = new Opaque();
//opaqueCppWrap = [[RNWrap alloc] init]; // old way of doing things using wrapper
pass the delegate to the Load method
// old way using bridge cast and wrapper
//if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)
// this works...
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, (myCppDelegate*)opaqueCpp, uiUnknownUniforms, &error) != PVR_SUCCESS)
Not sure why the wrapper class doesn't work, but I'm happy that my callback is working (appy no crashy!)
Phew, that was rough. Any thoughts/comments?

Resources