I want to get UITextInputMode in Swift 2 but UITextInputMode.activeInputModes() crashes.
let x = UITextInputMode.activeInputModes() // crash here
for t in x {
print(t)
}
I was able to work around this bug by using an Objective-C bridge.
Bridge.h
#ifndef Bridge_h
#define Bridge_h
#import "Kludge.h"
#endif
Kludge.h
#ifndef Kludge_h
#define Kludge_h
#import <UIKit/UITextInput.h>
#interface Kludge : NSObject
+ (NSArray<UITextInputMode *> *)activeInputModes;
#end
#endif
Kludge.m
#import "Kludge.h"
#implementation Kludge
+ (NSArray<UITextInputMode *> *)activeInputModes {
return (NSArray<UITextInputMode *> *)[UITextInputMode activeInputModes];
}
#end
From Swift, you can now call Kludge.activeInputModes() and get the correct results.
It is a bug in Xcode 7 as mentioned HERE. Which says:
Summary:
Prior to the Xcode 7 GM, UITextInputMode.activeInputModes() returned
an array of UITextInputMode instances. However, in the Xcode 7 GM, the
method signature in the header file and documentation states that it
returns an array of Strings, which is incorrect. As a result, code
that uses activeInputModes correctly no longer compiles, and
attempting to use activeInputModes in a Playground throws an
exception.
Related
I'm not familiar with Objecticve-C. I'm using it because I want to natively/correctly check if an app is installed on ios. I found the Objective-C snippet to see if an app is installed and understand needing a C-wrapper to basically have unity talk to the Objective-C script (mm file). Just don't understand how to get the C-wrapper to get the Objective-C value I have within my mm script.
// UnityPluginTest-1.mm
//
// Created by OJ on 7/13/16.
//
#import <Foundation/Foundation.h>
#interface SampleClass:NSObject
/* method declaration */
- (BOOL)isFBInstalledX;
#end
#implementation SampleClass
//Objective-C value I want
- (BOOL)isFBInstalledX {
return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"fb://"]];
}
#end
//C-wrapper that talks to Unity
extern "C"
{
bool isFBInstalled(){
// Need to get the Objective C BOOL value from above, my c# script will get this value once retrieved
//return -(Bool) isFBInstalledX value //--this doesn't work
//return ..... // I give up :(
}
}
Got the Answer! - Objective-C to UnityPlugin - App Installed Status
I am inexperienced with Objective-C and this is my first attempt at anything Swift. I Can't get Xcode to compile. ( I may also be missing a necessary line or two, but if I get it to compile, I can usually figure out the rest )
I've been all over docs and getting started, I don't know enough to know the answer if it's there:
http://bustoutsolutions.github.io/siesta/guide/objc/
https://bustoutsolutions.github.io/siesta/api/
My Code:
// MyAPI.swift
import Siesta
import SwiftyJSON
#objc class MyAPI: Service {
internal static let instance = MyAPI(baseURL:"https://api.example.com")
}
// ViewController.mm
#import "ViewController.h"
#import "PlateScanner.h"
#import "Plate.h"
#import "MyProject-swift.h"
...
- (IBAction)callAPI:(id)sender
{
[[MyAPI.instance resource:#"/profile/"] child:#"123"];
}
-(void)resourceChanged: (BOSResource*) resource event: (NSString*) event {
if([event hasPrefix:#"NewData"]) {
NSLog(#"%#",[resource text]);
}
}
...
I get the following 2 errors from ViewController.mm:
1. line starting "[[MyAPI": No visible #interface for 'MyAPI' declares the selector 'resource:'
2. line starting "-(void)reso": Expected a type
From this I understand that my ViewController is not understanding the necessary BOSResource type, but I don't know how to get the swift library imported properly?
Xcode generated code:
//MyProject-swift.h
...
SWIFT_CLASS("_TtC10MyProject5MyAPI")
#interface MyAPI : BOSService
+ (MyAPI * _Nonnull)instance;
#end
...
With Error in line starting "#interf...": Cannot find interface declaration for 'BOSService', superclass of 'MyAPI'
Any help is greatly appreciated!
i'm trying to get the Objection Framework working with Swift (XCode 6.4).
Everything works pretty well beside the macros required for register/inject objects e.g. objection_register
I followed the approach from "Bridging Cocoalumerjack with Swift" to get the macros working with Swift but XCode always complain: Use of undeclared identifier 'initialize' when implementing objectionRegister function in ObjectionSwift.m. Since i'm not to familiar with objective-c i got stuck when looking at the Objection.h initializer methods and trying to figure out whats wrong
Thx for your help!
ObjectionSwift.h
#import <Foundation/Foundation.h>
#interface ObjectionSwift : NSObject
+ (void) objectionRegister(NSString *) name;
#endif
ObjectionSwift.m
#import "ObjectionSwift.h"
#import "Objection.h"
#implementation ObjectionSwift
+ (void) objectionRegister:(NSString *) name {
objection_register_singleton(name)
}
#end
UPDATE
I switched to Typhoon as DI Framework which provides Swift support an works pretty well.
You can use class variable:
class ListingsViewController: UIViewController
{
class var initialize: Bool
{
JSObjection.registerClass(ListingsViewController.self, scope: JSObjectionScopeNormal)
return true
}
}
I started to build an IOS app with the new programming language Swift. I managed to use CocoaPods and was able to successfully create the DDTTYLogger with my CustomLoggerFormatter (Objective-C) in my AppDelegate.swift and append it to the loggers.
var customLoggerFormatter = CustomLoggerFormatter()
var consoleLogger: DDTTYLogger = DDTTYLogger.sharedInstance()
consoleLogger.setLogFormatter(customLoggerFormatter)
DDLog.addLogger(consoleLogger)
But the problem is, that the CocoaLumberjack Library is using preprocessor macros for the logger methods like DDLogVerbose(#"..")
Which is defined in the DDLog.h:
#define DDLogVerbose(frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_VERBOSE, LOG_LEVEL_DEF, LOG_FLAG_VERBOSE, 0, frmt, ##__VA_ARGS__)
Is there any workaround to make preprocessor defines work in Swift? Or did anyone try something similar with more success?
Okay, I just found a solution. Writing an Objective-C Wrapper class calling the preprocessors and offering methods to call it.
Hopefully this will help other people facing the same issues.
I first created a header file:
#interface DDLogWrapper : NSObject
+ (void) logVerbose:(NSString *)message;
+ (void) logError:(NSString *)message;
+ (void) logInfo:(NSString *)message;
#end
With the corresponding implementation:
#import <Foundation/Foundation.h>
#import "DDLogWrapper.h"
// Logging Framework Lumberjack
#import "DDLog.h"
#import "DDASLLogger.h"
#import "DDTTYLogger.h"
// Definition of the current log level
#ifdef DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_ERROR;
#endif
#implementation DDLogWrapper
+ (void) logVerbose:(NSString *)message {
DDLogVerbose(message);
}
+ (void) logError:(NSString *)message {
DDLogError(message);
}
+ (void) logInfo:(NSString *)message {
DDLogInfo(message);
}
#end
Important is to add the DDLogWrapper.h File to the ProjectName-Bridging-Header.h file and then you are able to instantiate in Swift the DDLogWrapper and call the methods logVerbose, logError, logInfo..
With the following code I was able to make a log statement:
DDLogWrapper.logVerbose("TEST");
I created a Swift wrapper for CocoaLumberjack that encapsulates everything nicely.
DDLog.addLogger(DDTTYLogger.sharedInstance())
DDLog.logLevel = .Info
logInfo("Info")
logWarn("Warn")
logDebug("Debug")
logError("Error")
As of 2.0.0beta4, CocoaLumberJack includes a CocoaLumberJack.swift file that makes its integration with Swift projects really easily.
They use a global var defaultDebugLevel to set the DDLogLevel, and you can swift basic precompile macros to customize it to your needs.
#if DEBUG
defaultDebugLevel = DDLogLevel.All
#else
defaultDebugLevel = DDLogLevel.Warning
#endif
DDLog.addLogger(DDTTYLogger.sharedInstance())
DDLogDebug("Debug")
DDLogInfo("Info")
DDLogWarn("Warning")
DDLogVerbose("Verbose")
DDLogError("Error")
Here is my Constants.h:
#import Foundation;
typedef NS_ENUM(NSUInteger, BarcodeType) {
kNormalBarcode,
kNoBarcode,
kGenericBarcode,
kInvalidBarcode,
kComicBarcode
};
#interface Constants : NSObject
#end
And here is a function that uses it:
.h:
#interface Helper : NSObject
- (BarcodeType)barcodeType:(NSString *)barcode;
.m:
#import "Constants.h"
...
- (BarcodeType)barcodeType:(NSString *)barcode
{
return kInvalidBarcode;
}
Why am I getting this warning on my function, and what do I need to change to fix it?
Conflicting return type in implementation of 'getBarcodeType:': 'id' vs 'BarcodeType' (aka 'enum BarcodeType')
This code seemed to work fine with older versions of Xcode.
Thanks!
Check your .h file. My guess is your declaration of the method uses id, which conflicts with your definition in the .m file that returns type BarcodeType. NSEnum values aren't objects, so id isn't valid. You'll want to correct the declaration so the return type matches the implementation.