How to add swizzling method to UIApplication using Swift? - objective-c

I have a code below trying to use swizzling method to UIApplication methods. But the methods not getting called. Meanwhile, I'm trying to add this code into a framework or a private pod.
extension UIApplication {
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
struct SwizzlingSelector {
let original:Selector
let swizzled:Selector
}
// make sure this isn't a subclass
if self !== UIApplication.self {
return
}
dispatch_once(&Static.token) {
let selectors = [
SwizzlingSelector(
original: Selector("application:didFinishLaunchingWithOptions:"),
swizzled: Selector("custome_application:didFinishLaunchingWithOptions:")
),
SwizzlingSelector(
original: Selector("applicationDidEnterBackground:"),
swizzled: Selector("custom_applicationDidEnterBackground:")
)
]
for selector in selectors {
let originalMethod = class_getInstanceMethod(self, selector.original)
let swizzledMethod = class_getInstanceMethod(self, selector.swizzled)
let didAddMethod = class_addMethod(self, selector.original, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, selector.swizzled, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}
}
// MARK: - Method Swizzling
public func custome_application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
print("is here")
return true
}
func custom_applicationDidEnterBackground(application: UIApplication) {
print("is herer")
}
}

I think you should implement this swizzling method in your AppDelegate but not as extension of UIApplication. Cause you swizzle your AppDelegate's methods but not UIApplication's methods.
extension YourAppDelegate {
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
struct SwizzlingSelector {
let original:Selector
let swizzled:Selector
}
// make sure this isn't a subclass
if self !== YourAppDelegate.self {
return
}
dispatch_once(&Static.token) {
let selectors = [
SwizzlingSelector(
original: Selector("application:didFinishLaunchingWithOptions:"),
swizzled: Selector("custome_application:didFinishLaunchingWithOptions:")
),
SwizzlingSelector(
original: Selector("applicationDidEnterBackground:"),
swizzled: Selector("custom_applicationDidEnterBackground:")
)
]
for selector in selectors {
let originalMethod = class_getInstanceMethod(self, selector.original)
let swizzledMethod = class_getInstanceMethod(self, selector.swizzled)
let didAddMethod = class_addMethod(self, selector.original, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, selector.swizzled, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}
}
// MARK: - Method Swizzling
public func custome_application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
print("is here")
return true
}
func custom_applicationDidEnterBackground(application: UIApplication) {
print("is herer")
}
}

Related

Convert Objective-C syntax to Swift 3

What will be the syntax of the following Objective-C method in Swift?
-(id)init
{
Viewcontroller static *vc=nil;
if(!vc)
{
vc=[super init];
return vc;
}
else return vc;
}
Below is the syntax in Swift 3
override init() {
var vc: Viewcontroller? = nil
if vc == nil {
vc = super.init()
return vc!
}
else {
return vc!
}
}

How set title of a WKInterfaceButton?

I'm trying to change the text of a button once it is pressed however it doesn't work. Am i missing something?
i've been trying to figure my problem for hours.
any help would be appreciated.
h. file
#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
#interface InterfaceController : WKInterfaceController
{
IBOutlet WKInterfaceButton*playpausebtn;
}
-(IBAction)play;
#end
m. file
#import "InterfaceController.h"
#import <WatchConnectivity/WatchConnectivity.h>
#interface InterfaceController() <WCSessionDelegate>
#end
#implementation InterfaceController
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
// Configure interface objects here.
}
- (void)willActivate {
[super willActivate];
if ([WCSession isSupported]) {
WCSession *session = [WCSession defaultSession];
session.delegate = self;
[session activateSession];
}
}
- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
[super didDeactivate];
}
-(IBAction)play{
[playpausebtn setTitle:#"sleep"];
}
It is working fine in Swift-3 Xcode-8.1 .
// InterfaceController.swift
// WatchKit Extension
import WatchKit
import Foundation
import WatchConnectivity
class InterfaceController: WKInterfaceController,WCSessionDelegate {
#IBOutlet var textLabel: WKInterfaceLabel!
var session:WCSession?
override func awake(withContext context: Any?) {
super.awake(withContext: context)
// Configure interface objects here.
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
checkSupportOfSession()
changeAttributeOfText()
}
#IBOutlet var buttonOutlet: WKInterfaceButton!
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
func checkSupportOfSession() {
if( WCSession.isSupported() ) {
self.session = WCSession.default()
self.session?.delegate = self
self.session?.activate()
}
}
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
print("session")
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
let message:String = message["textIndex"] as! String
textLabel.setText(message)
print(message)
}
func changeAttributeOfText() {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .left
let font = UIFont.boldSystemFont(ofSize: 12)
let attributes:Dictionary = [NSParagraphStyleAttributeName:paragraphStyle , NSFontAttributeName:font ]
let attributeString:NSAttributedString = NSAttributedString(string: "HELLO", attributes: attributes)
textLabel.setAttributedText(attributeString)
}
//Change the ButtonTitle after click
#IBAction func buttonClicked() {
buttonOutlet.setTitle("textNew")
}}
Demo App

converting setter, getter variable from objective C to swift 2.2

