Converting 'ZXingObjC' (QR Code Library) non-ARC to ARC, have some problems - objective-c

I've never worked with non-ARC before, and I tried ZXingObjC sample project (QR Code Scanner), it's non-ARC project as well as the library.
I started with deleting the autorealese, dealloc etc.
But I've encounter 'retain' and I don't know yet how to handle it.
I'll glad for a hand as it will benefit a lot of us.
Example of 'retain' statements:
if (zxd) {
input =
[ZXCaptureDeviceInput deviceInputWithDevice:zxd
ZXAV(error:nil)];
[input retain];
}
Another One:
- (void)setCaptureDevice:(ZXCaptureDevice *)device {
if (device == capture_device) {
return;
}
if(capture_device) {
ZXQT({
if ([capture_device isOpen]) {
[capture_device close];
}});
[capture_device release];
}
capture_device = [device retain];
}
EDIT:
OK, I've been trying to make "EDIT --> Refactor --> Convert to Objective-C ARC", I get:

Another way to use "ZXingOjbC" without convert it to arc projcet:
I use the library by turning off arc when compile it's source code, it works fine when combining both arc and non-arc code in the same project.
use following steps:
put "ZXingObjC" source folder into your project
go to project->Build Phases
select all ZXingObjc files(you can select all at once by pressing shift) then press Enter.
key in "-fno-objc-arc" tell compiler to compile these source code without arc.

OK, what I did is:
Clean all non-ARC old code.
"EDIT --> Refactor --> Convert to Objective-C ARC".
Added missing AudioToolbox.Framework
Project now fully work with ARC.
I'll upload later to github.

Related

React Native NativeModules Empty Object

