diff --git a/core/src/cz/nic/tablexia/menu/user/UserMenu.java b/core/src/cz/nic/tablexia/menu/user/UserMenu.java
index acf839fff72a612f22b6deec11a64623a9c244ff..eeb054ddaec965af9d94162c227fe5f93e4a42f0 100644
--- a/core/src/cz/nic/tablexia/menu/user/UserMenu.java
+++ b/core/src/cz/nic/tablexia/menu/user/UserMenu.java
@@ -188,16 +188,15 @@ public class UserMenu extends AbstractMenu {
             final UserMenuQrCodeSelectBoxItemGroup qrCodeSync = new UserMenuQrCodeSelectBoxItemGroup() {
                 @Override
                 public void performAction() {
+                    //Close if qr code scanner is active
+                    if(Tablexia.getQRCodeScanner().isCameraPreviewActive()) return;
+
                     //TODO Draw the magnifier and open the camera
                     //showSyncQrDialog() //probably ?
-
                     Tablexia.getQRCodeScanner().setQRCodeListener(new QRCodeScanner.QRCodeListener() {
                         @Override
-                        public void onCodeScanned(String data) {
+                        public void onCodeScanned(final String data) {
                             Tablexia.getQRCodeScanner().disableScanning();
-                            Tablexia.getQRCodeScanner().stopCameraPreview();
-                            Tablexia.getQRCodeScanner().removeQRCodeListener();
-
                             Pattern pattern = Pattern.compile(CODE_REGEX);
                             Matcher matcher = pattern.matcher(data);
 
@@ -205,6 +204,9 @@ public class UserMenu extends AbstractMenu {
                                 String uuid = matcher.group(1);
                                 runSyncWork(uuid);
                             }
+
+                            Tablexia.getQRCodeScanner().stopCameraPreview();
+                            Tablexia.getQRCodeScanner().removeQRCodeListener();
                         }
                     });
 
diff --git a/core/src/cz/nic/tablexia/util/ui/QRCodeScanner.java b/core/src/cz/nic/tablexia/util/ui/QRCodeScanner.java
index 86d15b5a4787e3b183f525dfff4400f449297b61..5b620e128a1df14d146f410b6907f195cc7888b3 100644
--- a/core/src/cz/nic/tablexia/util/ui/QRCodeScanner.java
+++ b/core/src/cz/nic/tablexia/util/ui/QRCodeScanner.java
@@ -1,5 +1,9 @@
 package cz.nic.tablexia.util.ui;
 
+import com.badlogic.gdx.Gdx;
+
+import cz.nic.tablexia.util.Log;
+
 /**
  * Created by drahomir on 10/5/16.
  */
@@ -10,6 +14,7 @@ public abstract class QRCodeScanner {
 
     private QRCodeListener listener;
     private boolean scanningEnabled = false;
+    private boolean cameraPreviewActive = false;
 
     public void enableScanning() {
         scanningEnabled = true;
@@ -23,6 +28,10 @@ public abstract class QRCodeScanner {
         return scanningEnabled;
     }
 
+    public boolean isCameraPreviewActive() {
+        return cameraPreviewActive;
+    }
+
     public void setQRCodeListener(QRCodeListener listener) {
         this.listener = listener;
     }
@@ -31,15 +40,44 @@ public abstract class QRCodeScanner {
         this.listener = null;
     }
 
-    public synchronized void onCodeScanned(String data) {
+    public synchronized void onCodeScanned(final String data) {
+        if(!isScanningEnabled()) return;
+
         if(listener != null) {
-            listener.onCodeScanned(data);
+            Gdx.app.postRunnable(new Runnable() {
+                @Override
+                public void run() { listener.onCodeScanned(data); }
+            });
+        }
+    }
+
+    public void startCameraPreview() {
+        if(isCameraPreviewActive()) {
+            Log.info(getClass(), "Camera preview is already active. Cannot start it again!");
+            return;
         }
+
+        Log.info(getClass(), "Starting Camera Preview!");
+
+        cameraPreviewActive = true;
+        onCameraPreviewStarted();
+    }
+
+    public void stopCameraPreview() {
+        if(!isCameraPreviewActive()) {
+            Log.info(getClass(), "Camera preview is not running. Cannot stop it!");
+            return;
+        }
+
+        Log.info(getClass(), "Stopping Camera Preview");
+
+        onCameraPreviewStopped();
+        cameraPreviewActive = false;
     }
 
     /* ABSTRACT METHODS */
     public abstract boolean isCameraAccessible();
 
-    public abstract void startCameraPreview();
-    public abstract void stopCameraPreview();
+    public abstract void onCameraPreviewStarted();
+    public abstract void onCameraPreviewStopped();
 }
diff --git a/ios/src/cz/nic/tablexia/IOSQRCodeScanner.java b/ios/src/cz/nic/tablexia/IOSQRCodeScanner.java
index 7ff4853d208404e5554ce61a240435731ea9d943..57f8876ec3ace89ccaa40a2a4760696cc757f3d4 100644
--- a/ios/src/cz/nic/tablexia/IOSQRCodeScanner.java
+++ b/ios/src/cz/nic/tablexia/IOSQRCodeScanner.java
@@ -13,22 +13,25 @@ import org.robovm.apple.avfoundation.AVCaptureOutput;
 import org.robovm.apple.avfoundation.AVCaptureSession;
 import org.robovm.apple.avfoundation.AVCaptureVideoOrientation;
 import org.robovm.apple.avfoundation.AVCaptureVideoPreviewLayer;
+import org.robovm.apple.avfoundation.AVLayerVideoGravity;
 import org.robovm.apple.avfoundation.AVMediaType;
 import org.robovm.apple.avfoundation.AVMetadataObject;
 import org.robovm.apple.avfoundation.AVMetadataObjectType;
 import org.robovm.apple.dispatch.DispatchQueue;
+import org.robovm.apple.dispatch.DispatchQueueAttr;
 import org.robovm.apple.foundation.NSArray;
 import org.robovm.apple.foundation.NSErrorException;
+import org.robovm.apple.uikit.UIApplication;
+import org.robovm.apple.uikit.UIInterfaceOrientation;
 import org.robovm.apple.uikit.UIView;
+import org.robovm.apple.uikit.UIViewController;
 
 import java.util.Arrays;
 
 import cz.nic.tablexia.util.ui.QRCodeScanner;
 
-/**
- * Created by drahomir on 10/5/16.
- */
 public class IOSQRCodeScanner extends QRCodeScanner {
+    private static final String DISPATCH_QUEUE_NAME = "qrCodeQueue";
 
     private class CaptureMetadataOutputDelegate extends AVCaptureMetadataOutputObjectsDelegateAdapter{
         private IOSQRCodeScanner qrCodeScanner;
@@ -39,14 +42,14 @@ public class IOSQRCodeScanner extends QRCodeScanner {
 
         @Override
         public void didOutputMetadataObjects(AVCaptureOutput captureOutput, NSArray<AVMetadataObject> metadataObjects, AVCaptureConnection connection) {
-            if(!isScanningEnabled()) return;
-
             if(metadataObjects != null && metadataObjects.size() > 0) {
                 AVMetadataObject data = metadataObjects.get(0);
                 if(data.getType() == AVMetadataObjectType.QRCode) {
                     //Found QR Code TODO - change data.toString()
                     qrCodeScanner.onCodeScanned(data.toString());
                 }
+
+                metadataObjects.dispose();
             }
         }
     }
@@ -59,13 +62,12 @@ public class IOSQRCodeScanner extends QRCodeScanner {
 
     private CaptureMetadataOutputDelegate captureDelegate;
 
+    private UIViewController cameraPreviewViewController;
     private UIView cameraPreviewView;
     private AVCaptureVideoPreviewLayer videoPreviewLayer;
 
     private DispatchQueue dispatchQueue;
 
-    private boolean cameraPreviewRunning = false;
-
     private void initializeCameraDevice() {
         if(cameraDevice != null) return;
 
@@ -86,12 +88,22 @@ public class IOSQRCodeScanner extends QRCodeScanner {
         return cameraDevice != null;
     }
 
-    @Override
-    public void startCameraPreview() {
-        if(cameraPreviewRunning)  return;
+    private AVCaptureVideoOrientation getOrientationForCameraPreviewLayer() {
+        switch (UIApplication.getSharedApplication().getStatusBarOrientation()) {
+            case LandscapeLeft: return AVCaptureVideoOrientation.LandscapeLeft;
+            case LandscapeRight: return AVCaptureVideoOrientation.LandscapeRight;
+            case Portrait: return AVCaptureVideoOrientation.Portrait;
+            case PortraitUpsideDown: return AVCaptureVideoOrientation.PortraitUpsideDown;
+            default: return AVCaptureVideoOrientation.LandscapeLeft;
+        }
+    }
 
-        cameraPreviewRunning = true;
+    private void updateViewPreviewLayerOrientation() {
+        if(videoPreviewLayer != null ) videoPreviewLayer.getConnection().setVideoOrientation(getOrientationForCameraPreviewLayer());
+    }
 
+    @Override
+    public void onCameraPreviewStarted() {
         captureSession = new AVCaptureSession();
 
         initializeCameraDevice();
@@ -104,8 +116,9 @@ public class IOSQRCodeScanner extends QRCodeScanner {
             e.printStackTrace();
         }
 
+        dispatchQueue = DispatchQueue.create(DISPATCH_QUEUE_NAME, DispatchQueueAttr.Serial());
+
         captureMetadataOutput = new AVCaptureMetadataOutput();
-        dispatchQueue = DispatchQueue.getMainQueue();
         captureDelegate = new CaptureMetadataOutputDelegate();
         captureMetadataOutput.setMetadataObjectsDelegate(captureDelegate, dispatchQueue);
 
@@ -114,61 +127,73 @@ public class IOSQRCodeScanner extends QRCodeScanner {
 
         IOSApplication iosApplication = (IOSApplication) Gdx.app;
 
+        cameraPreviewViewController = new UIViewController() {
+            @Override
+            public void viewWillLayoutSubviews() {
+                super.viewWillLayoutSubviews();
+                updateViewPreviewLayerOrientation();
+            }
+
+            @Override
+            public void willAnimateRotation(UIInterfaceOrientation uiInterfaceOrientation, double v) {
+                //Unforunately this method is deprecated and there isnt binding in RoboVM for these replacements...
+                // - willTransitionToTraitCollection:withTransitionCoordinator:
+                // - viewWillTransitionToSize:withTransitionCoordinator:
+                super.willAnimateRotation(uiInterfaceOrientation, v);
+                updateViewPreviewLayerOrientation();
+            }
+        };
+
         cameraPreviewView = new UIView();
         cameraPreviewView.setBounds(iosApplication.getUIViewController().getView().getBounds());
         cameraPreviewView.setCenter(iosApplication.getUIViewController().getView().getCenter());
 
+        cameraPreviewViewController.setView(cameraPreviewView);
+
         videoPreviewLayer = new AVCaptureVideoPreviewLayer(captureSession);
-        //TODO - Change orientation on device rotate
-        videoPreviewLayer.getConnection().setVideoOrientation(AVCaptureVideoOrientation.LandscapeLeft);
+        videoPreviewLayer.setVideoGravity(AVLayerVideoGravity.ResizeAspectFill);
+        videoPreviewLayer.getConnection().setVideoOrientation(getOrientationForCameraPreviewLayer());
         videoPreviewLayer.setFrame(cameraPreviewView.getBounds());
 
-        //Prevents java objects to get GCed unless captureSession ObjC object gets deallocated!
-        cameraDevice.addStrongRef(captureDeviceInput);
-        captureDeviceInput.addStrongRef(captureDelegate);
-        captureMetadataOutput.addStrongRef(captureDelegate);
-
-        captureDelegate.addStrongRef(captureSession);
-        videoPreviewLayer.addStrongRef(captureSession);
-
         cameraPreviewView.getLayer().addSublayer(videoPreviewLayer);
+
+        iosApplication.getUIViewController().addChildViewController(cameraPreviewViewController);
         iosApplication.getUIViewController().getView().addSubview(cameraPreviewView);
 
         if(!captureSession.isRunning()) captureSession.startRunning();
     }
 
     @Override
-    public void stopCameraPreview() {
-        if(!cameraPreviewRunning) return;
-
-        cameraPreviewRunning = false;
-
+    public void onCameraPreviewStopped() {
         captureSession.stopRunning();
 
         captureSession.removeInput(captureDeviceInput);
         captureSession.removeOutput(captureMetadataOutput);
 
-        captureDeviceInput.removeStrongRef(captureDelegate);
-        captureDeviceInput.release();
+        captureDeviceInput.dispose();
         captureDeviceInput = null;
 
-        captureMetadataOutput.removeStrongRef(captureDelegate);
-        captureMetadataOutput.release();
+        captureMetadataOutput.dispose();
         captureMetadataOutput = null;
 
-        captureDelegate.removeStrongRef(captureSession);
-        captureDelegate.release();
+        captureDelegate.dispose();
         captureDelegate = null;
 
-        videoPreviewLayer.removeStrongRef(captureSession);
         videoPreviewLayer.removeFromSuperlayer();
+        videoPreviewLayer.dispose();
         videoPreviewLayer = null;
 
+        cameraPreviewViewController.removeFromParentViewController();
+        cameraPreviewViewController.dispose();
+        cameraPreviewViewController = null;
+
         cameraPreviewView.removeFromSuperview();
-        cameraPreviewView.release();
+        cameraPreviewView.dispose();
         cameraPreviewView = null;
 
-        captureSession.release();
+        captureSession.dispose();
         captureSession = null;
+
+        dispatchQueue = null;
     }
 }