Using SPUserResizableView in Swift - ios

I'm trying to use the SPUserResizableView created by Spoletto in github (https://github.com/spoletto/SPUserResizableView).
I imported the .h and .m files, created a bridge and added the delegates to my controller.
I think problem is that problem is that the library is very old and that's why I get many errors in the .h and .m files so I can't use the library.
Errors - http://postimg.org/gallery/3bq2ldo0m/
Can you help me setup the library in swift?

I also got the same error, Just add these two in SPUserResizableView.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
Your problem will be resolved.

You need to set up an Objective-C bridging header and then import it in there. To do this:
Drag and drop the .h and .m SPUserResizableView files into your project.
When Xcode asks if you want to create a bridging header, select 'Yes'.
Type in the new file called 'YOUR-PROJECT-NAME-bridging-header.h' this code:
#import SPUserResizableView.h
You should now be able to use it in Swift!

I got this working with Swift 4 by moving the variable declarations from the interface to the implementation, and removing the release and dealloc code.
SPUserResizableView.h changed to
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
typedef struct SPUserResizableViewAnchorPoint {
CGFloat adjustsX;
CGFloat adjustsY;
CGFloat adjustsH;
CGFloat adjustsW;
} SPUserResizableViewAnchorPoint;
#protocol SPUserResizableViewDelegate;
#class SPGripViewBorderView;
#interface SPUserResizableView : UIView {
}
//...
//(identical from this point on)
SPUserResizableView.m changed to
//...
//(identical up to)
//CGColorSpaceRelease(baseSpace), baseSpace = NULL;
CGColorSpaceRelease(baseSpace);
baseSpace = NULL;
#implementation SPUserResizableView
SPGripViewBorderView *borderView;
UIView *contentView;
CGPoint touchStart;
CGFloat minWidth;
CGFloat minHeight;
// Used to determine which components of the bounds we'll be modifying, based upon where the user's touch started.
SPUserResizableViewAnchorPoint anchorPoint;
id <SPUserResizableViewDelegate> delegate;
//#synthesize contentView, minWidth, minHeight, preventsPositionOutsideSuperview, delegate;
//...
//(this part identical)
- (void)dealloc {
[contentView removeFromSuperview];
}
#end

Related

ObjC app build gets build error for call to swift function within ObjC static library

