Identifying if the application is terminating because the system is shutting down - objective-c

I am trying to convert these lines in Objective-C to swift
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender
{
...
NSAppleEventDescriptor* appleEventDesc = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent];
NSAppleEventDescriptor* whyDesc = [appleEventDesc attributeDescriptorForKeyword:kEventParamReason];
OSType why = [whyDesc typeCodeValue];
if (why==kAEShutDown || why==kAERestart || why==kAEReallyLogOut)
they will detect if the app is terminating due to the system shutting down.
I am unable to convert this line
if (why==kAEShutDown || why==kAERestart || why==kAEReallyLogOut)
I guessed something like
let codeValue = whyDescription?.typeCodeValue
if ((codeValue == AEKeyword(kAEShutDown)) ||
(codeValue == AEKeyword(kAERestart)) ||
(codeValue == AEKeyword(kAEReallyLogOut))) {
Is this correct?
or should it be
if ((codeValue == OSType(kAEShutDown)) ||
(codeValue == OSType(kAERestart)) ||
(codeValue == OSType(kAEReallyLogOut))) {
Xcode is compiling it fine, but I am not sure if kAEShutDown, kAERestart, and kAEReallyLogOut are `AEKeywords that can be used there.
I could find no documentation on that, as expected.

Both AEKeyword and OSType are a typealias to FourCharCode. Technically, they are the same type, therefore it does not matter which you use.
However, since typeCodeValue is declared as OSType, then OSType is the logical choice.
Also, it seems the constants are already declared as OSType, therefore there should not be any reason to cast them.

Related

OpenCV BackgroundSubtractor.getBackgroundImage crashes with invalid frame type

I'm using OpenCV in an iOS app via Objective-C wrapper and it works generally fine but an attempt to read a background image from a background subtractor crashes the app:
cv::Ptr<BackgroundSubtractor> backSub = createBackgroundSubtractorMOG2();
for (int i = 0; i < arr.count; i++) { // arr - NSArray of UIImage
Mat mask;
Mat frame = [OpenCVWrapper _matFrom:arr[i]]; // converts UIImage to OpenCV.Mat
backSub->apply(frame, mask); // this works great, I can read the mask and it's valid
}
Mat background;
backSub->getBackgroundImage(background); // this crashes
The error implies that my frame has an invalid format. But in my case, I'm just creating a variable to be used by the getBackgroundImage. I tried to create a new Mat with the expected type CV_8UC1 (and CV_8UC3) with no luck, the app is still crashing with the same error.
libc++abi: terminating with uncaught exception of type cv::Exception: OpenCV(4.3.0) /Volumes/build-storage/build/master_iOS-mac/opencv/modules/video/src/bgfg_gaussmix2.cpp:929: error: (-215:Assertion failed) frameType == CV_8UC1 || frameType == CV_8UC3 || frameType == CV_32FC1 || frameType == CV_32FC3 in function 'getBackgroundImage'
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
Same code works flawlessly in my python test (declare variable and store the background there):
background = backSub.getBackgroundImage()
How should I properly access a background image from createBackgroundSubtractorMOG2 in Objective-C?

Rust Range.contains failed to be inlined/optimized

I was running my code through Clippy and it suggested changing the following:
const SPECIAL_VALUE: u8 = 0; // May change eventually.
pub fn version1(value: u8) -> bool {
(value >= 1 && value <= 9) || value == SPECIAL_VALUE
}
Into
pub fn version2(value: u8) -> bool {
(1..=9).contains(&value) || value == SPECIAL_VALUE
}
Since it is more readable. Unfortunately the resulting assembly output is twice as long, even with optimization level 3. Manually inlining it (2-nestings down), gives almost the same code as version1 and is as efficient.
pub fn manually_inlined(value: u8) -> bool {
(1 <= value && value <= 9) || value == SPECIAL_VALUE
}
If I remove the || value == SPECIAL_VALUE they all resolve with the same (though with 1 more instruction added to decrement the parameter value before a compare). Also if I change SPECIAL_VALUE to something not adjacent to the range they all resolve to same assembly code as version2, which is the reason why I kept it 0 unless I eventually have to change it.
I have a link to Godbolt with the code here: https://rust.godbolt.org/z/bMYzfcYob
Why is the compiler failing to properly inline/optimize version2? Is it an "optimization bug"? Or am I misunderstanding some semantics of Rust, maybe something with the borrowing prevents the optimization, but can't the compiler assume no mutation of value due to the aliasing and referencing rules?
Trying to do the same in C++ suggest, yields the worse option in both cases (https://godbolt.org/z/zahfz65W3)
Edit: Changing the compiler for my C++ version to GCC makes it optimized in both cases.
This was indeed a missed optimization opportunity that has now been corrected in LLVM. https://github.com/rust-lang/rust/issues/90609#issuecomment-1046037263 .

More efficient way to write conditionals with lots of OR operators

How can I (more) efficiently write out an if / else conditional that uses the same variable and a huge amount of OR operators?
I've been banging my head on the desk trying to think of a way around writing out all of these OR operators with the same comparison. For loops won't do the trick, and I'm pretty certain that a do / while loop wouldn't do it either. A switch / case might solve this, but I don't think it could condense the code or make it any less tedious to write out.
The example below illustrates my dilemma. The uicollectionview API has a protocol method which is called for each section in the collection and needs a return value for the number of items in that section. Essentially, the protocol method below is a fancy for loop.
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (section == 0 || section == 31) return 7;
else if (section == 1 || section == 26 || section == 27 || section == 28 || section == 29 || section == 30) return 6;
else if (section == 2 || section == 3 || section == 4 || section == 5 || section == 6 || section == 7 || section == 8 || section == 9 || section == 10 || section == 11 || section == 12 || section == 13 || section == 14 || section == 15) return 2;
else if (section == 16 || section == 17 || section == 18 || section == 19 || section == 20 || section == 21 || section == 22 || section == 23 || section == 24 || section == 25) return 4;
else return 7;
}
As you can see in the extremely tedious if / else conditional I've written, it checks for every single section. I feel like I'm missing something - that Objective-C provides a nifty way around this kind of tedious and inefficient conditional writing / checking?
A clean way is to use a switch statement. These are usually implemented with a branching array, so are quite efficient.
switch (section)
{
case 0:
case 31:
return 7;
...
}
And the most efficient of all (branchless) is a lookup-table:
const int nums[]= { 7, 6, 2, 2, 2... };
return nums[section];
switch is probably the right answer, but you can also use shift/mask, something like:
int sectionBit = 0x00000001 << section;
if (sectionBit & 0x80000001) return 7;
if (sectionBit & 0x7c000002) return 6;
etc
The disadvantage of this approach is that it's tedious and error-prone to define the bit constants, but one can sometimes develop the constants by using enums, etc (at the expense of long declaration strings).
A generic approach to this is to use NSArray / NSDictionary to build indexes, something like:
NSArray *sections = #[#3, #5, #27, ...];
if ([sections containsObject:#3]) ...
or
NSDictionary *sections = #{ #5: #27, #7: #23, ... };
int value = [sections[#(section)] intValue]

NSObject description and custom summaries in Xcode

I override object's -(NSString*)description however Xcode always displays error: summary string parsing error in summary field in variables view.
My current implementation is the following:
- (NSString*)description {
return [NSString stringWithFormat:#"<%# %p> x=%f, y=%f", self.class, self, _x, _y];
}
If I type po objectName in console, LLDB shows a fine output as expected, however Xcode and command p objectName always indicate error, so what's the proper debug description format to make summary field work? Worth to notice that the output of "p" command is the same as a summary message that you see in Xcode for instances of Foundation classes.
Update:
As far as I can see from "WWDC 2012 session Debugging in Xcode", custom summaries can be implemented using Custom python script only. -(NSString*)description or -(NSString*)debugDescription methods are not connected anyhow to summary messages. I thought they are because I got an error displayed, but it seems it's a standard message for classes that do not have their own formatters.
I would suggest at least:
- (NSString*)description {
return [NSString stringWithFormat:#"%#; x=%f, y=%f", [super description], _x, _y];
}
So that you're not manually replicating the NSObject default and thereby blocking any non-default behaviour your superclass may have opted to include.
Beyond that, "summary string parsing error" is an lldb error. It's being reported by the debugger only. Per its documentation, po is correct for Objective-C objects; p is for C or C++ objects. So you needn't heed that error — it's essentially just telling you that you used the wrong lldb command.
EDIT: for what it's worth, the method used by CFArray is open source and looks like:
static CFStringRef __CFArrayCopyDescription(CFTypeRef cf) {
CFArrayRef array = (CFArrayRef)cf;
CFMutableStringRef result;
const CFArrayCallBacks *cb;
CFAllocatorRef allocator;
CFIndex idx, cnt;
cnt = __CFArrayGetCount(array);
allocator = CFGetAllocator(array);
result = CFStringCreateMutable(allocator, 0);
switch (__CFArrayGetType(array)) {
case __kCFArrayImmutable:
CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = immutable, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
break;
case __kCFArrayDeque:
CFStringAppendFormat(result, NULL, CFSTR("<CFArray %p [%p]>{type = mutable-small, count = %u, values = (%s"), cf, allocator, cnt, cnt ? "\n" : "");
break;
}
cb = __CFArrayGetCallBacks(array);
for (idx = 0; idx < cnt; idx++) {
CFStringRef desc = NULL;
const void *val = __CFArrayGetBucketAtIndex(array, idx)->_item;
if (NULL != cb->copyDescription) {
desc = (CFStringRef)INVOKE_CALLBACK1(cb->copyDescription, val);
}
if (NULL != desc) {
CFStringAppendFormat(result, NULL, CFSTR("\t%u : %#\n"), idx, desc);
CFRelease(desc);
} else {
CFStringAppendFormat(result, NULL, CFSTR("\t%u : <%p>\n"), idx, val);
}
}
CFStringAppend(result, CFSTR(")}"));
return result;
}
As with the other comments above, I'm willing to gamble that the answer is: Xcode's debugger isn't smart in any sense and definitely isn't smart enough to use the correct po means of getting an Objective-C description; if your object is an uninflected Objective-C object then the debugger isn't going to be able to figure it out.

What would be a good way to pick cache file names for images downloaded from internet?

What would be a good way to pick cache file names for images downloaded from internet for caching purpose to ensure that no matter what the URL is we got valid file name?
We often pick images from the net. It's often useful to store those images in temporary cache so we don't keep downloading the same image again and again.
So I suppose, I would need a cacheFileName. It should be a function of the URL. However, it must not contain special characters like :, /, &
In other words, it has to be a valid file name.
What would be the way to do so?
I can make some my self. Perhaps I can use URLEncode which seems to do just fine. However, I wonder, if there are consideration I missed.
This is the current Code I use:
- (NSString *) URLEncodedString {
NSMutableString * output = [NSMutableString string];
const char * source = [self UTF8String];
int sourceLen = strlen(source);
for (int i = 0; i < sourceLen; ++i) {
const unsigned char thisChar = (const unsigned char)source[i];
if (false && thisChar == ' '){
[output appendString:#"+"];
} else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
(thisChar >= 'a' && thisChar <= 'z') ||
(thisChar >= 'A' && thisChar <= 'Z') ||
(thisChar >= '0' && thisChar <= '9')) {
[output appendFormat:#"%c", thisChar];
} else {
[output appendFormat:#"%%%02X", thisChar];
}
}
return output;
}
It's taken from some great answer in stackOverflow which I have forgotten.
I wonder if the result of this function will always get a valid file name. Does anyone has better file name generator?
If you do proper networking, NSURLCache handles caching of images just fine automatically.
However, I got the feeling that you aren’t really interested in caching, but in (more or less permanently) storing images.
In that case, build a proper model for your app.
Because you don’t tell us what the images you want to be storing are for, I cannot be more helpful than this:
If you’re on iOS 5+/OS X 10.7+, you can use NSAttributeDescription’s allowsExternalBinaryDataStorage setting to have the NSSQLiteStoreType handle naming, creating, retrieving, updating, and deleting the backing files for the image data transparently on your behalf.
If you have to support older OS versions, you can still use external storage through a transient attribute. Your entity description then has to have an attribute for the name of the data-file, though. In that situation, the SHA-1 (available through the CommonCrypto framework) of the image’s data will provide for a good file name.
Aside
If you’ve found that code in an answer on Objective-C, downvote it, and delete that code above:
-[NSString stringByAddingPercentEscapesUsingEncoding:], and CFURLCreateStringByAddingPercentEscapes do exactly what they (or their docs) say.