Call Objective C custom init function from Swift - ios

Class A is writen in Objective C and have a custom init fucntion
#interface A ()
....
#end
#implementation A
- (id)customInitImplementedInA
{
...
return self;
}
Class B inherits from Class A and uses this custom init in the following way:
#interface B : A ()
....
#end
#implementation B
+(instancetype)instanceB{
B *b = [[B alloc] customInitImplementedInA];
...
return b;
}
Now I would like to create class C writen in Swift that inharits from A and uses the same init function. How do I do that?
class C: A {
//How do I use customInitImplementedInA here?
}

You should be able to do this via super.methodname syntax.
class C: A {
init() {
super.customInitImplementedInA()
// Any extra initialization for C goes here.
}
}

If you inherit your swift class from Obj-C than your swift clas will have obj-c init().
if you need to call it you can include it to your swift init.
class C: A {
var message: B?
init(message: B) {
super.customInitImplementedInA()
self.message = message
}
}

Related

How to pass an Objective-C with callback to a Swift method?

I really don't know how to ask this question, but:
I have a bridge between Objective-C and Swift
In my Obj-C class I invoke my Swift class
IAPbridge = [[IAPBridge alloc] init];
[IAPbridge requestProducts];
I have a swift class
public func requestProducts () {
}
My Obj-C class should have a block to receive some data from the Swift class
It should be something like this (this code is wrong, but something like what I think it should be)
Obj-C
[IAPbridge requestProducts:^(id *products) {
NSLog(#"Response:%#", products);
}];
Swift
public typealias ProductsRequestCompletionHandler = (_ products: [SKProduct]?) -> Void
private var productsRequestCompletionHandler: ProductsRequestCompletionHandler?
public func requestProducts (completionHandler) {
productsRequestCompletionHandler = completionHandler
productsRequestCompletionHandler?(true, products)
}
So, any help?
This part is impossible as your spec stands:
productsRequestCompletionHandler?(true, products)
You cannot hand back two values if a ProductsRequestCompletionHandler takes only one value. So you will have to revise your definition of a ProductsRequestCompletionHandler.
We may then imagine that on the Swift side we have a class like this:
#objc class IAPBridge : NSObject {
public typealias ProductsRequestCompletionHandler = (Bool, [SKProduct]?) -> Void
#objc func requestProducts(_ ch:ProductsRequestCompletionHandler) {
let products : [SKProduct]? = // whatever
ch(true, products)
}
}
Over on the Objective-C side, your class's .m file must import the implicitly generated bridging header:
#import "MyApp-Swift.h" // or whatever it is called
In the eyes of your Objective-C class, an IAPBridge has this method:
- (void)requestProducts:(SWIFT_NOESCAPE void (^ _Nonnull)(BOOL, NSArray<SKProduct *> * _Nullable))ch;
So now you just call it:
IAPBridge* b = [[IAPBridge alloc] init];
[b requestProducts:^(BOOL success, NSArray<SKProduct *> * products) {
if (success) {
NSLog(#"Thank you for the products! They are %#", products);
} else {
NSLog(#"%#", #"Darn, something went wrong");
}
}];

Static variables in protocols

I have a protocol A which has a static variabe x. B is a implementation of A. In Class C I pass an instance of B and assigned it to a. How can I access 2 (value of x in class B) from it ?
protocol A {
static var x : Int { get }
}
class B : A {
static var x: Int {
return 2
}
}
class C {
// instance of B is assigned to a.
let a: A
print(a.x)
}
A static variable belongs to the class, not the instance. You can refer to the class by calling dynamicType:
print(a.dynamicType.x)
So things have changed a little bit since this answer was posted
type(of: a).x
Within class C a is a property that holds an instance of a type adhering to protocol A. A static variable (otherwise known as a class variable) however is not accessible from an instance, it is accessible from the class, so you will access the value in the following way:
B.x
An instance variable would be a different matter and the code for this would be:
protocol A {
var x : Int { get }
}
class B : A {
var x: Int {
return 2
}
}
class C {
// instance of B is assigned to a.
let a: A
init() {
a = B()
}
}
C().a.x
These can happily co-exist with the same variable names:
protocol A {
static var x : Int { get }
var x : Int { get }
}
class B : A {
static var x: Int {
return 2
}
var x: Int {
return 2
}
}
class C {
// instance of B is assigned to a.
let a: A
init() {
a = B()
}
}
C().a.x
B.x

public private and protected in objective-c

Hi I am trying to learn Opps concept in Objective C but I know PHP so I took a program in which for public, private and protected mentioned bellow.
<?php
//Public properties and method can be inherited and can be accessed outside the class.
//private properties and method can not be inherited and can not be accessed outside the class.
//protected properties and method can be inherited but can not be accessed outside the class.
class one
{
var $a=20;
private $b=30;
protected $c=40;
}
class two extends one
{
function disp()
{
print $this->c;
echo "<br>";
}
}
$obj2=new two;
$obj2->disp(); //Inheritance
echo"<br>";
$obj1=new one;
print $obj1->c; //Outside the class
?>
So this I am trying to convert in Objective c code mentioned bellow.
#import <Foundation/Foundation.h>
#interface one : NSObject
{
#private int a;
#public int b;
#protected int c;
}
#property int a;
#property int b;
#property int c;
#end
#implementation one
#synthesize a,b,c;
int a=10;
int b=20;
int c=30;
#end
#interface two : one
-(void)setlocation;
#end
#implementation two
-(void)setlocation;
{
// NSLog(#"%d",a);
NSLog(#"%d",b);
// NSLog(#"%d",c);
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
two *newtwo;
newtwo =[[two alloc]init];
//calling function
[newtwo setlocation];
}
return 0;
}
When I run the above code I am getting
2015-11-03 23:20:16.877 Access Specifier[3562:303] 0
Can some one resolve my problem.
This type of question has been asked before and there's a good explanation in the accepted answer for Private ivar in #interface or #implementation
In general I would recommend you avoid instance variables and use #property instead. Properties have the benefit of read-only/write controls, and free synthesized setters and getters (which if you're learning OOP concepts is a critical concept you should employ).
Properties are declared in the #interface part of an Obj-C file. For access control (according to the link) you have no public/private/protected keywords. All Obj-C methods (and by extension, properties) are public if they're defined in the .h file. If you want them "private" you define them in the the .m file using a class category:
//MyClass.m
#interface MyClass ()
#property(nonatomic, retain) NSString* myString;
#end
#implementation MyClass
#end

convert struct to objective c array or class

I m new for IOS. I have some source code for OS X and java. I was trying to convert to IOS.
In OS X, I have the following.
struct _NoteData {
int number; /** The Midi note number, used to determine the color */
WhiteNote *whitenote; /** The white note location to draw */
NoteDuration duration; /** The duration of the note */
BOOL leftside; /** Whether to draw note to the left or right of the stem */
int accid; /** Used to create the AccidSymbols for the chord */
};
typedef struct _NoteData NoteData;
#interface ChordSymbol : NSObject <MusicSymbol> {
_NoteData notedata[20];/** The notes to draw */
}
_NoteData is like an array and class here. number, whitenote,duration..are instance variable for _noteData.
I was trying to change struct to objective c class:
#interface _NoteData:NSObject{
#property NSInteger number_color;
#property WhiteNote *whitenote;
#property NoteDuration duration;
#property BOOL leftside;
#property NSInteger accid;
};
#interface ChordSymbol : NSObject <MusicSymbol> {
_NoteData notedata[20];/** The notes to draw */
}
In my .m file, it has
+(BOOL)notesOverlap:(_NoteData*)notedata withStart:(int)start andEnd:(int)end {
for (int i = start; i < end; i++) {
if (!notedata[i].leftside) {
return YES;
}
}
return NO;
}
!notedata[i] throw error expected method to read array element. I understand _NoteData is a class, not an array. What should I change?
In java:
private NoteData[] notedata;
NoteData is a class, and notedata is an array which store NoteData.
Same method in java
private static boolean NotesOverlap(NoteData[] notedata, int start, int end) {
for (int i = start; i < end; i++) {
if (!notedata[i].leftside) {
return true;
}
}
return false;
}
I feel all I need is to declare an array with _NoteData object. How can I do that?
Objective-C is a superset of C, so you can use C struct in Objective-C code. You can keep your code in the first paragraph. You need to move the function declaration in ChordSymbol class's header file.
+(BOOL)notesOverlap:(NoteData*)notedata withStart:(int)start andEnd:(int)end;
In another Objective-C class's implementation file, call the Class function like this.
NoteData y[] = {
{ .leftside = YES },
{ .leftside = YES },
{ .leftside = YES },
{ .leftside = YES }
};
BOOL result = [ChordSymbol notesOverlap:y withStart:0 andEnd:3];
NSLog(#"%d",result);
Edit
You can use NSArray for this purpose. You create an array and populate its data with NoteData objects.
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:20];
NoteData *data1 = [[NoteData alloc] init];
data1.number_color = 1;
[array addObject:data1];
Then you should change (_NoteData*)notedata to (NSArray*)array, and it should work.

override setter with call to inherited setter

I am a little bit confused: can I override a setter / getter but still use the super setter/getter? If yes - how?
Use case:
class A {
void set value(num a) {
// do something smart here
}
}
class B extends A {
void set value(num a) {
// call parent setter and then do something even smarter
}
}
If this is not possible how can one still preserve the API but expand the logic in the new class. The users of the code already use instance.value = ... so I do not want to change it to method call is possible.
Please help:)
You can access to parent with super. :
class B extends A {
void set value(num a) {
super.value = a;
}
}
Only need call super.value = a
class A {
void set value(String value) {
print(value.toUpperCase());
}
}
class B extends A {
void set value(String value) {
super.value = value;
print(value.toLowerCase());
}
}
void main() {
B b = new B();
b.value = "Hello World";
}

Resources