1

I made a project with Swift code which was included with CollectionView and a swift class, now I made a collectionview in obj-c and I would like to use a class from my old swift project, how is it possible to combine that swift file(class) with my current obj-c file? In my swift class I also used delegates so kinda found it hard to combine these two :).

Here's my code - CollectionView in obj-c:

#import "ViewController.h"
#import "CollectionViewTest-Swift.h"


@interface ViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>


@property NSArray *image_Arr;
@property NSArray *label_Arr;


@end

@implementation ViewController
{
    ImpressionStalker *impressionEventStalker;
}



@synthesize Collection_view;


- (void)viewDidLoad {
    [super viewDidLoad];
    
//    collectionView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
//    impressionEventStalker = ImpressionStalker(minimumPercentageOfCell: 0.70, collectionView: collectionView, delegate: self)

    
    
    _image_Arr = [ [NSArray alloc] initWithObjects:@"image_1",@"image_2",@"image_3",@"image_4",@"image_5", nil];
    _label_Arr = [ [NSArray alloc] initWithObjects:@"0 Comments",@"2 Comments",@"4 Comments",@"0 Comments",@"5 Comments", nil];

    
    
    impressionEventStalker = [[ImpressionStalker alloc]initWithMinimumPercentageOfCell:0.70 collectionView:self.Collection_view delegate: self];
    
    
}


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return _image_Arr.count;
}


// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL_ID" forIndexPath:indexPath];
    
    UIImageView *Image_View = (UIImageView *) [cell viewWithTag:100];
    
    UILabel *Label = (UILabel *) [cell viewWithTag:101];
    
    Image_View.image = [UIImage imageNamed:[_image_Arr objectAtIndex:indexPath.row]];
    
    Label.text = [_label_Arr objectAtIndex:indexPath.row];
    
    return cell;
}


- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}


@end

my Swift File/Class:

import Foundation
import UIKit

@objc
protocol ImpressionStalkerDelegate:NSObjectProtocol {
    func sendEventForCell(atIndexPath indexPath:IndexPath)
}

protocol ImpressionItem {
    func getUniqueId()->String
}


@objc
class ImpressionStalker: NSObject {
    
    //MARK: Variables & Constants
    let minimumPercentageOfCell: CGFloat
    weak var collectionView: UICollectionView?
    
    static var alreadySentIdentifiers = [String]()
    weak var delegate: ImpressionStalkerDelegate?
    
    
    
    
    //MARK: Initializer
    @objc
    init(minimumPercentageOfCell: CGFloat, collectionView: UICollectionView, delegate:ImpressionStalkerDelegate ) {
            self.minimumPercentageOfCell = minimumPercentageOfCell
            self.collectionView = collectionView
            self.delegate = delegate
        }
    
    
    
    // Checks which cell is visible:
    @objc
    func stalkCells() {
        for cell in collectionView!.visibleCells {
            if let visibleCell = cell as? UICollectionViewCell & ImpressionItem {
                let visiblePercentOfCell = percentOfVisiblePart(ofCell: visibleCell, inCollectionView: collectionView!)
                
                if visiblePercentOfCell >= minimumPercentageOfCell,  !ImpressionStalker.alreadySentIdentifiers.contains(visibleCell.getUniqueId()){ // >0.70 and not seen yet then...
                    guard let indexPath = collectionView!.indexPath(for: visibleCell), let delegate = delegate else {
                        continue
                    }
                    print(indexPath)
                    delegate.sendEventForCell(atIndexPath: indexPath) // send the cell's index since its visible.
                    ImpressionStalker.alreadySentIdentifiers.append(visibleCell.getUniqueId()) // to avoid double events to show up.
                }
            }
        }
    }
    
    
    
    // Func Which Calculate the % Of Visible of each Cell:
    @objc
    private func percentOfVisiblePart(ofCell cell:UICollectionViewCell, inCollectionView collectionView:UICollectionView) -> CGFloat{
           
           guard let indexPathForCell = collectionView.indexPath(for: cell),
               let layoutAttributes = collectionView.layoutAttributesForItem(at: indexPathForCell) else {
                   return CGFloat.leastNonzeroMagnitude
           }
           
           let cellFrameInSuper = collectionView.convert(layoutAttributes.frame, to: collectionView.superview)
           
           let interSectionRect = cellFrameInSuper.intersection(collectionView.frame)
           let percentOfIntersection: CGFloat = interSectionRect.height/cellFrameInSuper.height
           
           return percentOfIntersection
       }
    
}

1 Answer 1

2

As a Objective-C file isn't in context for Swift and requires to import every new file *.h or *.m, you've to import *-Swift.h in your Objective-C file to import Swift classes.

As Apple says:

You don't need to do anything special to create the generated header — Just import it to use its contents in your Objective-C code

https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c

Swift files and Objective-C files in same project

  • If your project name is MyBeautifulApp, so you're going to import
#import MyBeautifulApp-Swift.h

to use Swift classes from there.

Swift files in different project from Objective-C project

But if your Swift file is a framework instead of target, you must use

#import <MyBeautifulApp/MyBeautifulApp-Swift.h>

after doing that:

  • Import Swift code into Objective-C within the same framework: Under Build Settings, in Packaging, make sure the Defines Module setting for that framework target is set to Yes

Let me know if I helped you please.

Sign up to request clarification or add additional context in comments.

6 Comments

first of all thanks for the answer :) it made me to understand more about swift with objc, but also my problem is that Idk how for example to use my delegate method in my swift's class in my objc code :(
I'm sorry! So let me see if I got it: you must implement sendEventForCell(atIndexPath:) in Objective-C class alright? Have you tried @objc up that function name? @objc func sendEventForCell(atIndexPath indexPath: IndexPath)
Yes I added objc to every method lol, Its just im trying to understand how to implement that delegate method into my objc file, kinda new to objc :)
Have you added @objc as in protocol scope as in function name? It has to be added both.
ye :\ I will try to find out how it works :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.