Hi everyone,
I'm working on a macOS authorization plugin (NameAndPassword) to enable users to log into their system using only MFA, effectively making it passwordless. To achieve this, I'm attempting to store the user's password securely in the Keychain so it can be used when necessary without user input.
However, when I attempt to store the password, I encounter error code -25308. Below is the code I'm using to save the password to the Keychain:
objc code
(void)storePasswordInKeychain:(NSString *)password forAccount:(NSString *)accountName {
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: @"com.miniOrange.nameandpassword",
(__bridge id)kSecAttrAccount: accountName,
(__bridge id)kSecValueData: passwordData,
(__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAfterFirstUnlock
};
// Delete any existing password for the account
OSStatus deleteStatus = SecItemDelete((__bridge CFDictionaryRef)query);
if (deleteStatus == errSecSuccess || deleteStatus == errSecItemNotFound) {
[Logger debug:@"Old password entry deleted or not found."];
} else {
[Logger error:@"Failed to delete existing password: %d", (int)deleteStatus];
}
// Add the new password
OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
if (addStatus == errSecSuccess) {
[Logger debug:@"Password successfully saved to the Keychain."];
} else {
[Logger error:@"Failed to save password: %d", (int)addStatus];
}
}
Any insights or suggestions would be greatly appreciated!
Objective-C
RSS for tagObjective-C is a programming language for writing iOS, iPad OS, and macOS apps.
Posts under Objective-C tag
194 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hi,
I use AudioQueueNewInput() with my very own run loop and dedicated thread. But now it doesn't show the mic alert window.
Howto fix this?
AudioQueueNewInput(&(core_audio_port->record_format),
ags_core_audio_port_handle_input_buffer,
core_audio_port,
ags_core_audio_port_input_run_loop, kCFRunLoopDefaultMode,
0,
&(core_audio_port->record_aq_ref));
Hello,
I am currently working on a project that involves periodically querying OSLog to forward system log entries to a backend. While the functionality generally operates as expected, I have encountered a memory leak in my application. Through testing, I have isolated the issue to the following simplified code example:
#import <Foundation/Foundation.h>
#import <OSLog/OSLog.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
while(1) {
NSError *error = nil;
OSLogStore *logStore = [OSLogStore storeWithScope:OSLogStoreSystem error:&error];
if (!logStore)
NSLog(@"Failed to create log store: %@", error);
sleep(1);
}
}
return 0;
}
When running this example, the application exhibits increasing memory usage, consuming an additional 100 to 200 KB per iteration, depending on whether the build is Debug or Release.
Given that Automatic Reference Counting is enabled, I anticipated that the resources utilized by logStore would be automatically released at the end of each iteration. However, this does not appear to be the case.
Am I using the API wrong?
I would appreciate any insights or suggestions on how to resolve this issue.
Thank you.
I have an iPad app, written in objective-c and distributed through Enterprise developer, as it is not for public use but specific to some large companies.
The app has a local database and works offline
For some functions of the app I need to display images (not edit or cut them, just display them)
Right now there is integrated MWPhotoBrowser viewer, which has not been maintained for almost 10 years, so in addition to warnings in compilation I have to fight with some historical bugs especially on high resolution images. https://github.com/mwaterfall/MWPhotoBrowser
Do you know of a modern and maintained OFFLINE photo viewer? I evaluate both free and paid (maybe an SDK). My needs are very basic
I have found this one https://github.com/TimOliver/TOCropViewController, but I need to disable the photos edit features and especially I would lose the useful feature of displaying multiple images (mwphoto for multiple images showed a gallery)
We are developing remote desktop app on macOS and recently got user's report about unexpected app crash on macOS 15.2 beta.
On macOS 15.2, there's strange app crash on NSDictionary extension method.
We have narrowed down the steps and create the sample code to duplicate this issue.
Create a cocoa app project in objective-c
Try to access [NSNull null] value in NSDictionary
Use specific method name for NSDictionary extension - (long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue;
The console output for the example app is like below, the method pointer seems to be wrong when trying to get value with longLongValueForKey:withDefault: method to a [NSNull null] object.
********* longLongValueForKey: a: 0
********* longLongValueForKey: b: 100
********* longLongValueForKey: c: 0
********* longLongValueForKey:withDefault: a: -1
********* longLongValueForKey:withDefault: b: 100
********* exception: -[NSNull longLongValue]: unrecognized selector sent to instance 0x7ff8528d9760
********* longLongValueForKey:withDefault1: a: -1
********* longLongValueForKey:withDefault1: b: 100
********* longLongValueForKey:withDefault1: c: -1
Please create an objective-c app project and add below code to reproduce this issue.
//
// AppDelegate.m
// DictionaryTest
//
// Created by splashtop on 2024/11/13.
//
#import "AppDelegate.h"
#define IsNullObject(id) ((!id) || [id isKindOfClass:[NSNull class]])
@interface NSDictionary (extension)
(long long)longLongValueForKey:(NSString*)key;
(long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue;
(long long)longLongValueForKey:(NSString*)key withDefault1:(long long)defaultValue;
@end
@interface AppDelegate ()
@property (strong) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
NSDictionary* dict = @{
@"b" : @(100),
@"c" : [NSNull null],
};
@try {
long long a = [dict longLongValueForKey:@"a"];
NSLog(@"********* longLongValueForKey: a: %lld", a);
long long b = [dict longLongValueForKey:@"b"];
NSLog(@"********* longLongValueForKey: b: %lld", b);
long long c = [dict longLongValueForKey:@"c"];
NSLog(@"********* longLongValueForKey: c: %lld", c);
}
@catch(NSException* e) {
NSLog(@"********* exception: %@", e);
}
@try {
long long a = [dict longLongValueForKey:@"a" withDefault:-1];
NSLog(@"********* longLongValueForKey:withDefault: a: %lld", a);
long long b = [dict longLongValueForKey:@"b" withDefault:-1];
NSLog(@"********* longLongValueForKey:withDefault: b: %lld", b);
long long c = [dict longLongValueForKey:@"c" withDefault:-1];
NSLog(@"********* longLongValueForKey:withDefault: c: %lld", c);
}
@catch(NSException* e) {
NSLog(@"********* exception: %@", e);
}
@try {
long long a = [dict longLongValueForKey:@"a" withDefault1:-1];
NSLog(@"********* longLongValueForKey:withDefault1: a: %lld", a);
long long b = [dict longLongValueForKey:@"b" withDefault1:-1];
NSLog(@"********* longLongValueForKey:withDefault1: b: %lld", b);
long long c = [dict longLongValueForKey:@"c" withDefault1:-1];
NSLog(@"********* longLongValueForKey:withDefault1: c: %lld", c);
}
@catch(NSException* e) {
NSLog(@"********* exception: %@", e);
}
}
@end
@implementation NSDictionary (extension)
(long long)longLongValueForKey:(NSString*)key {
long long defaultValue = 0;
id value = [self objectForKey:key];
if (IsNullObject(value) || value == [NSNull null]) {
return defaultValue;
}
if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) {
return [value longLongValue];
}
return defaultValue;
}
(long long)longLongValueForKey:(NSString*)key withDefault:(long long)defaultValue {
id value = [self objectForKey:key];
if (IsNullObject(value) || value == [NSNull null]) {
return defaultValue;
}
if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) {
return [value longLongValue];
}
return defaultValue;
}
(long long)longLongValueForKey:(NSString*)key withDefault1:(long long)defaultValue {
id value = [self objectForKey:key];
if (IsNullObject(value) || value == [NSNull null]) {
return defaultValue;
}
if ([value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[NSString class]]) {
return [value longLongValue];
}
return defaultValue;
}
@end
In Xcode 16, even if Objective-C is selected, the Navigator in the documentation viewer displays Swift information.
I don't know when this bug was introduced, but it's there in the last Xcode 16 betas at least.
I hope as many developers as possible submit this bug to Apple to get their attention.
P.S. Yes, I know there's Dash. For many years, Dash was a much better option than Xcode's built-in viewer. However, in version 5, the Dash developer introduced some unfortunate UI changes that made Xcode a better option to view the documentation in certain cases. Unfortunately, the Dash developer doesn't seem to be interested in user feedback anymore. He's been ignoring suggestions and user requests for years by now.
I have an old Objective-C app that has been running for several years. The last compilation was in February 2024. I just upgraded to Sequoia 15.1.
The app has four subviews on its main view. When I run the app only the subview that was the last one instantiated is visible. I know the other subviews are there, because a random mouse click in one invisible view causes the expected change in the visible view.
What changed in 15.1 to cause this?
This is a post down memory lane for you AppKit developers and Apple engineers...
TL;DR:
When did the default implementation of NSViewController.loadView start making an NSView when there's no matching nib file? (I'm sure that used to return nil at some point way back when...)
If you override NSViewController.loadView and call [super loadView] to have that default NSView created, is it safe to then call self.view within loadView?
I'm refactoring some old Objective-C code that makes extensive use of NSViewController without any use of nibs. It overrides loadView, instantiates all properties that are views, then assigns a view to the view controller's view property. This seems inline with the documentation and related commentary in the header. I also (vaguely) recall this being a necessary pattern when not using nibs:
@interface MyViewController: NSViewController
// No nibs
// No nibName
@end
@implementation MyViewController
- (void)loadView {
NSView *hostView = [[NSView alloc] initWithFrame:NSZeroRect];
self.button = [NSButton alloc...];
self.slider = [NSSlider alloc...];
[hostView addSubview:self.button];
[hostView addSubview:self.slider];
self.view = hostView;
}
@end
While refactoring, I was surprised to find that if you don't override loadView and do all of the setup in viewDidLoad instead, then self.view on a view controller is non-nil, even though there was no nib file that could have provided the view. Clearly NSViewController has realized that:
There's no nib file that matches nibName.
loadView is not overridden.
Created an empty NSView and assigned it to self.view anyways.
Has this always been the behaviour or did it change at some point? I could have sworn that if there as no matching nib file and you didn't override loadView, then self.view would be nil.
I realize some of this behaviour changed in 10.10, as noted in the header, but there's no mention of a default NSView being created.
Because there are some warnings in the header and documentation around being careful when overriding methods related to view loading, I'm curious if the following pattern is considered "safe" in macOS 15:
- (void)loadView {
// Have NSViewController create a default view.
[super loadView];
self.button = [NSButton...];
self.slider = [NSSlider...];
// Is it safe to call self.view within this method?
[self.view addSubview:self.button];
[self.view addSubview:self.slider];
}
Finally, if I can rely on NSViewController always creating an NSView for me, even when a nib is not present, then is there any recommendation on whether one should continue using loadView or instead move code the above into viewDidLoad?
- (void)viewDidLoad {
self.button = [NSButton...];
self.slider = [NSSlider...];
// Since self.view always seems to be non-nil, then what
// does loadView offer over just using viewDidLoad?
[self.view addSubview:self.button];
[self.view addSubview:self.slider];
}
This application will have macOS 15 as a minimum requirement.
I'll describe my crash with an example, looking for some insights into the reason why this is happening.
@objc public protocol LauncherContainer {
var launcher: Launcher { get }
}
@objc public protocol Launcher: UIViewControllerTransitioningDelegate {
func initiateLaunch(url: URL, launchingHotInstance: Bool)
}
@objc final class LauncherContainer: NSObject, LauncherContainer, TabsContentCellTapHandler {
...
init(
...
) {
...
super.init()
}
...
//
// ContentCellTapHandler
//
public func tabContentCellItemDidTap(
tabId: String
) {
...
launcher.initiateNewTabNavigation(
tabId: tabId // Crash happens here
)
}
public class Launcher: NSObject, Launcher, FooterPillTapHandler {
public func initiateNewTabNavigation(tabId: String) {
...
}
}
public protocol TabsContentCellTapHandler: NSObject {
func tabContentCellItemDidTap(
tabId: String,
}
Crash stack last 2 lines are- libswiftCore.dylib swift_unknownObjectRetain libswiftCore.dylib String._bridgeToObjectiveCImpl()
String._bridgeToObjectiveCImpl() gets called when the caller and implementation is in Swift file
I believe due to @objc class LauncherContainer there'd be bridging header generated. Does that mean tabId passed to tabContentCellItemDidTap is a String but the one passed to initiateNewTabNavigation is NSString?
TabId is UUID().uuidString if that helps. Wondering if UUID().uuidString has something to do with this.
Thanks a ton for helping. Please find attached screenshot of the stack trace.
So I was trying to use an NSArrayController to bind the contents of a property , first I tried using NSDictionary and it worked great, here's what I did:
@interface ViewController : NSViewController
@property IBOutlet ArrayController * tableCities;
@end
...
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString* filePath = @"/tmp/city_test.jpeg";
NSDictionary *obj = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": @"NYC",
@"filePath": filePath};
NSDictionary *obj2 = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": @"Chicago",
@"filePath": filePath};
NSDictionary *obj3 = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": @"Little Rock",
@"filePath": filePath};
[_tableCities addObjects:@[obj, obj2, obj3]];
}
@end
Now for an NSPopUpButton, binding the Controller Key to the ArrayController and the ModelKeyPath to "name" works perfectly and the popupbutton will show the cities as I expected.
But now, instead of using an NSDictionary I wanted to use a custom class for these cities along with an NSMutableArray which holds the objects of this custom class. I'm having some trouble going about this.
There are different microphones that can be connected via a 3.5-inch jack or via USB or via Bluetooth, the behavior is the same.
There is a code that gets access to the microphone (connected to the 3.5-inch audio jack) and starts an audio capture session. At the same time, the microphone use icon starts to be displayed. The capture of the audio device (microphone) continues for a few seconds, then the session stops, the microphone use icon disappears, then there is a pause of a few seconds, and then a second attempt is made to access the same microphone and start an audio capture session. At the same time, the microphone use icon is displayed again. After a few seconds, access to the microphone stops and the audio capture session stops, after which the microphone access icon disappears.
Next, we will try to perform the same actions, but after the first stop of access to the microphone, we will try to pull the microphone plug out of the connector and insert it back before trying to start the second session. In this case, the second attempt to access begins, the running part of the program does not return errors, but the microphone access icon is not displayed, and this is the problem. After the program is completed and restarted, this icon is displayed again.
This problem is only the tip of the iceberg, since it manifests itself in the fact that it is not possible to record sound from the audio microphone after reconnecting the microphone until the program is restarted.
Is this normal behavior of the AVFoundation framework? Is it possible to somehow make it so that after reconnecting the microphone, access to it occurs correctly and the usage indicator is displayed? What additional actions should the programmer perform in this case? Is there a description of this behavior somewhere in the documentation?
Below is the code to demonstrate the described behavior.
I am also attaching an example of the microphone usage indicator icon.
Computer description: MacBook Pro 13-inch 2020 Intel Core i7 macOS Sequoia 15.1.
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <AVFoundation/AVFoundation.h>
#include <Foundation/NSString.h>
#include <Foundation/NSURL.h>
AVCaptureSession* m_captureSession = nullptr;
AVCaptureDeviceInput* m_audioInput = nullptr;
AVCaptureAudioDataOutput* m_audioOutput = nullptr;
std::condition_variable conditionVariable;
std::mutex mutex;
bool responseToAccessRequestReceived = false;
void receiveResponse()
{
std::lock_guard<std::mutex> lock(mutex);
responseToAccessRequestReceived = true;
conditionVariable.notify_one();
}
void waitForResponse()
{
std::unique_lock<std::mutex> lock(mutex);
conditionVariable.wait(lock, [] { return responseToAccessRequestReceived; });
}
void requestPermissions()
{
responseToAccessRequestReceived = false;
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted)
{
const auto status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
std::cout << "Request completion handler granted: " << (int)granted << ", status: " << status << std::endl;
receiveResponse();
}];
waitForResponse();
}
void timer(int timeSec)
{
for (auto timeRemaining = timeSec; timeRemaining > 0; --timeRemaining)
{
std::cout << "Timer, remaining time: " << timeRemaining << "s" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
bool updateAudioInput()
{
[m_captureSession beginConfiguration];
if (m_audioOutput)
{
AVCaptureConnection *lastConnection = [m_audioOutput connectionWithMediaType:AVMediaTypeAudio];
[m_captureSession removeConnection:lastConnection];
}
if (m_audioInput)
{
[m_captureSession removeInput:m_audioInput];
[m_audioInput release];
m_audioInput = nullptr;
}
AVCaptureDevice* audioInputDevice = [AVCaptureDevice deviceWithUniqueID: [NSString stringWithUTF8String: "BuiltInHeadphoneInputDevice"]];
if (!audioInputDevice)
{
std::cout << "Error input audio device creating" << std::endl;
return false;
}
// m_audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioInputDevice error:nil];
// NSError *error = nil;
NSError *error = [[NSError alloc] init];
m_audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioInputDevice error:&error];
if (error)
{
const auto code = [error code];
const auto domain = [error domain];
const char* domainC = domain ? [domain UTF8String] : nullptr;
std::cout << code << " " << domainC << std::endl;
}
if (m_audioInput && [m_captureSession canAddInput:m_audioInput]) {
[m_audioInput retain];
[m_captureSession addInput:m_audioInput];
}
else
{
std::cout << "Failed to create audio device input" << std::endl;
return false;
}
if (!m_audioOutput)
{
m_audioOutput = [[AVCaptureAudioDataOutput alloc] init];
if (m_audioOutput && [m_captureSession canAddOutput:m_audioOutput])
{
[m_captureSession addOutput:m_audioOutput];
}
else
{
std::cout << "Failed to add audio output" << std::endl;
return false;
}
}
[m_captureSession commitConfiguration];
return true;
}
void start()
{
std::cout << "Starting..." << std::endl;
const bool updatingResult = updateAudioInput();
if (!updatingResult)
{
std::cout << "Error, while updating audio input" << std::endl;
return;
}
[m_captureSession startRunning];
}
void stop()
{
std::cout << "Stopping..." << std::endl;
[m_captureSession stopRunning];
}
int main()
{
requestPermissions();
m_captureSession = [[AVCaptureSession alloc] init];
start();
timer(5);
stop();
timer(10);
start();
timer(5);
stop();
}
For a personal project, I have been writing some library to interface the CoreBluetooth API with the go language. Because of what it does, that library is written in objective-C with ARC disabled.
One function I had to write takes a memory buffer (allocated with malloc() on the go side), creates an NSData object out of it to pass the data to the writeValue:forCharacteristic:type: CoreBluetooth method, and then releases the NSData as well as the original memory buffer:
void Write(CBPeripheral *p, CBCharacteristic *c, void *bytes, int len) {
NSData *data = [NSData dataWithBytesNoCopy:bytes length:len freeWhenDone:true];
[p writeValue:data forCharacteristic:c type:CBCharacteristicWriteWithoutResponse];
[data release];
}
One thing I noticed is that the retainCount for data increases during the writeValue:forCharacteristic:type: API call. It is 1 before, and 2 after. This is surprising to me, because the documentation says "This method copies the data passed into the data parameter, and you can dispose of it after the method returns."
I suspects this results in a memory leak. Am I missing something here ?
I have an NSMutableArray defined as a property in my ViewController class:
@interface ViewController ()
@property NSMutableArray *tableCities;
@end
When the "Add" button is clicked, a new city is added:
NSString* filePath = @"/tmp/city_test.jpeg";
NSDictionary *obj = @{@"image": [[NSImage alloc] initByReferencingFile:filePath],
@"name": @"testCity",
@"filePath": filePath};
[_tableCities addObject: obj];
Okay, this is fine, it is adding a new element to this NSMutableArray, now what I want is to somehow bind the "name" field of each city to my NSPopUpButton.
So in storyboard I created an NSArrayController and tried to set its "Model Key Path" to my NSMutableArray as shown below:
Then I tried to bind the NSPopUpButton to the NSArrayController as follows:
but it doesn't work either, a city is added but the NSPopUpButton isn't displaying anything, what gives?
In genealogy software, I have an NSView that displays a family tree where each person is in a subview. Before Sequoia, the subviews would draw in the order I add them to the parent NSView. For some reason, Sequoia calls drawRect in reverse order.
For example, a tree with cells for son, father, and mother used to be drawn in that order, but Sequoia draws them as mother, father, and son.
For static cell placement it would not matter, but these trees dynamically adjust as users change data or expand and contract branches from the tree. Drawing them in the wrong order messes up all the logic and many trees are corrupted.
Has the new drawing order been implemented for some reason and can it be changed? Is it documented?
underlying Objective-C module 'FirebaseSharedSwift' not found
aymodazhnyneylcscdggrsgjocui/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FirebaseSharedSwift.build/Objects-normal/x86_64/FirebaseSharedSwift.private.swiftinterface:5:19: underlying Objective-C module 'FirebaseSharedSwift' not found
Command SwiftCompile failed with a nonzero exit code
Hello everyone,
I'm working on an iOS application using Objective-C and UITabBarController. My app has more than 5 tabs, so the additional tabs are placed under the "More" tab. However, I've encountered an issue specific to iOS 18 where the first item in the "More" tab does not show up properly. This issue does not occur in iOS 17 or earlier versions.
Here's my setup method:
(void)mainTabbarSetUp {
NSMutableArray *tabItemArray = [NSMutableArray array];
UIViewController *viewController1, *viewController2, *viewController3, *viewController4, *viewController5, *viewController6, *viewController7;
UINavigationController *navviewController1, *navviewController2, *navviewController3, *navviewController4, *navviewController5, *navviewController6, *navviewController7;
viewController1 = [[UIViewController alloc] init];
navviewController1 = [[UINavigationController alloc] initWithRootViewController:viewController1];
navviewController1.tabBarItem.title = @"Watch List";
navviewController1.tabBarItem.image = [UIImage imageNamed:@"tab_icn_watchlist"];
[tabItemArray addObject:navviewController1];
// Similarly adding other view controllers...
viewController6 = [[UIViewController alloc] init];
navviewController6 = [[UINavigationController alloc] initWithRootViewController:viewController6];
navviewController6.tabBarItem.title = @"Cancelled";
navviewController6.tabBarItem.image = [UIImage imageNamed:@"tab_icn_cancelled"];
[tabItemArray addObject:navviewController6];
self.mainTabBarController.viewControllers = tabItemArray;
}
What I've Tried:
Verified that each view controller is correctly initialized and assigned to a UINavigationController before being added to the tab array.
Logged the contents of the moreNavigationController to confirm that it contains the correct view controllers.
Tested by reducing the number of view controllers to less than 5, and the issue does not occur.
Ensured that all UINavigationControllers are configured consistently (e.g., translucency, bar style, etc.).
My view controller has this property:
@property NSMutableArray *tableCities;
Whenever I press a button a new city object is added to this array, it consists of a dictionary of NSStrings containing the name and state of the city being added.
Now, I have an NSPopUpButton that I'd like to bind to the city name of all cities in this NSMutableArray, how exactly can I achieve this with the Bindings Inspector?
I understand the mvc thing kinda, theres an array as a model, a tableview as a control, and the interface as a control (right?)
so like, I drag an array controller on to the form display thing, assign a delegate to it the view and app module/header, add data to it and the tableview updates after I add a function to it? in vs the events are in the event browser, do I just copy and paste the code from the tutorial?
how do I add controls and do all the advanced stuff? the documentation on developer.apple.com isnt that detailed, and most books are outdated or n/a since its objective c
tutorials would be nice, some home grown method would be cool too
thank you
unidef warrell yashizzo
For a Cocoa project I have this table view controller:
@interface TableViewController : NSObject <NSTableViewDataSource, NSTableViewDelegate>
@property (nonatomic, strong) NSMutableArray *numbers;
@property (nonatomic, strong) NSMutableArray *letters;
@end
#import "TableViewController.h"
@implementation TableViewController
- (NSMutableArray *)numbers
{
if (!_numbers)
{
_numbers = [NSMutableArray arrayWithArray:@[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10"]];
}
return _numbers;
}
- (NSMutableArray *)letters
{
if (!_letters)
{
_letters = [NSMutableArray arrayWithArray: @[@"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", @"j"]];
}
return _letters;
}
// NSTableViewDataSource Protocol Method
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
return self.numbers.count;
}
// NSTableViewDelegate Protocol Method
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSString *identifier = tableColumn.identifier;
NSTableCellView *cell = [tableView makeViewWithIdentifier:identifier owner:self];
if ([identifier isEqualToString:@"numbers"])
{
cell.textField.stringValue = [self.numbers objectAtIndex:row];
}
else
{
cell.textField.stringValue = [self.letters objectAtIndex:row];
}
return cell;
}
In the storyboard I created a NSTableView and set up the connection, after running it I get what I expected:
okay, cool, but I have a question:
why is this working even though I haven't created a NSTableView as a property for my ViewController or for my TableViewController?
Also, there's another problem, now I want to add a button to this window such that, every time I click it, a new item should be added to this table(for now it can be anything)
So I created a button and a method for this and linked the action to the story board:
-(IBAction) addNewNumber:(id)sender
{
[_numbers addObject:@"1234"];
[_letters addObject:@"testing"];
}
Now, every time I click this button I can see that this method is indeed being called and that indeed IT IS adding a new member to these arrays, the thing is, the table is not being updated, what gives? Any advice on how I can fix this behavior?
I understand we can use MPSImageBatch as input to
[MPSNNGraph encodeBatchToCommandBuffer: ...]
method.
That being said, all inputs to the MPSNNGraph need to be encapsulated in a MPSImage(s).
Suppose I have an machine learning application that trains/infers on thousands of input data where each input has 4 feature channels. Metal Performance Shaders is chosen as the primary AI backbone for real-time use.
Due to the nature of encodeBatchToCommandBuffer method, I will have to create a MTLTexture first as a 2D texture array. The texture has pixel width of 1, height of 1 and pixel format being RGBA32f.
The general set up will be:
#define NumInputDims 4
MPSImageBatch * infBatch = @[];
const uint32_t totalFeatureSets = N;
// Each slice is 4 (RGBA) channels.
const uint32_t totalSlices = (totalFeatureSets * NumInputDims + 3) / 4;
MTLTextureDescriptor * descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatRGBA32Float
width: 1
height: 1
mipmapped: NO];
descriptor.textureType = MTLTextureType2DArray
descriptor.arrayLength = totalSlices;
id<MTLTexture> texture = [mDevice newTextureWithDescriptor: descriptor];
// bytes per row is `4 * sizeof(float)` since we're doing one pixel of RGBA32F.
[texture replaceRegion: MTLRegionMake3D(0, 0, 0, 1, 1, totalSlices)
mipmapLevel: 0
withBytes: inputFeatureBuffers[0].data()
bytesPerRow: 4 * sizeof(float)];
MPSImage * infQueryImage = [[MPSImage alloc] initWithTexture: texture
featureChannels: NumInputDims];
infBatch = [infBatch arrayByAddingObject: infQueryImage];
The training/inference will be:
MPSNNGraph * mInferenceGraph = /*some MPSNNGraph setup*/;
MPSImageBatch * returnImage = [mInferenceGraph encodeBatchToCommandBuffer: commandBuffer
sourceImages: @[infBatch]
sourceStates: nil
intermediateImages: nil
destinationStates: nil];
// Commit and wait...
// Read the return image for the inferred result.
As you can see, the setup is really ad hoc - a lot of 1x1 pixels just for this sole purpose.
Is there any better way I can achieve the same result while still on Metal Performance Shaders? I guess a further question will be: can MPS handle general machine learning cases other than CNN? I can see the APIs are revolved around convolution network, both from online documentations and header files.
Any response will be helpful, thank you.