I am facing issues while converting from Objective C to Swift 2.2.. Can anyone help me..??
Here is the code in Objective C
variables declared as
#property (nonatomic, assign) NSInteger currentViewControllerIndex;
#property (nonatomic, getter = isWrapEnabled) BOOL wrapEnabled;
and the variable setting functions in Objective C are
- (void)setWrapEnabled:(BOOL)sWrapEnabled {
wrapEnabled = sWrapEnabled;
[self.view layoutIfNeeded];
}
- (void)setCurrentViewControllerIndex:(NSInteger)curViewControllerIndex {
[self scrollToViewControllerAtIndex:curViewControllerIndex animated:NO];
}
This is how i have written in Swift
var tmpWrapEnabled : Bool = Bool()
internal(set) var wrapEnabled : Bool? {
get {
return tmpWrapEnabled
}
set(newValue) {
if newValue == true {
tmpWrapEnabled = newValue!
self.view.layoutIfNeeded()
}
}
}
var tmpCurrentViewControllerIndex : NSInteger = 0
internal(set) var currentViewControllerIndex : NSInteger? {
get {
return tmpCurrentViewControllerIndex
}
set(newValue) {
tmpCurrentViewControllerIndex = newValue!
}
}
Basically you need only the didSet observers, for the rest the variable behaves as a normal variable.
var wrapEnabled : Bool {
didSet {
if wrapEnabled {
self.view.layoutIfNeeded()
}
}
}
var currentViewControllerIndex : Int {
didSet {
scrollToViewControllerAtIndex(currentViewControllerIndex, animated:false)
}
}
Consider that the observers are not called when the initial value is assigned to the variable.

Objective-C to Swift Conversion Issue

I am trying to convert Apple's own sample code which is only written in Objective-C in to Swift.
This is what's in Objective C
.h
#import UIKit;
#class AVCaptureSession;
#interface AAPLPreviewView : UIView
#property (nonatomic) AVCaptureSession *session;
#end
.m
#import AVFoundation;
#import "AAPLPreviewView.h"
#implementation AAPLPreviewView
+ (Class)layerClass
{
return [AVCaptureVideoPreviewLayer class];
}
- (AVCaptureSession *)session
{
AVCaptureVideoPreviewLayer *previewLayer = (AVCaptureVideoPreviewLayer *)self.layer;
return previewLayer.session;
}
- (void)setSession:(AVCaptureSession *)session
{
AVCaptureVideoPreviewLayer *previewLayer = (AVCaptureVideoPreviewLayer *)self.layer;
previewLayer.session = session;
}
#end
So far, this what I came up for Swift:
import AVFoundation
import UIKit
class CamPreviewLayer: UIView
{
var session: AVCaptureSession!
override class func layerClass() -> AnyClass
{
return AVCaptureVideoPreviewLayer
}
func session() -> AVCaptureSession {
var previewLayer: AVCaptureVideoPreviewLayer = self.layer as! AVCaptureVideoPreviewLayer
return previewLayer.session
}
func setSession(session: AVCaptureSession) {
let previewLayer: AVCaptureVideoPreviewLayer = self.layer as! AVCaptureVideoPreviewLayer
previewLayer.session = session
}
}
My Swift code has 3 errors.
You have to remove var session: AVCaptureSession like this.
import AVFoundation
import UIKit
class AVPreviewView : UIView {
override class func layerClass() -> AnyClass {
return AVCaptureVideoPreviewLayer.self
}
func session () -> AVCaptureSession {
return (self.layer as! AVCaptureVideoPreviewLayer).session
}
func setSession(session : AVCaptureSession) -> Void {
(self.layer as! AVCaptureVideoPreviewLayer).session = session;
(self.layer as! AVCaptureVideoPreviewLayer).videoGravity = AVLayerVideoGravityResizeAspect;
}
}
Hope it help!

How to invoke [self new] in Swift

Here is an UIView extension written in ObjectiveC to easily create view for using Auto-layout:
+(id)autolayoutView
{
UIView *view = [self new];
view.translatesAutoresizingMaskIntoConstraints = NO;
return view;
}
it invokes [self new] so any subclass of UIView can use this method. How can I achieve this in Swift?
OK, this appears to be the solution. The type must have a required initializer with the correct parameter list (in this case no parameters).
class SubView: UIView {
override required init() {
super.init()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
class func autolayoutView() -> UIView {
var view = self()
view.setTranslatesAutoresizingMaskIntoConstraints(false)
return view
}
}
Though both Carrl and Gregory Higley are right with there solutions, including thr remark about the fact that self() needs to use a required init i wanted to post a more general example:
class Human {
var gender = String()
required init() {
self.gender = "any"
}
class func newHuman() -> Human {
return self()
}
}
class Man : Human {
required init() {
super.init()
self.gender = "male"
}
}
var someMan = Man.newHuman()
println(someMan.gender) // male
Inspired by Gregory Higley, i think the solution is here:
extension UIView{
class func autolayoutView() -> UIView {
var view = self()
view.setTranslatesAutoresizingMaskIntoConstraints(false)
return view
}
}
Update for Swift2.1:
extension UIView{
class func autolayoutView() -> UIView {
let view = self.init()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}
}