Trying to get ObjC app project to call Swift function within ObjC static lib..........
My ObjC app project build gets build error for reference to a Swift function that is within an ObjC static lib (.a) that is imported into the app project.
The file Hub_lib-Bridging-Header.h has no code.
OBJ-C APP PROJECT..............................................
ViewController.mm within the ObjC app project...
#import "ViewController.h"
#import "Hub_lib.h"
#import "Hub_lib-Swift.h"
#import "hublib.hpp"
#interface ViewController ()
#end
#implementation ViewController
. . .
- (IBAction)run_simple_central:(id)sender {
[self BLE.start_central];
}
BLE.h within ObjC app project...........
#import <CoreBluetooth/CoreBluetooth.h>
#import "Hub_lib-Swift.h"
#interface BLE: NSObject
//< CBPeripheralManagerDelegate >
#property(strong, nonatomic) CBPeripheralManager* peripheralManager;
#property(strong, nonatomic) CBMutableCharacteristic* transferCharacteristic;
#property(strong, nonatomic) NSData* dataToSend;
#property(nonatomic, readwrite) NSInteger sendDataIndex;
-(void)start_central;
#end /* BLE_h */
BLE.m within app; a wrapper for call to swift..........................
#import "BLE.h"
#import "Hub_lib-Swift.h"
#interface BLE ()
#end
#implementation BLE
-(void)start_central
{
Hub_lib* BLE_central = [Hub_lib new];
[BLE_central centralManager.run_central];
}
made a test project to be able to replicate your errors.
You are close but you need to take care of how your static lib has its internal methods and classes exposed in its header so you can use them elsewhere.
let's begin with the Objective-C Static Library project. Hub_lib.h
#import <Foundation/Foundation.h>
// we want the lib header as clean as possible
// it will then be imported in your project with '#import <Hub_lib/Hub_lib.h>'
// auto-generated swift -> objc bridging header imported here will
// mess it up when imported somewhere else.
// so when using swift->objc bridging place next line in .m file instead
//#import "Hub_lib-Swift.h"
//#class BLE_Central; // pre-declaration of a later fully declared Class.
// as we moved the property into .m file we dont need it here.
#interface Hub_lib : NSObject
// to make this work you would need pre-declaration of BLE_Central, see above interface
//#property BLE_Central *ble; // placed in .m interface extension instead.
-(void)run_central;
#end
static lib counterpart / implementation Hub_lib.m
#import "Hub_lib.h"
#import "Hub_lib-Swift.h"
#interface Hub_lib ()
#property BLE_Central *ble_central;
#end;
#implementation Hub_lib
-(instancetype)init {
if (!(self=[super init])) return nil;
_ble_central = [[BLE_Central alloc] init];
return self;
}
-(void)run_central {
[_ble_central run_central];
}
#end
notice BLE_Central property is placed in the class interface extension and when you want to use swift module stuff that exposes back to objc you need to declare the auto-generated bridge somewhere (best done in .m file #import "Hub_lib-Swift.h")
your BLE_central.swift with its protocol method implementation
import Foundation
import UIKit
import CoreBluetooth
import os
var centralManager: CBCentralManager = CBCentralManager()
class BLE_Central: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
os_log("centralManagerDidUpdateState")
}
var discoveredPeripheral: CBPeripheral?
var transferCharacteristic: CBCharacteristic?
var writeIterationsComplete = 0
var connectionIterationsComplete = 0
let defaultIterations = 5 // change this value based on test usecase
var data = Data()
// as you figured out before we need to expose to #objc
#objc public func run_central()
{
os_log("run_central")
// out-commented for testing purposes
//mobile_sys_hub_lib.centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: true])
os_log("Scanning started")
}
}
As long no extra code from objc is used in swift inside the static lib, the
Hub_lib-Bridging-Header.h is empty
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
Next let's see how to import your static lib in your "sim backend UI" Objective-C Project app.
Goto "sim backend UI" App Target settings > General > Framework, Libraries, and.. > hit the + button and search for your compiled libHub_lib.a file. > select it > hit ok. Should be very much in your framework list by now.
Yes, thats not enough! You have to declare its header in your app project somewhere. Where exactly is up to you. Instead of implementing it multiple times we do the following in BLE.h
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
//#import "Hub_lib-Swift.h" // no no no no
#import <Hub_lib/Hub_lib.h> // much better. test-compile once if it is crying
NS_ASSUME_NONNULL_BEGIN
#interface BLE: NSObject
// <CBPeripheralManagerDelegate> // "//<Protocol>" will confuse doxygen
#property (strong, nonatomic) CBPeripheralManager* peripheralManager;
#property (strong, nonatomic) CBMutableCharacteristic* transferCharacteristic;
#property (strong, nonatomic) NSData* dataToSend;
#property (nonatomic, readwrite) NSInteger sendDataIndex;
-(void)start_central;
#end /* BLE_h */
NS_ASSUME_NONNULL_END
counterpart BLE.m
#import "BLE.h"
#implementation BLE
-(void)start_central
{
NSLog(#"invoked BLE start_central");
Hub_lib *Hub_central = [Hub_lib new];
[Hub_central run_central];
}
#end
Your ViewController.m or .mm makes use of BLE.h with its already imported static lib header
#import "ViewController.h"
#import "BLE.h"
#interface ViewController ()
#property (nonatomic) BLE *ble;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(100, 100, 200, 50);
[btn setTitle:#"run simple central" forState:(UIControlStateNormal)];
[btn setTitleColor:UIColor.greenColor forState:(UIControlStateNormal)];
btn.layer.backgroundColor = UIColor.orangeColor.CGColor;
btn.layer.cornerRadius = 5.0f;
[self.view addSubview:btn];
[btn addTarget:self action:#selector(run_simple_central:) forControlEvents:(UIControlEventTouchUpInside)];
}
- (IBAction)run_simple_central:(id)sender {
// BLE needs to be allocated to take effect.
if (!_ble) _ble = [[BLE alloc] init];
// testing.. should log "run_central" + "Scanning started"
[self.ble start_central];
}
#end
Made a testButton so you can see if the implementation invokes what you expect. Compile!
And? Aoutsch! Does not work. What happened?
If your App is a plain Objective-C project it doesn't know about swift yet and will complain in a weirdo way, possibly via something like
Link: Could not find or use auto-linked library 'swiftCoreImage'
Undefined symbol: value witness table for Builtin.UnknownObject*
Solution: Most easy way is to create a swift file in your app project and allow Xcode to make a bridging header for you. (Alternatively change project settings, search for "bridge" and go step by step thru the properties)
The swift file does not have to have special content.
//
// MakeProjectSwiftCompatible.swift
//
import Foundation
Compile again. now it should work because the partly implemented swift module from within your static lib can properly work when your Objc-App-Project is able to work with swift stuff.
Edit as you asked to work with Objective-C++/C++ in your static library things change a little bit.. so here some additional example code to proof it.
In Hub_lib project (targeting your "framework") add some files which will keep some random testing c++ code
//HubCPP.h
#import <Foundation/Foundation.h>
#include <vector>
NS_ASSUME_NONNULL_BEGIN
class SomeCPPClass
{
public:
SomeCPPClass(id<NSObject> obj, size_t size);
~SomeCPPClass();
id<NSObject> getBuffer() { return buffers[bufferIdx]; }
unsigned int getCurrentIdx();
private:
std::vector <id <NSObject>> buffers;
unsigned int bufferIdx;
bool isReady;
};
NS_ASSUME_NONNULL_END
To make Xcode know that you work with C++ you need to have implementation file ending with .mm and also need to change HubCpp.h "Identity and Type (right Xcode panel while file selected)" to C++ Header
// HubCpp.mm
#import "HubCPP.h"
SomeCPPClass::SomeCPPClass (id<NSObject> obj, size_t size) :
bufferIdx (0),
isReady(false)
{
uint8_t ringSize = 255;
assert (ringSize > 0);
for (uint8_t i = 0; i < ringSize; i++)
{
//buffers.push_back ();
bufferIdx = (unsigned int)size;
}
}
SomeCPPClass::~SomeCPPClass() {
// cleanup allocated stuff here.
}
unsigned int SomeCPPClass::getCurrentIdx() {
return bufferIdx;
}
Rename Hub_lib.m to .mm and change its import rules accordingly to the following ..
#import "Hub_lib.h"
#import <CoreBluetooth/CoreBluetooth.h> //needed because the -Swift.h bridge will cry in the next line
#import "Hub_lib-Swift.h"
#import "HubCPP.h"
lets change the proofing method in Hub_lib.mm so it really uses C++
-(void)run_central {
[_ble_central run_central];
SomeCPPClass *cpp = new SomeCPPClass(#"justSomeNSStringObject",2);
unsigned int idx = cpp->getCurrentIdx();
NSLog(#"objectiveCplusplus testIdx = %u", idx);
}
Compile Hub_lib (scheme). It should work by now and also accept the use of #import <vector>.
If this works go on and change your Objc-Project-App.
Switch your compile Scheme to target your Objc-App.
Change file name BLE.m to BLE.mm (makes it a Objective C++ Source)
Change file name BLE.h to BLE.hh (makes it a C++ header)
Change in BLE.mm #import "BLE.h to #import "BLE.hh
in ViewController.m kick out the line #import "BLE.h" and replace it into ViewController.h instead as #import "BLE.hh"
(In general its much easier to keep your compiler informed what language to expect in implementation when you place import headers in header files.)
Compile. Thats it! Your Objective-C++ static lib should properly work at this point.
Edit
You can find a ready made workspace for Xcode here...github: combine cpp swift and objective-c in static lib
Solution from StackO user: Asperi
Emptied top folder
Created workspace at top folder
1.1 Copied clean app and lib to top folder
Add ObjC lib .xcodeproj to workspace using Xcode > File > Add files ...
Add ObjC app .xcodeproj to workspace
Added dependency of sim_backend_UI to lib via workspace
a. app proj > General tab > Frameworks, Libs.. > +
b. Select lib .a
c. Add.
Add Some.swift (any swift file you want) to sim_backend_UI, just for the purpose Xcode add required system swift dynamic libraries (which will be needed for swift part in static library as well)... and confirm creating bridge in appeared dialog
a. new file > Swift > Some.swift
b. Create Bridging Header
c. Added to Some.swift ...
import Foundation
struct Some{}
Set Xcode active scheme to app and target device
Build
"succeeded"

Using Objective-c classes in Swift Classes

I have forced to use some classes of objective-c language in swift recently, I have searched and found this Apple doc:
To import Objective-C code into Swift from the same target
1) In your Objective-C bridging header file, import every Objective-C
header you want to expose to Swift. For example:
#import "XYZCustomCell.h"
#import "XYZCustomView.h"
#import "XYZCustomViewController.h"
2) In Build Settings, in Swift Compiler - Code Generation, make sure the Objective-C Bridging Header
build setting under has a path to the bridging header file. The path
should be relative to your project, similar to the way your Info.plist
path is specified in Build Settings. In most cases, you should not
need to modify this setting.
Any public Objective-C headers listed in
this bridging header file will be visible to Swift. The Objective-C
functionality will be available in any Swift file within that target
automatically, without any import statements. Use your custom
Objective-C code with the same Swift syntax you use with system
classes.
I followed steps and added initial code to my swift class:
let percentageView: FSPercentageView = FSPercentageView(frame: CGRectMake(15, 65, 300, 300))
But I got an error with message: Used of undeclared type 'FSPercentageView'.
I have searched this error related using objective-c in swift but I did not find any useful answer.
I checked the bridge header file path and It seems to be fine.
I hope your suggestion fix my problem.
UPDATE:
My Bridging-Header.h
#import "FSPercentageView.h"
My Class of FSPercentageView.h :
#import <Foundation/Foundation.h>
#import "MCCore.h"
#class FCPercentageView;
typedef enum {
FSPercentageViewTextStyleAutomaticShowsPercentage,
FSPercentageViewTextStyleUserDefined
} FSPercentageViewTextStyle;
#interface FSPercentageView : MCNewCustomLayeredView
/*
Sets the percentage of the view.
*/
#property (nonatomic) CGFloat percentage;
/*
Sets the percentage of the view.
*/
#property (nonatomic) CGFloat initialPercentage;
/*
Defines the border percentage for both filled and unfilled portions.
*/
#property (nonatomic) CGFloat borderPercentage;
/*
The label of the text in the center of the doughnut.
*/
#property (nonatomic, retain) UILabel *textLabel;
/*
The color for the filled portion of the doughnut.
*/
#property (nonatomic, retain) UIColor *fillColor;
/*
The color for the unfilled portion of the doughnut.
*/
#property (nonatomic, retain) UIColor *unfillColor;
}
and the initial segment of FSPercentageView.m:
#import "FSPercentageView.h"
#import "FSNewCustomLayeredView+FSCustomLayeredViewSubclass.h"
typedef enum {
FSPercentageViewStateNormal,
FSPercentageViewStatePushed
} FSPercentageViewTouchState;
#interface FSPercentageView()
#property (nonatomic, retain) UIView *centerView;
#property (nonatomic) FSPercentageViewTouchState touchState;
#end
#implementation FSPercentageView
- (void)setDefaults
{
[super setDefaults];
self.linePercentage = 0.15;
self.borderPercentage = 0;
self.showTextLabel = YES;
self.animationDuration = 0.5;
self.unfillColor = [MCUtil iOS7DefaultGrayColorForBackground];
self.borderColorForFilledArc = [UIColor blackColor];
self.borderColorForUnfilledArc = [UIColor clearColor];
self.borderPercentageForFilledArc = -1;
self.borderPercentageForUnfilledArc = -1;
self.adjustsFontSizeAutomatically = YES;
self.roundedImageOverlapPercentage = 0;
self.touchState = FSPercentageViewStateNormal;
self.gradientColor1 = [MCUtil iOS7DefaultBlueColor];
self.gradientColor2 = [MCUtil iOS7DefaultGrayColorForBackground];
_percentage = 0.0;
_initialPercentage = 0.0;
_centerView = [[UIView alloc] init];
_textLabel = [[UILabel alloc] init];
}
- (void)willDrawSublayers
{
if (!self.fillColor) {
self.fillColor = self.tintColor;
}
}
- (Class)classForSublayers {
return [MCSliceLayer class];
}
and the swift code:
let percentageView: FSPercentageView = FSPercentageView(frame: CGRectMake(15, 35, 289, 311))
Shows the error in above line.
I hope your suggestion fix my problem.
But you have not given any information, so no suggestion is possible. What Apple says is true; I assure you that this feature does work. The problem can only be that you have not followed the directions that you yourself have quoted.
I found the problem which my code has.
I have two targets in my app and also I am using Test Unit.
Because of adding my swift code in all mentioned targets, the project was needed to have 3 bridging class related to each target and also the headers must be imported in all of them. Actually the red message was about unit test bridging file.
Right now, I removed my swift class from Test Unit and The code is compiling and running without any problem.

Howto achieve animation like store house in ios?

Hi all i have got to implement storehouse like animation in my project. I found a third party library but sorry it is in swift. Please help me with objective c code
Refference link for animation is
Animation Store house
StoreTableView.h
#import <UIKit/UIKit.h>
#protocol StoreHouseTableViewTransform
#property (nonatomic) CGFloat scaleValue;
-(void)transFormForCell:(CGFloat)scaleFactor;
#end
#interface StoreTableView : UITableView
#end
StoreTableView.m
#import "StoreTableView.h"
#implementation StoreTableView
-(void)layoutSubviews{
[super layoutSubviews];
[self transformTable];
}
- (void )transformTable{
for (NSIndexPath *indexpath in self.indexPathsForVisibleRows) {
UITableViewCell *cell = [self cellForRowAtIndexPath:indexpath];
if ([cell conformsToProtocol:#protocol(StoreHouseTableViewTransform)]) {
UITableViewCell <StoreHouseTableViewTransform> *vc = (UITableViewCell<StoreHouseTableViewTransform> *)cell;
CGFloat distCenter=[self computeDistance:indexpath];
[vc transFormForCell:[self computeScale:distCenter withMinScale:vc.scaleValue]];
}
}
}
-(CGFloat )computeDistance:(NSIndexPath *)indexpath{
CGRect rect=[self rectForRowAtIndexPath:indexpath];
CGFloat cellCenter=rect.origin.y + rect.size.height/2;
CGFloat cellContentCenter=self.contentOffset.y + self.bounds.size.height/2;
return fabs(cellCenter - cellContentCenter);
}
-(CGFloat )computeScale:(CGFloat)distanceOfCenter withMinScale:(CGFloat)scaleFactor{
return (1.0-scaleFactor) * distanceOfCenter / self.bounds.size.height;
}
#end
StoreTableViewCell.h
#import <UIKit/UIKit.h>
#import "StoreTableView.h"
#interface StoreTableViewCell : UITableViewCell<StoreHouseTableViewTransform>{
CGFloat minimumScale;
}
#property (weak, nonatomic) IBOutlet UIView *backView;
#property (weak, nonatomic) IBOutlet UIImageView *scaleImage;
#end
StoreTableViewCell.m
#import "StoreTableViewCell.h"
#implementation StoreTableViewCell
#synthesize scaleValue;
-(void )prepareForReuse{
[super prepareForReuse ];
minimumScale = 0.85;
self.backView.transform = CGAffineTransformMakeScale(minimumScale, minimumScale);
}
#pragma mark delegate
-(void)transFormForCell:(CGFloat)scaleFactor{
self.backView.transform = CGAffineTransformMakeScale(1.0 - scaleFactor, 1.0 - scaleFactor);
}
#end
This is objective-C implementation of StoreHouse Animation
Subclass your TableView with StoreTableView and Cell with StoreTableViewCell.
I think so this will help you
play with scaleFactor
I spent about 4 hours trying to enable Swift in my Xcode Objc-based project. My "myproject-Swift.h" file was created successfully, but my Xcode didn't see my Swift-classes. So I decided to create a new Xcode Objc-based project and finally I found the right answer! Hope this post will help someone :-)
Step by step swift integration for Xcode Objc-based project:
1.Create new *.swift file (in Xcode) or add it by using Finder
2.Add swift bridging empty header if Xcode have not done this before (see 4 below)
3.Implement your Swift class by using #objc attribute:
import UIKit
#objc class Hello : NSObject {
func sayHello () {
println("Hi there!")
}
}
4.Open Build Settings and check this parameters:
Product Module Name : myproject
Defines Module : YES
Embedded Content Contains Swift : YES
Install Objective-C Compatibility Header : YES
Objective-C Bridging Header : $(SRCROOT)/Sources/SwiftBridging.h
5. Import header (which is auto generated by Xcode) in your *.m file
#import "myproject-Swift.h"
6. Clean and rebuild your Xcode project
Profit
They have open sourced their animation engine. Built on top of CADisplayLink, they recommend this mainly if you're looking to do physics based animations that interact with gestures.
https://github.com/storehouse/Advance

iOS - adding a method to NSObject without importing the category .h file

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

Grabbing iPhone screenWidth and Height for reusability

I created a category like so:
#import "UIViewController+Dimensions.h"
#implementation UIView (Dimensions)
- (double) screenWidth2
{
return self.frame.size.width;
}
- (double) screenHeight2
{
return self.frame.size.height;
}
#end
But when I try to call it in my view controller after importing it, I get:
"Use of undeclared identifier screenWidth2;
Is there a better way to grab the screenWidth in one place then every view controller I'm in?
I then did this in my view controller:
_registerButton.frame = CGRectMake(0.0, 0.0, [self screenWidth2] / 2.0 - 1.0, 60.0);
but the app compiles runs and crashes. And the category's .h file is:
#import <UIKit/UIKit.h>
#interface UIViewController (Dimensions)
- (double) screenWidth2;
- (double) screenHeight2;
#end
You need to add
#import "UIViewController+Dimensions.h"
In the code using the category (the file where you call [uiViewControllerInstance screenWidth2])
Have you checked that those variables are declared in the .h? So, they are public.
Also, to use the category, add this:
#import "UIViewController+Dimensions.h"
In the class that have to use the category.

Resources