I am suppose to extend a objective C class in swift which has a class extension in different header file with +Protected. The same is implemented in one .m file as usual.
But my problem is If i subclass this class I cannot use the variables and cannot call any methods which are private. But in Objective C if I subclass and import the same +Protected.h file in .m file I can use the private vars and methods of the super class. Can anyone show the way to do it I mean subclass and use the private methods and vars of it in swift as we are able to do in Objective C. Example is show below
#interface Parent : NSObject
#end
In seperate header file
#interface Parent()
#property NSInteger money;
-(void)spend;
#end
#import "Parent+Protected.h"
#implementation Parent
#end
Using other files for new class
#interface ObjCChild : Parent
#end
#import "Parent+Protected.h"
#implementation ObjCChild
-(void)spend {
self.money--;
}
#end
I am trying the same in swift
class SwiftChild : Parent {
override func spend () {
self.money--
}
}
Here only ObjCChild can spend money not swift child(Even it wont get money :) ). Can anyone help swift child.???
Related
I have 2 classes,
class A(Obj-C) and
class B(Swift).
Class A has a delegate protocol
#protocol ADelegate<NSObject>
- (void)someMethod:(NSString *)str;
#end
to which class B conforms:
class B: ADelegate { ... }
But the issue is, the other Objective-C classes which use class B as a property can access to those delegate methods to which my Swift class conforms. For example, there is a class C(Obj-C):
#interface Class_C_ViewController ()
#property (nonatomic, strong) B *classB_property;
- (void)viewDidLoad {
[self.classB_property someMethod: #""];
}
#end
So basically that Swift property can access and call the delegate methods from another Obj-C class.
Is there a way to make those methods private, so no other class can call those methods but Swift class?
I really hope that I could explain my issue. If you have any questions please let me know.
I'm successfully mixing and matching Obj-C and Swift in an Xcode 7 project. However, I can't seem to figure out how, in an Objective C class, to inherit from a Swift class (and yes I know about declaring that Swift class as #objc for visibility). In this case the desired Swift superclass MySwiftViewController is a subclass of UIViewController. For now, in Obj-C, I'm inheriting directly from UIViewController and not gaining access to the capabilities I added in MySwiftViewController.
Here's what i understand:
-- To declare an Obj-C class as inheriting from something, that must be in the .h file after the ':':
#import <UIKit/UIKit.h>
#interface RootViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#end
-- To make Swift classes visible, that is #imported:
#import "MyProject-Swift.h"
However, you cannot import the Swift auto-generated bridging header into the Obj-C .h file. You also cannot forward-declare an opaque superclass with #class. So, is this possible and how?
Unfortunately, it's not possible to subclass a Swift class in Objective-C. Straight from the docs:
You cannot subclass a Swift class in Objective-C.
See Apple's guide on interoperability for more details on what you can and cannot access with Objective-C.
As for Xcode 8.0 and earlier there is dirty-hacky solution, that probably will be fixed in the future.
If you want to subclass from swift file, you can add objc_subclassing_restricted attribute. You can make it as macro for convenience.
Code:
Swift class.
import Foundation
class SwiftClass : NSObject {
func say() {
print("hi");
}
}
Objc class:
#import <Foundation/Foundation.h>
#import "test-Swift.h"
#define SWIFT_SUBCLASS __attribute__((objc_subclassing_restricted))
SWIFT_SUBCLASS
#interface ObjcClass : SwiftClass
- (instancetype)init;
#end
#implementation ObjcClass
- (void)say {
NSLog(#"oops");
}
#end
But, as I understand, it is not supported, and you may have any sort of bugs because of it. So it is not guide to action, and more like curious thing to know.
In fact, it can be achieved by category:
Swift code
import UIKit
#objc open class TestModel: NSObject {
#objc var testName: String = String()
}
Objective C .h file code
#import <Foundation/Foundation.h>
#import "Test-Swift.h"
#interface TestModel (Add)
- (void)configTestName;
#end
Objective C .m file code
#import "TestModel+Add.h"
#implementation TestModel (Add)
- (void)configTestName {
self.testName = #"12323";
}
#end
I m trying to passing values from second class to first class for that I am using protocol and delegate process. Whenever I run my program I am facing below Issue.
No Type or Protocol Named 'locateMeDelegate'
Viewcontroller A .h
#interface first : UIViewController < locateMeDelegate > { }
In my case the issue was caused by importing the delegate's header file to the delegator's class .h file. This seems to create a sort of vicious circle. As soon as I deleted the import statement of the delegate's header from the delegator's .h file, the error went away.
Tipically, if you intend your protocol to be used by other classes you must declare it in the header file like this:
// MyClass.h
#protocol MyProtocol;
#interface MyClass : NSObject
#end
#protocol MyProtocol
- (void) doSomething: (MyClass*) m;
#end
After you declare it, you should implement the methods of the protocol in the implementation file, which should conform to the protocol like this:
// MyClass.m
#implementation MyClass <MyProtocol>
pragma mark - MyProtocol methods
- (void) doSomething: (MyClass *)m {
// method body
}
#end
After these two steps you're ready to use you protocol in any class you desire. For example, let's say we want to pass data to MyClass from other class (e.g. OtherClass.h). You should declare in OtherClass.h a property so that we can refer to MyClass and execute the protocol. Something like this:
// OtherClass.h
#import MyClass.h
#interface OtherClass : NSObject
#property (weak) id<MyProtocol> delegate;
#end
You don't forget to import the header file where you declared your protocol, otherwise Xcode will prompt No Type or protocol named "MyProtocol"
id<MyProtocol> delegate; means you can set as the delegate of OtherClass any object (id) that conforms to the MyProtocol protocol (<MyProtocol>)
Now you can create an OtherClass object from MyClass and set its delegate property to self. Like this:
// MyClass.m
- (void)viewDidLoad() {
OtherClass *otherClass = [[OtherClass alloc] init];
otherClass.delegate = self;
}
It's possible to set the delegate to self because the delegate can be any object and MyClass conforms to MyProtocol.
I hope this can help. If you want to know more about protocols you can refer to this two websites:
Working with Protocols - Apple Documentation
Ry's Objective-C Tutorial (This one is easy to pick up)
I also faced the same issue and it seems the error is from Xcode itself. Please Try running on Physical device. This would solve the issue faced.
I'm writing some Swift classes that build upon functionality in our objective-c app. I have a objective-c class with a delegate that conforms to a protocol. I'm trying to call a method on that delegate from inside of a Swift class I'm simplified it down to this.
FredTestProtocol.h:
#protocol FredTestProtocol
- (void) dumbMethod;
#end
FredTestClass.h:
#import <Foundation/Foundation.h>
#import "FredTestProtocol.h"
#interface FredTestClass : NSObject <FredTestProtocol>
#property (nonatomic, weak) NSObject <FredTestProtocol> *delegate;
#end
FredTestClass.m:
#import "FredTestClass.h"
#implementation FredTestClass
- (void) dumbMethod
{
NSLog(#"Boy, this is a dumb method");
}
#end
FredSwiftClass.swift
import Foundation
class FredSwiftClass {
func test()
{
let ocObject = FredTestClass()
ocObject.delegate.dumbMethod() // Error occurs here.
}
}
The indicated line produces the error "'NSObject' does not have a method named 'dumbMethod'" I've tried a lot of ways to eliminate the error, to no avail. I'm sure I'm missing something really fundamental. Can someone tell me how I should go about calling the delegate method from Swift?
When Swift examines the property delegate it simply sees that is is an NSObject and the fact that you have noted that it implements a protocol is ignored. I can't find any specific documentation as to why this is the case.
You can address this in a couple of ways.
First, you can redefine your delegate property to use class anonymity, then Swift will just see it as some object that implements the protocol -
FredTestClass.h
#import <Foundation/Foundation.h>
#import "FredTestProtocol.h"
#interface FredTestClass : NSObject <FredTestProtocol>
#property id<FredTestProtocol> delegate;
#end
Then your Swift code will compile as written.
or you can leave your delegate definition as is and tell Swift that you want to access the delegate as an instance of an object that implements the protocol via downcast -
FredTestSwift.swift
import Foundation
class FredSwiftClass {
func test()
{
let ocObject = FredTestClass()
let theDelegate=ocObject.delegate as! FredTestProtocol
theDelegate.dumbMethod()
}
}
Pretty sure I've got it.
func test()
{
let ocObject = FredTestClass()
if let myDelegate = ocObject.delegate as? FredTestProtocol
{
myDelegate.dumbMethod()
}
}
i want to know if the following situation can be done. I have inherited a project of iOS 8. I'd like to add a method to NSObject so that all objects can see it. and I have done this already. Here is the category implementation i have created:
#import "NSObject+myCategory.h"
#implementation NSObject (myCategory)
-(void)localizeStringIncludeDefault{
NSLog(#"about to localize String");
}
#end
Now i go to a MyViewController.m for example and try to call the method but its not working its not seen:
heres the .h:
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
BOOL someFakeBoolean;
IBOutlet UIView *someView;
//etc
}
#property (nonatomic,assign) IBOutlet MyViewController *myViewController;
-(void)localizeStringIncludeDefault;
and here is the implementation *.m and my issue:
#implementation MyViewController
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self localizeStringIncludeDefault] //this call cant be done, the method is not visible
}
- (void) viewDidDisappear:(BOOL)animated
{
//etc
}
//etc
I mean it makes sense to me that i'd have to import the "NSObject+myCategory.h" into the MyViewController header to use the category but because i've inherited this code it already has a base. I dont want to go into every .h file and import this. Is a easy way to extend object so that EVERY object class sees my method ?
One option would be to add the category .h file to the pch file. Then it will be seen by every class in your project without the need to import it explicitly.
Declare your global variables or declarations in your pch file or rather make a Global.h and just import this in your pch file (helps a lot in reusability). You can declare extern items as well in your Global.h and populate in App Delegate