I am trying from iOS and use it Xamarin Forms..issue is that.i don't know swift at all..
#objc func scanDocument()
{
let testViewController = ViewControllerCamer()
testViewController.delegate = self
present(scannler, animated: true)
}
In Xamarin we need to implement the protocol like following
public class MyDelegate : VNDocumentCameraViewControllerDelegate
{
public override void DidFinish(VNDocumentCameraViewController controller, VNDocumentCameraScan scan)
{
base.DidFinish(controller, scan);
//do something you want
}
public override void DidCancel(VNDocumentCameraViewController controller)
{
base.DidCancel(controller);
}
public override void DidFail(VNDocumentCameraViewController controller, NSError error)
{
base.DidFail(controller, error);
}
}
VNDocumentCameraViewController control = new VNDocumentCameraViewController();
control.Delegate = new MyDelegate();
Related
I created a custom class with function delegation. Is it possible to call the didPlaneUpdate function in ViewController1 by calling the addToPlane () function from ViewController2 ? Below is my code:
// CustomClass.swift:
protocol PlaneDelegate: class {
func didPlaneUpdate()
}
class Plane {
static let shared = Plane()
weak var delegate: PlaneDelegate?
public init() { }
public func addToPlane() {
updatePlane()
}
public func updatePlane() {
delegate?.didPlaneUpdate()
}
}
// ViewController1.swift:
class ViewControllerPlane: UIViewController, PlaneDelegate {
var plane = Plane()
override func viewDidLoad() {
super.viewDidLoad()
plane.delegate = self
}
func didPlaneUpdate() {
print("test updated")
}
// ViewController2.swift:
var plane = Plane()
plane.addToPlane()
or
// ViewController2.swift:
Plane.shared.addToPlane()
It doesn't work.
I'm Korean android developer and new at Swift.
I am migrating my android app to ios, but meet a problem with interface and listener. I don't know how to implement listener to communicate between a custom view and a view controller.
I have a custom view(i.e. MyView) that has two buttons and each has own function.
In Android(with Java), I usually make an listener Interface in MyView and assign two functions inside like void func1( String val1 ) and func2...
public class MyView extends RelativeLayout {
private Button b1, b2;
private String val1, val2;
public interface OnButtonListener {
void onFunc1(String val1);
void onFunc2(String val2);
}
private OnButtonListener onButtonListener;
public void setOnButtonListener( OnButtonListener onButtonListener ) {
this.onButtonListener = onButtonListener;
}
public MyView( Context context, AttributeSet attrs ) {
super( context, attrs );
b1.setOnClickListener( view -> {
if (onButtonListener != null){
onButtonListener.onFunc1( val1 );
}
} );
b2.setOnClickListener( view -> {
if (onButtonListener != null){
onButtonListener.onFunc1( val2 );
}
} );
}
}
public class MyActivity extends Activity {
MyView myView1, myView2;
#Override
protected void onCreate( #Nullable Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
myView1.setOnButtonListener( new MyView.OnButtonListener() {
#Override
public void onFunc1( String val1 ) {
Log.d(TAG, val1);
}
#Override
public void onFunc2( String val2 ) {
Log.d(TAG, val2);
}
} );
myView2.setOnButtonListener( new MyView.OnButtonListener() {
#Override
public void onFunc1( String val1 ) {
// do something1
}
#Override
public void onFunc2( String val2 ) {
// do something2
}
} );
}
}
This code works perfectly as I wanted. So I've tried to apply same pattern into Swift, but I couldn't find any way to do.
below is for swift 4
import Foundation
import UIKit
import SnapKit
protocol OnButtonListener {
func onButton1( _ val1: String )
func onButton2( _ val2: String )
}
class MyView: UIView {
var onButtonListener: OnButtonListener?
var val1 = "abc"
var val2 = "123"
override init( frame: CGRect ) {
super.init( frame: frame )
let b1 = UIButton()
let b2 = UIButton() // i'm using snapkit
b1.addTarget(self, action: #selector(onB1), for: .touchUpInside)
b2.addTarget(self, action: #selector(onB2), for: .touchUpInside)
}
#objc func onB1() {
if onButtonListener != nil {
onButtonListener!.onButton1(val1 )
}
}
#objc func onB2() {
if onButtonListener != nil {
onButtonListener!.onButton2(val2 )
}
}
}
class MyVC : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myView1 = MyView()
let myView2 = MyView()
myView1.onButtonListener = {
// ???
}
myView2.onButtonListener = {
// ???
}
}
}
I don't know how to implement listener in ViewContorller. I've tried same way as Kotlin but I didn't work too. Thank you for reading.
You have to set delegate in your viewcontroller and implement protocol methods in your viewcontroller
class MyVC : UIViewController, OnButtonListener {
override func viewDidLoad() {
super.viewDidLoad()
let myView1 = MyView()
myView1. onButtonListener = self
let myView2 = MyView()
myView2. onButtonListener = self
}
func onButton1( _ val1: String ) {
print(val1)
}
func onButton2( _ val2: String ) {
print(val2)
}
}
**Method 2: ** You can use block as well
class MyView: UIView {
var buttonAction : ((_ value : String) -> Void)? = nil
//.... your code
#objc func onB1() {
if let action = buttonAction {
action("abc")
}
}
#objc func onB2() {
if let action = buttonAction {
action("xyz")
}
}
}
In you ViewController
override func viewDidLoad() {
super.viewDidLoad()
let myView1 = MyView()
myView1.buttonAction = { value in
print(value)
}
}
Update your view controller code as follows:
First confirm your OnButtonListener protocol to UIViewController, and implement protocol method in your view controller.
class MyVC : UIViewController, OnButtonListener {
override func viewDidLoad() {
super.viewDidLoad()
let myView1 = MyView()
// Confirm protocol implementation in current view controller
myView1.onButtonListener = self
let myView2 = MyView()
// Confirm protocol implementation in current view controller
myView2.onButtonListener = self
}
func onButton1( _ val1: String) {
// your code
}
func onButton2( _ val2: String) {
// your code
}
}
I'm trying to set my AssetService as changeObserver, but I get the folowing error:
Error:(8, 14) type 'AssetService' does not conform to protocol 'PHPhotoLibraryChangeObserver'
While photoLibraryDidChange is the only required method. Here's my code:
import UIKit
import Photos
public class AssetService : PHPhotoLibraryChangeObserver {
public init() {
// here I do some other stuff
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self)
}
public func photoLibraryDidChange(changeInstance: PHChange) {
dispatch_async(dispatch_get_main_queue(), {
})
}
}
I think you need to extend from NSObject in order to use it in the PhotoFramework
Therefore you need also to override the init and add super.init()
import UIKit
import Photos
public class AssetService : NSObject, PHPhotoLibraryChangeObserver {
public override init() {
super.init()
// here I do some other stuff
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self)
}
public func photoLibraryDidChange(changeInstance: PHChange) {
dispatch_async(dispatch_get_main_queue(), {
})
}
}
Hope this will solve it
In Swift 3.0 the register actually looks like this now:
func photoLibraryDidChange(_ changeInstance: PHChange) {
DispatchQueue.main.async {
}
}
public override init() {
super.init()
PHPhotoLibrary.shared().register(self)
}
Everything else is the same in Bart Schoon's answer
I have the following code in which I'm trying to force abstraction (abstract class/conformance):
PlayerProtocol:
protocol PlayerProtocol {
func play();
func stop();
func pause();
func getVolume() -> UInt32;
func setVolume(level: UInt32);
func isPaused() -> Bool;
func isStopped() -> Bool;
func onSessionResume();
func onSessionInterupt();
}
BasicPlayer:
class BasicPlayer : PlayerProtocol {
//some variables here..
init() {
//init some variables here..
}
func play() {
fatalError("play() - pure virtual function called.");
}
func stop() {
fatalError("stop() - pure virtual function called.");
}
func pause() {
fatalError("stop() - pure virtual function called.");
}
func getVolume() -> UInt32 {
fatalError("getVolume() - pure virtual function called.");
}
func setVolume(level: UInt32) {
fatalError("setVolume() - pure virtual function called.");
}
func isPaused() -> Bool {
fatalError("isPaused() - pure virtual function called.");
}
func isStopped() -> Bool {
fatalError("isStopped() - pure virtual function called.");
}
func onSessionInterupt() {
fatalError("onSessionInterupt() - pure virtual function called.");
}
func onSessionResume() {
fatalError("onSessionResume() - pure virtual function called.");
}
}
AudioPlayer:
class AudioPlayer : BasicPlayer, PlayerProtocol {
private var device: COpaquePointer = nil;
private var context: COpaquePointer = nil;
private var source: ALuint = 0;
private var buffer: ALuint = 0;
private var interrupted: Bool = false;
private var volume: Float = 50;
override init() {
super.init();
//..
}
deinit {
//..
}
override func play() {
//..
}
override func stop() {
//..
}
override func pause() {
//..
}
override func setVolume(volume: UInt32) {
//..
}
override func getVolume() -> UInt32 {
//..
}
func isPlaying() -> Bool {
//..
}
override func isPaused() -> Bool {
//..
}
override func isStopped() -> Bool {
//..
}
func isAudioPlaying() -> Bool {
return AVAudioSession.sharedInstance().otherAudioPlaying;
}
override func onSessionInterupt() {
self.pause();
}
override func onSessionResume() {
self.play();
}
func setData(buffer: ALuint, source: ALuint) {
self.buffer = buffer;
self.source = source;
}
}
But even though I specified that AudioPlayer implements the PlayerProtocol, it doesn't force me to implement all the member functions like play, stop, etc.. I can remove them and it doesn't complain. It's probably because the super class implements it but I can't figure out how to leave it un-implemented in the super class and allow the derived classes to do the implementation instead.
Basically, BasicPlayer is supposed to be abstract and any class inheriting it must implement "certain" members (not all). OnSessionInterrupt isn't implemented in the derived class. I need it to error.
How can I do this? How can I get it to error at compile time on un-implemented members in the derived classes but not the abstract class?
AudioPlayer is a subclass of a class that already conforms to PlayerProtocol. Because you've implemented all of the methods in the superclass, those implementations are available in your subclass, so you aren't obliged to redeclare them.
It looks to me like you are conceptually abstracting your interface in two separate ways: through a protocol and through an abstract superclass. This might be superfluous? One or the other should be able to serve your purposes.
Hello I'm trying to call a function to show the GameCenter LeaderBoard from an SKScene but I've been unsuccessful. Here is how I call the function from a SKScene.
class Menu: SKScene {
func score(sender:UIButton!) {
GamecenterUtils.sharedGamecenterUtils.showLeaderboardOnViewController(GamecenterUtils(),leaderboardID:"myleaderID")
}
}
I get a compiler error 'GamecenterUtils' is not convertible to UIViewController.
But I do this because GamecenterUtils is my CGGameCenterControllDelegate.
Here is the GamecenterUtils class than handles everything for Game Center:
private let _sharedGamecenterUtils = GamecenterUtils();
class GamecenterUtils : NSObject, GKGameCenterControllerDelegate {
class var sharedGamecenterUtils : GamecenterUtils{
return _sharedGamecenterUtils;
}
override init(){
}
func authenticateLocalUserOnViewController(viewController:UIViewController){
var localPlayer:GKLocalPlayer = GKLocalPlayer.localPlayer();
if (localPlayer.authenticated == false) {
localPlayer.authenticateHandler = {(authViewController, error) -> Void in
if (authViewController != nil) {
viewController.presentViewController(authViewController,animated:false,nil);
}
}
}
else {
println("Already authenticated");
}
}
func reportScore(score:Int,leaderboardID:NSString) {
var scoreReporter:GKScore = GKScore(leaderboardIdentifier:"catchthategg01");
scoreReporter.value = Int64(score);
scoreReporter.context = 0;
GKScore.reportScores([scoreReporter],{(error) -> Void in
if let reportError = error {
println("Unable to report score!\nError:\(error)");
}
else {
println("Score reported successfully!");
}
});
}
func showLeaderboardOnViewController(viewController:UIViewController?, leaderboardID:NSString){
if let containerController = viewController {
var gamecenterController:GKGameCenterViewController = GKGameCenterViewController();
gamecenterController.gameCenterDelegate = self;
gamecenterController.viewState = GKGameCenterViewControllerState.Leaderboards;
gamecenterController.leaderboardIdentifier = "catchthategg01";
viewController?.presentViewController(gamecenterController,animated:false,nil);
}
}
func gameCenterViewControllerDidFinish(_gameCenterViewController: GKGameCenterViewController!){
_gameCenterViewController.dismissViewControllerAnimated(false,nil);
}
}
Thank you for your help.