Trying to create my first npm module in order to determine if a user is on the phone. It's for a React Native app. No matter what I try, the module returns undefined. NativeModules always appears to be an empty object.
Please help! Below is a link to the code. export default RNOnPhoneCall; in index.js will only return undefined. How do I link the functions in ios folder, and export them in index.js? Heads up, android is not up to date yet, only ios.
Link to Github
After snooping around a little, I found out that the Obj-C file isn't added to the Compile Sources in Xcode. Just follow me:
Let's say the file names are: NotchNative.h and NotchNative.m. If the NotchNative.m file is not listed, the files will not be compiled by Xcode hence it needs to be added to the Compile Sources.
Follow the steps in the image and rebuild/run the iOS app again.
It's surely a fault on the Xcode side, as it doesn't happen in case of Swift projects.
Try rebuilding your project. I faced the same issue recently and simply rebuilding resolved it
I was not exporting the method correctly in my iOS file. Here's the solution, along with a link to the final project.
react-native-check-phone-call-status on github
#import "RNCheckPhoneCallStatus.h"
#import "React/RCTLog.h"
#import <AVFoundation/AVAudioSession.h>
#import<CoreTelephony/CTCallCenter.h>
#import<CoreTelephony/CTCall.h>
#implementation RNCheckPhoneCallStatus
RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(get:(RCTResponseSenderBlock)callback)
{
NSString *phoneStatus = #"PHONE_OFF";
CTCallCenter *ctCallCenter = [[CTCallCenter alloc] init];
if (ctCallCenter.currentCalls != nil)
{
NSArray* currentCalls = [ctCallCenter.currentCalls allObjects];
for (CTCall *call in currentCalls)
{
if(call.callState == CTCallStateConnected)
{
phoneStatus = #"PHONE_ON";
}
}
}
callback(#[[NSNull null], phoneStatus]);
}
#end

Privileged Helper Tool within a Swift project

I've created an Xcode project using Swift and a privileged Helper tool using Objective-C. The helper tool works fine within a project which has also been created in Objective-C but it doesn't seem to work within a project created with Swift.
The service itself is being installed. I can see the helper binary within the /Library/PrivilegedHelperTools directory and it's permissions seem to be okay (as well as the user: root). Removing the helper by using launchctl results in re-installing the tool when my project runs (that works as expected) but I can't call any method of the helper tool.
There is neither any exception being thrown nor does any other error occur (at least there seem to be no error as the Console shows nothing as well).
Does anybody know whether this might be an issue with Swift? Because running the same helper tool within another project (written in Objective-C) works well.
I could figure out what the problem was. The helper tool has a main.m wich contains a main() method. I just forgot to fill it with code that creates an instance of my helper class and trigger its listener:
#import <Foundation/Foundation.h>
#import "Helper.h"
int main(int argc, const char * argv[])
{
#autoreleasepool
{
Helper *helper = [[Helper alloc] init];
[helper run];
}
return EXIT_FAILURE;
}
This code causes the Helper instance to run in an infinite loop waiting for incoming connections (from Helper.h):
- (void)run
{
[_listener resume];
[[NSRunLoop currentRunLoop] run];
}
_listener is an instance of NSXPCListener.

Run a scene created with Cocos Builder in cocos2d 2.0, assertion failed

I am following this tutorial to try to run a scene created in Cocos Builder (the tutorial does it with a detailed "cat jump" project, but it's not important for me to do it the same way). I am doing it with cocos2d 2.0 instead of 2.1 as done in the tutorial because with the version 2.1 I get some syntax errors in the CCBReader class, which instead compiles fine with cocos2d 2.0 .
I've followed the guide until the "The Main Event" paragraph, and the app should work. For who doesn't want to follow the guide, this is what I've done so far:
Correctly dragged CCBReader and CCControlExtension folder to the xcode project;
Dragged all the resources from the Cocos Builder project folder to xcode project's resources;
Created a group named "scenes" in which I dragged my MainMenuScene.ccbi file;
Replaced the line of code that pushes the scene with this one:
-
[director_ runWithScene: [CCBReader sceneWithNodeGraphFromFile: #"MainMenuScene.ccbi"]];
I even tried this:
[director_pushScene: [CCBReader sceneWithNodeGraphFromFile: #"MainMenuScene.ccbi"]];
With no luck. When I run the app an assertion fails:
I've found the main reason of the problem, but I don't know how to fix it. The problem is that in a CCBReader method:
+ (CCScene*) sceneWithNodeGraphFromFile:(NSString *)file owner:(id)owner
{
return [CCBReader sceneWithNodeGraphFromFile:file owner:owner parentSize:[[CCDirector sharedDirector] winSize]];
}
This method returns nil, then this other method gets called:
+ (CCScene*) sceneWithNodeGraphFromFile:(NSString *)file owner:(id)owner parentSize:(CGSize)parentSize
{
CCNode* node = [CCBReader nodeGraphFromFile:file owner:owner parentSize:parentSize];
CCScene* scene = [CCScene node];
[scene addChild:node];
return scene;
}
Where node is nil, and this causes the assertion fail, but I don't know why sceneWithNodeGraphFromFile:owner: returns nil, I have a file named "MainMenuScene.ccbi" in my project, and it's also copied into the app the bundle, so I don't see a reason for this method to return nil. I would really appreciate if someone could show me how to fix this problem, or to show me some alternative way to import a Cocos Builder scene into a cocos2d 2.0 project.
put a breakpoint on this line:
CCNode* node = [CCBReader nodeGraphFromFile:file owner:owner parentSize:parentSize];
then look at all of the variables in the variable view then step into that method, you will see why that is returning nil, probably wrong file path, or wrong type, URL for path etc
Ramy, seens like the file isn`t compiled in your project. check if the file "MainMenuScene.ccbi" is on your Bundle Resources.
You can check it in your project > Build Phases > Copy Bundle Resources...
Or you can select the file in your project tree and check "Target Membership" on right panel (Utilities)
It turned out that I forgot to add the directory "ccbResources" from the Cocos Builder project to xcode. Now with this folder added the entire project works.

Foundation tool OS X Service, Garbage Collection, MacRuby: why my NSRunLoop won't loop in acceptInputForMode:beforeDate:?

I'm writing an OS X Service with MacRuby. It upcases the selected text. It mostly works, but… well, here's all of it:
#!/usr/local/bin/macruby
# encoding: UTF-8
framework 'Foundation'
framework 'AppKit'
class KCUpcase
def upcase(pasteboard, userData: s_userdata, error: s_error)
incoming_string = pasteboard.stringForType "public.utf8-plain-text"
outgoing_string = incoming_string.upcase
pasteboard.clearContents
pasteboard.setString(outgoing_string, forType: "public.utf8-plain-text")
end
end
NSLog "Starting…"
NSRegisterServicesProvider(KCUpcase.new, "Upcase")
NSLog "Registered…"
NSRunLoop.currentRunLoop\
.acceptInputForMode(NSDefaultRunLoopMode,
beforeDate:NSDate.dateWithTimeIntervalSinceNow(10.0))
NSLog "Done."
It's just a Foundation tool, not part of an Application.
Now, see the NSRunLoop… line? That doesn't really work. The program exits imediately. I suppose the loop runs once and then exits. Anyhoo, the fact is that it's definititely not waiting 10s for input. So, here's what I did instead:
NSRunLoop.currentRunLoop.runUntilDate NSDate.dateWithTimeIntervalSinceNow(60.0)
And that works, but naturally the program sticks around for 60s, and it's a kludge. So I implemented the whole thing in Objective C (Including KCUpcase, which is not shown). And… it works. With manual memory management. Once I switch to GC (-fobjc-gc-only), it exits imediately same as the MacRuby version.
#import <Foundation/Foundation.h>
#import "KCUpcase.h"
int main (int argc, const char * argv[]) {
NSLog(#"Starting…");
NSRegisterServicesProvider([[KCUpcase alloc] init], #"KCUpcase");
NSLog(#"Registered…");
[[NSRunLoop currentRunLoop]
acceptInputForMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:10.0]];
NSLog(#"Done.");
return 0;
}
But, alas, the fix is easy: because this is a Foundation tool (not an NSApplication), it seems I have to start GC manually by calling objc_startCollectorThread. Here:
#import <objc/objc-auto.h>
// ...
NSLog(#"Starting…");
objc_startCollectorThread();
NSRegisterServicesProvider([[KCUpcase alloc] init], #"KCUpcase");
// ...
Ok, but what's up with MacRuby then? Let's throw it into the mix:
#import <MacRuby/MacRuby.h>
// ...
NSLog(#"Starting…");
objc_startCollectorThread(); // This magic stops working once we add MacRuby
[[MacRuby sharedRuntime] evaluateString: #"$stderr.puts 'hi from macruby'"];
NSRegisterServicesProvider([[KCUpcase alloc] init], #"KCUpcase");
// ...
And, again, it's not waiting in the loop. And, again, ussing the runUntilDate: kludge instead of acceptInputForMode:beforeDate: works:
NSLog(#"Starting…");
[[MacRuby sharedRuntime] evaluateString: #"$stderr.puts 'hi from macruby'"];
NSRegisterServicesProvider([[KCUpcase alloc] init], #"KCUpcase");
NSLog(#"Registered…");
// Hmmm…
[[NSRunLoop currentRunLoop]
runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]];
NSLog(#"Done.");
return 0;
So, I suppose I'm missing something terribly obvious. Please enlighten me.
And by the way, the full MacRuby version of the project is available here (download) with a Rake task that'll build and install it in ~/Library/Services. Then you need to enable its checkbox in Services in the Keyboard Preference Pane (once).
(or git clone git://gist.github.com/537075.git)
Aside: Interestingly, I tried calling NSLog inside the MacRuby string, and it raised NoMethodError. What gives?
It's a bit weird but here is a workaround:
framework 'Foundation'
framework 'AppKit'
class KCUpcase
def upcase(pasteboard, userData: s_userdata, error: s_error)
incoming_string = pasteboard.stringForType "public.utf8-plain-text"
outgoing_string = incoming_string.upcase
pasteboard.clearContents
pasteboard.setString(outgoing_string, forType: "public.utf8-plain-text")
end
end
puts "Starting…"
NSRegisterServicesProvider(KCUpcase.new, "Upcase")
puts "Registered…"
later = NSDate.dateWithTimeIntervalSinceNow(5)
NSRunLoop.currentRunLoop.runUntilDate later
puts "Done"
Basically, you need to define the timestamp before you dispatch the runloop request otherwise the main loop exists before getting the instruction. As you spotted, this is not really a MacRuby bug but still, hopefully that helps.
acceptInputForMode:beforeDate: only runs the loop once. As soon as any input (other than a timer) is processed, it exits. runUntilDate: however continues running the loop until the date is reached.

imagepicker controller shows error when build for iphone simulator 3.0

I am developing an application which uses both video recording and photo shoting.So i want to show buttons according to os for this i implement these methods.It's working fine when i build for OS 3.1 but when i build for OS 3.0 it shows errors
here are the methods
if ([self videoRecordingAvailable])
{
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.allowsImageEditing = YES;
imagePickerController.allowsEditing = YES;
imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh;
imagePickerController.videoMaximumDuration = 60.0f; // Length for video recording in seconds
imagePickerController.mediaTypes = [NSArray arrayWithObjects:#"public.movie", nil];
imagePickerController.showsCameraControls=YES;
[self.navigationController presentModalViewController:imagePickerController animated:YES];
}
- (BOOL) videoRecordingAvailable
{
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) return NO;
return [[UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera] containsObject:#"public.movie"];
}
the errors are
error: request for member 'allowsEditing' in something not a structure or union
error: request for member 'videoQuality' in something not a structure or union
error: 'UIImagePickerControllerQualityTypeHigh' undeclared (first use in this function)
(Each undeclared identifier is reported only once for each function it appears in.)
error: request for member 'videoMaximumDuration' in something not a structure or union
error: request for member 'showsCameraControls' in something not a structure or union
how do i solve this issue?
The problem is that the video capture has been added in 3.1, which means that the image picker from 3.0 does not support any of the video properties and methods (see the documentation and pay attention to the Availability sections).
As for the solution, I guess you could try using the message syntax instead of the dot syntax:
[picker setShowsCameraControls:YES];
This will give you warnings though (when compiled for 3.0 and older), and you have to be careful not to do it on older devices, because you’ll get an unknown selector exception. Or you can call the selector dynamically, which will get rid of the warnings and you can also check if the selector is supported first:
SEL msg = #selector(setShowsCameraControls:);
if ([picker respondsToSelector:msg])
[picker performSelector…];
There are already several questions about writing for different OS versions.
Responding to comments: I think the main problem is that you are blindly pasting the code without understading it. Don’t do that. Sit and think about what the code does, until you understand each and every line. Now to explain your problem more thoroughly:
The Image Picker in 3.0 has no video controls, since it can’t record video. Therefore when you try to compile a code such as picker.showsCameraControls, the compiler complains: There is no showsCameraControls property in the Image Picker class, that has only been added in 3.1.
But there is a way around that, you can use the message syntax ([foo setBar:…]) instead of the dot syntax (foo.bar=…). If the foo object has no setBar method, the compiler will warn you, but the code will compile. Now let’s use the message syntax to set the camera controls:
[picker setShowsCameraControls:YES];
When you compile this code for 3.1, it will compile without warning and run without error. When you compile for 3.0, you will get a warning from the compiler and if you run the code, it will fail (since there really is no showsCameraControls property). But that is not a problem, since you can only decide to run the fragile code if the OS supports it:
BOOL videoSupported = [picker respondsToSelector:#selector(setShowsCameraControls:)];
if (videoSupported) {
[picker setShowsCameraControls:YES];
// set all the other video properties
} else {
// do what makes sense without video support
}
This will work, but you’ll still get compiler warnings on 3.0. Now it depends on your default build target. If you build for 3.1, the warnings will disappear and the code should work on 3.0 just fine.